Changeset 8168 in josm for trunk/src


Ignore:
Timestamp:
2015-04-06T01:43:03+02:00 (9 years ago)
Author:
bastiK
Message:

see #11216 - Limit size of TMS cache (patch by wiktorn)

Location:
trunk/src/org
Files:
10 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/apache/commons

  • trunk/src/org/openstreetmap/josm/Main.java

    r8126 r8168  
    6868import org.openstreetmap.josm.data.UndoRedoHandler;
    6969import org.openstreetmap.josm.data.ViewportData;
     70import org.openstreetmap.josm.data.cache.JCSCacheManager;
    7071import org.openstreetmap.josm.data.coor.CoordinateFormat;
    7172import org.openstreetmap.josm.data.coor.LatLon;
     
    10891090     */
    10901091    public static boolean exitJosm(boolean exit, int exitCode) {
     1092        JCSCacheManager.shutdown();
    10911093        if (Main.saveUnsavedModifications()) {
    10921094            geometry.remember("gui.geometry");
  • trunk/src/org/openstreetmap/josm/gui/bbox/SlippyMapBBoxChooser.java

    r7005 r8168  
    1212import java.util.Arrays;
    1313import java.util.Collections;
     14import java.util.HashMap;
    1415import java.util.HashSet;
    1516import java.util.List;
     17import java.util.Map;
    1618import java.util.Set;
    1719import java.util.concurrent.CopyOnWriteArrayList;
     
    2628import org.openstreetmap.gui.jmapviewer.OsmTileLoader;
    2729import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
     30import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
    2831import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
    2932import org.openstreetmap.gui.jmapviewer.tilesources.MapQuestOpenAerialTileSource;
     
    114117    public static final String RESIZE_PROP = SlippyMapBBoxChooser.class.getName() + ".resize";
    115118
    116     private OsmTileLoader cachedLoader;
     119    private TileLoader cachedLoader;
    117120    private OsmTileLoader uncachedLoader;
    118121
     
    132135        SpringLayout springLayout = new SpringLayout();
    133136        setLayout(springLayout);
    134         TMSLayer.setMaxWorkers();
    135         cachedLoader = TMSLayer.loaderFactory.makeTileLoader(this);
     137
     138        Map<String, String> headers = new HashMap<>();
     139        headers.put("User-Agent", Version.getInstance().getFullAgentString());
     140
     141        cachedLoader = TMSLayer.loaderFactory.makeTileLoader(this, headers);
    136142
    137143        uncachedLoader = new OsmTileLoader(this);
    138         uncachedLoader.headers.put("User-Agent", Version.getInstance().getFullAgentString());
     144        uncachedLoader.headers.putAll(headers);
    139145        setZoomContolsVisible(Main.pref.getBoolean("slippy_map_chooser.zoomcontrols",false));
    140146        setMapMarkerVisible(false);
  • trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java

    r8153 r8168  
    2222import java.util.ArrayList;
    2323import java.util.Collections;
    24 import java.util.HashSet;
     24import java.util.HashMap;
    2525import java.util.LinkedList;
    2626import java.util.List;
    2727import java.util.Map;
    28 import java.util.Map.Entry;
    2928import java.util.Scanner;
    30 import java.util.Set;
    3129import java.util.concurrent.Callable;
    3230import java.util.regex.Matcher;
     
    4240import org.openstreetmap.gui.jmapviewer.AttributionSupport;
    4341import org.openstreetmap.gui.jmapviewer.Coordinate;
    44 import org.openstreetmap.gui.jmapviewer.JobDispatcher;
    4542import org.openstreetmap.gui.jmapviewer.MemoryTileCache;
    46 import org.openstreetmap.gui.jmapviewer.OsmFileCacheTileLoader;
    4743import org.openstreetmap.gui.jmapviewer.OsmTileLoader;
    48 import org.openstreetmap.gui.jmapviewer.TMSFileCacheTileLoader;
    4944import org.openstreetmap.gui.jmapviewer.Tile;
    5045import org.openstreetmap.gui.jmapviewer.interfaces.CachedTileLoader;
    51 import org.openstreetmap.gui.jmapviewer.interfaces.TileClearController;
     46import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
     47import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
    5248import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
    5349import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
     
    6460import org.openstreetmap.josm.data.imagery.ImageryInfo;
    6561import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
     62import org.openstreetmap.josm.data.imagery.TMSCachedTileLoader;
    6663import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
    6764import org.openstreetmap.josm.data.preferences.BooleanProperty;
     
    7673import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
    7774import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    78 import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener;
    7975import org.openstreetmap.josm.io.CacheCustomContent;
    8076import org.openstreetmap.josm.io.OsmTransferException;
     
    109105    //public static final BooleanProperty PROP_DRAW_DEBUG = new BooleanProperty(PREFERENCE_PREFIX + ".draw_debug", false);
    110106    public static final BooleanProperty PROP_ADD_TO_SLIPPYMAP_CHOOSER = new BooleanProperty(PREFERENCE_PREFIX + ".add_to_slippymap_chooser", true);
    111     public static final IntegerProperty PROP_TMS_JOBS = new IntegerProperty("tmsloader.maxjobs", 25);
    112107    public static final StringProperty PROP_TILECACHE_DIR;
    113108
     
    123118
    124119    public interface TileLoaderFactory {
    125         OsmTileLoader makeTileLoader(TileLoaderListener listener);
    126     }
    127 
    128     protected MemoryTileCache tileCache;
     120        TileLoader makeTileLoader(TileLoaderListener listener);
     121        TileLoader makeTileLoader(TileLoaderListener listener, Map<String, String> headers);
     122    }
     123
     124    protected TileCache tileCache;
    129125    protected TileSource tileSource;
    130     protected OsmTileLoader tileLoader;
     126    protected TileLoader tileLoader;
     127
    131128
    132129    public static TileLoaderFactory loaderFactory = new TileLoaderFactory() {
    133130        @Override
    134         public OsmTileLoader makeTileLoader(TileLoaderListener listener) {
    135             String cachePath = TMSLayer.PROP_TILECACHE_DIR.get();
    136             if (cachePath != null && !cachePath.isEmpty()) {
    137                 try {
    138                     OsmFileCacheTileLoader loader;
    139                     loader = new TMSFileCacheTileLoader(listener, new File(cachePath));
    140                     loader.headers.put("User-Agent", Version.getInstance().getFullAgentString());
    141                     return loader;
    142                 } catch (IOException e) {
    143                     Main.warn(e);
    144                 }
     131        public TileLoader makeTileLoader(TileLoaderListener listener, Map<String, String> inputHeaders) {
     132            Map<String, String> headers = new HashMap<>();
     133            headers.put("User-Agent", Version.getInstance().getFullAgentString());
     134            headers.put("Accept", "text/html, image/png, image/jpeg, image/gif, */*");
     135            if (inputHeaders != null)
     136                headers.putAll(inputHeaders);
     137
     138            try {
     139                return new TMSCachedTileLoader(listener, "TMS",
     140                        Main.pref.getInteger("socket.timeout.connect",15) * 1000,
     141                        Main.pref.getInteger("socket.timeout.read", 30) * 1000,
     142                        headers,
     143                        PROP_TILECACHE_DIR.get());
     144            } catch (IOException e) {
     145                Main.warn(e);
    145146            }
    146147            return null;
     148        }
     149
     150        @Override
     151        public TileLoader makeTileLoader(TileLoaderListener listener) {
     152            return makeTileLoader(listener, null);
    147153        }
    148154    };
     
    151157     * Plugins that wish to set custom tile loader should call this method
    152158     */
     159
    153160    public static void setCustomTileLoaderFactory(TileLoaderFactory loaderFactory) {
    154161        TMSLayer.loaderFactory = loaderFactory;
    155162    }
    156 
    157     private Set<Tile> tileRequestsOutstanding = new HashSet<>();
    158163
    159164    @Override
     
    166171            tile.setImage(sharpenImage(tile.getImage()));
    167172        }
    168         tile.setLoaded(true);
     173        tile.setLoaded(success);
    169174        needRedraw = true;
    170175        if (Main.map != null) {
    171176            Main.map.repaint(100);
    172177        }
    173         tileRequestsOutstanding.remove(tile);
    174178        if (Main.isDebugEnabled()) {
    175179            Main.debug("tileLoadingFinished() tile: " + tile + " success: " + success);
    176         }
    177     }
    178 
    179     private static class TmsTileClearController implements TileClearController, CancelListener {
    180 
    181         private final ProgressMonitor monitor;
    182         private boolean cancel = false;
    183 
    184         public TmsTileClearController(ProgressMonitor monitor) {
    185             this.monitor = monitor;
    186             this.monitor.addCancelListener(this);
    187         }
    188 
    189         @Override
    190         public void initClearDir(File dir) {
    191         }
    192 
    193         @Override
    194         public void initClearFiles(File[] files) {
    195             monitor.setTicksCount(files.length);
    196             monitor.setTicks(0);
    197         }
    198 
    199         @Override
    200         public boolean cancel() {
    201             return cancel;
    202         }
    203 
    204         @Override
    205         public void fileDeleted(File file) {
    206             monitor.setTicks(monitor.getTicks()+1);
    207         }
    208 
    209         @Override
    210         public void clearFinished() {
    211             monitor.finishTask();
    212         }
    213 
    214         @Override
    215         public void operationCanceled() {
    216             cancel = true;
    217180        }
    218181    }
     
    226189     *
    227190     * @param monitor
    228      * @see MemoryTileCache#clear()
    229191     * @see OsmFileCacheTileLoader#clearCache(org.openstreetmap.gui.jmapviewer.interfaces.TileSource, org.openstreetmap.gui.jmapviewer.interfaces.TileClearController)
    230192     */
     
    232194        tileCache.clear();
    233195        if (tileLoader instanceof CachedTileLoader) {
    234             ((CachedTileLoader)tileLoader).clearCache(tileSource, new TmsTileClearController(monitor));
     196            ((CachedTileLoader)tileLoader).clearCache();
    235197        }
    236198    }
     
    416378        currentZoomLevel = getBestZoom();
    417379
    418         tileCache = new MemoryTileCache();
    419 
    420         tileLoader = loaderFactory.makeTileLoader(this);
    421         if (tileLoader == null) {
     380        Map<String, String> headers = null;
     381        if (tileSource instanceof TemplatedTMSTileSource) {
     382            headers = (((TemplatedTMSTileSource)tileSource).getHeaders());
     383        }
     384
     385        // FIXME: tileCache = new MemoryTileCache();
     386        tileLoader = loaderFactory.makeTileLoader(this, headers);
     387        if (tileLoader instanceof TMSCachedTileLoader) {
     388            tileCache = (TileCache) tileLoader;
     389        } else {
     390            tileCache = new MemoryTileCache();
     391        }
     392        if (tileLoader == null)
    422393            tileLoader = new OsmTileLoader(this);
    423         }
    424         tileLoader.timeoutConnect = Main.pref.getInteger("socket.timeout.connect",15) * 1000;
    425         tileLoader.timeoutRead = Main.pref.getInteger("socket.timeout.read", 30) * 1000;
    426         if (tileSource instanceof TemplatedTMSTileSource) {
    427             for(Entry<String, String> e : ((TemplatedTMSTileSource)tileSource).getHeaders().entrySet()) {
    428                 tileLoader.headers.put(e.getKey(), e.getValue());
    429             }
    430         }
    431         tileLoader.headers.put("User-Agent", Version.getInstance().getFullAgentString());
    432     }
    433 
    434     @Override
    435     public void setOffset(double dx, double dy) {
    436         super.setOffset(dx, dy);
    437         needRedraw = true;
    438394    }
    439395
     
    472428    }
    473429
    474     /**
    475      * Function to set the maximum number of workers for tile loading to the value defined
    476      * in preferences.
    477      */
    478     public static void setMaxWorkers() {
    479         JobDispatcher.setMaxWorkers(PROP_TMS_JOBS.get());
    480         JobDispatcher.getInstance().setLIFO(true);
    481     }
    482 
    483430    @SuppressWarnings("serial")
    484431    public TMSLayer(ImageryInfo info) {
    485432        super(info);
    486433
    487         setMaxWorkers();
    488434        if(!isProjectionSupported(Main.getProjection())) {
    489435            JOptionPane.showMessageDialog(Main.parent,
    490                 tr("TMS layers do not support the projection {0}.\n{1}\n"
    491                 + "Change the projection or remove the layer.",
    492                 Main.getProjection().toCode(), nameSupportedProjections()),
    493                 tr("Warning"),
    494                 JOptionPane.WARNING_MESSAGE);
     436                    tr("TMS layers do not support the projection {0}.\n{1}\n"
     437                            + "Change the projection or remove the layer.",
     438                            Main.getProjection().toCode(), nameSupportedProjections()),
     439                            tr("Warning"),
     440                            JOptionPane.WARNING_MESSAGE);
    495441        }
    496442
     
    685631        }
    686632        needRedraw = true;
    687         JobDispatcher.getInstance().cancelOutstandingJobs();
    688         tileRequestsOutstanding.clear();
    689633    }
    690634
     
    771715     * into the tileCache.
    772716     */
    773     synchronized Tile tempCornerTile(Tile t) {
     717    Tile tempCornerTile(Tile t) {
    774718        int x = t.getXtile() + 1;
    775719        int y = t.getYtile() + 1;
     
    781725    }
    782726
    783     synchronized Tile getOrCreateTile(int x, int y, int zoom) {
     727    Tile getOrCreateTile(int x, int y, int zoom) {
    784728        Tile tile = getTile(x, y, zoom);
    785729        if (tile == null) {
     
    795739     * already in the cache.
    796740     */
    797     synchronized Tile getTile(int x, int y, int zoom) {
     741    Tile getTile(int x, int y, int zoom) {
    798742        int max = (1 << zoom);
    799743        if (x < 0 || x >= max || y < 0 || y >= max)
     
    802746    }
    803747
    804     synchronized boolean loadTile(Tile tile, boolean force) {
     748    boolean loadTile(Tile tile, boolean force) {
    805749        if (tile == null)
    806750            return false;
    807         if (!force && (tile.hasError() || tile.isLoaded()))
     751        if (!force && (tile.isLoaded() || tile.hasError()))
    808752            return false;
    809753        if (tile.isLoading())
    810754            return false;
    811         if (tileRequestsOutstanding.contains(tile))
    812             return false;
    813         tileRequestsOutstanding.add(tile);
    814         JobDispatcher.getInstance().addJob(tileLoader.createTileLoaderJob(tile));
     755        tileLoader.createTileLoaderJob(tile).submit();
    815756        return true;
    816757    }
     
    12691210            if (zoom < minZoom)
    12701211                return nullTileSet;
    1271             TileSet ts = tileSets[zoom-minZoom];
    1272             if (ts == null) {
    1273                 ts = new TileSet(topLeft, botRight, zoom);
    1274                 tileSets[zoom-minZoom] = ts;
    1275             }
    1276             return ts;
    1277         }
     1212            synchronized (tileSets) {
     1213                TileSet ts = tileSets[zoom-minZoom];
     1214                if (ts == null) {
     1215                    ts = new TileSet(topLeft, botRight, zoom);
     1216                    tileSets[zoom-minZoom] = ts;
     1217                }
     1218                return ts;
     1219            }
     1220        }
     1221
    12781222        public TileSetInfo getTileSetInfo(int zoom) {
    12791223            if (zoom < minZoom)
    12801224                return new TileSetInfo();
    1281             TileSetInfo tsi = tileSetInfos[zoom-minZoom];
    1282             if (tsi == null) {
    1283                 tsi = TMSLayer.getTileSetInfo(getTileSet(zoom));
    1284                 tileSetInfos[zoom-minZoom] = tsi;
    1285             }
    1286             return tsi;
     1225            synchronized (tileSetInfos) {
     1226                TileSetInfo tsi = tileSetInfos[zoom-minZoom];
     1227                if (tsi == null) {
     1228                    tsi = TMSLayer.getTileSetInfo(getTileSet(zoom));
     1229                    tileSetInfos[zoom-minZoom] = tsi;
     1230                }
     1231                return tsi;
     1232            }
    12871233        }
    12881234    }
     
    12901236    @Override
    12911237    public void paint(Graphics2D g, MapView mv, Bounds bounds) {
    1292         //long start = System.currentTimeMillis();
    12931238        EastNorth topLeft = mv.getEastNorth(0, 0);
    12941239        EastNorth botRight = mv.getEastNorth(mv.getWidth(), mv.getHeight());
     
    14361381            myDrawString(g, tr("Pixel scale: {0}", getScaleFactor(currentZoomLevel)), 50, 170);
    14371382            myDrawString(g, tr("Best zoom: {0}", Math.log(getScaleFactor(1))/Math.log(2)/2+1), 50, 185);
     1383            if(tileLoader instanceof TMSCachedTileLoader) {
     1384                TMSCachedTileLoader cachedTileLoader = (TMSCachedTileLoader)tileLoader;
     1385                int offset = 185;
     1386                for(String part: cachedTileLoader.getStats().split("\n")) {
     1387                    myDrawString(g, tr("Cache stats: {0}", part), 50, offset+=15);
     1388                }
     1389
     1390            }
    14381391        }
    14391392    }
  • trunk/src/org/openstreetmap/josm/gui/preferences/imagery/TMSSettingsPanel.java

    r7937 r8168  
    1212import javax.swing.SpinnerNumberModel;
    1313
     14import org.openstreetmap.josm.data.imagery.TMSCachedTileLoader;
     15import org.openstreetmap.josm.data.imagery.TMSCachedTileLoaderJob;
    1416import org.openstreetmap.josm.gui.layer.TMSLayer;
     17import org.openstreetmap.josm.gui.widgets.JosmTextField;
    1518import org.openstreetmap.josm.tools.GBC;
    16 import org.openstreetmap.josm.gui.widgets.JosmTextField;
    1719
    1820/**
     
    2931    private final JCheckBox addToSlippyMapChosser = new JCheckBox();
    3032    private final JosmTextField tilecacheDir = new JosmTextField();
     33    private final JSpinner maxElementsOnDisk;
     34    private final JSpinner maxConcurrentDownloads;
     35
    3136
    3237    /**
     
    3742        minZoomLvl = new JSpinner(new SpinnerNumberModel(TMSLayer.DEFAULT_MIN_ZOOM, TMSLayer.MIN_ZOOM, TMSLayer.MAX_ZOOM, 1));
    3843        maxZoomLvl = new JSpinner(new SpinnerNumberModel(TMSLayer.DEFAULT_MAX_ZOOM, TMSLayer.MIN_ZOOM, TMSLayer.MAX_ZOOM, 1));
     44        maxElementsOnDisk = new JSpinner(new SpinnerNumberModel(TMSCachedTileLoader.MAX_OBJECTS_ON_DISK.get().intValue(), 0, Integer.MAX_VALUE, 1));
     45        maxConcurrentDownloads = new JSpinner(new SpinnerNumberModel(TMSCachedTileLoaderJob.THREAD_LIMIT.get().intValue(), 0, Integer.MAX_VALUE, 1));
    3946
    4047        add(new JLabel(tr("Auto zoom by default: ")), GBC.std());
     
    6168        add(GBC.glue(5, 0), GBC.std());
    6269        add(tilecacheDir, GBC.eol().fill(GBC.HORIZONTAL));
     70
     71        add(new JLabel(tr("Maximum concurrent downloads: ")), GBC.std());
     72        add(GBC.glue(5, 0), GBC.std());
     73        add(maxConcurrentDownloads, GBC.eol());
     74
     75        add(new JLabel(tr("Maximum elements in disk cache: ")), GBC.std());
     76        add(GBC.glue(5, 0), GBC.std());
     77        add(this.maxElementsOnDisk, GBC.eol());
     78
    6379    }
    64    
     80
    6581    /**
    6682     * Loads the TMS settings.
     
    7389        this.minZoomLvl.setValue(TMSLayer.getMinZoomLvl(null));
    7490        this.tilecacheDir.setText(TMSLayer.PROP_TILECACHE_DIR.get());
     91        this.maxElementsOnDisk.setValue(TMSCachedTileLoader.MAX_OBJECTS_ON_DISK.get());
     92        this.maxConcurrentDownloads.setValue(TMSCachedTileLoaderJob.THREAD_LIMIT.get());
    7593    }
    76    
     94
    7795    /**
    7896     * Saves the TMS settings.
     
    8199    public boolean saveSettings() {
    82100        boolean restartRequired = false;
    83        
     101
    84102        if (TMSLayer.PROP_ADD_TO_SLIPPYMAP_CHOOSER.get() != this.addToSlippyMapChosser.isSelected()) {
    85103            restartRequired = true;
     
    90108        TMSLayer.setMaxZoomLvl((Integer)this.maxZoomLvl.getValue());
    91109        TMSLayer.setMinZoomLvl((Integer)this.minZoomLvl.getValue());
    92         TMSLayer.PROP_TILECACHE_DIR.put(this.tilecacheDir.getText());
    93        
     110
     111        TMSCachedTileLoader.MAX_OBJECTS_ON_DISK.put((Integer) this.maxElementsOnDisk.getValue());
     112
     113        if (!TMSCachedTileLoaderJob.THREAD_LIMIT.get().equals(this.maxConcurrentDownloads.getValue())) {
     114            restartRequired = true;
     115            TMSCachedTileLoaderJob.THREAD_LIMIT.put((Integer) this.maxConcurrentDownloads.getValue());
     116        }
     117
     118        if (!TMSLayer.PROP_TILECACHE_DIR.get().equals(this.tilecacheDir.getText())) {
     119            restartRequired = true;
     120            TMSLayer.PROP_TILECACHE_DIR.put(this.tilecacheDir.getText());
     121        }
     122
    94123        return restartRequired;
    95124    }
Note: See TracChangeset for help on using the changeset viewer.