source: josm/trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoader.java@ 9600

Last change on this file since 9600 was 9004, checked in by wiktorn, 8 years ago

Fix high CPU usage when showing small tiles.

  • AbstractTileSourceLayer - check insane() zoom level based on TileCache size instead of hardcoded value
  • TileCache - add interface to check size of the cache
  • TMSCachedTileLoader - remove unnnecessary TileCache interface and its methods
  • HostLimitQueue - correct log message
  • JCSCachedTileLoaderJob - add debug logs for putting request into queue and start of processing
  • Property svn:eol-style set to native
File size: 5.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.imagery;
3
4import java.io.IOException;
5import java.util.Map;
6import java.util.concurrent.ThreadPoolExecutor;
7import java.util.concurrent.TimeUnit;
8
9import org.apache.commons.jcs.access.behavior.ICacheAccess;
10import org.openstreetmap.gui.jmapviewer.Tile;
11import org.openstreetmap.gui.jmapviewer.interfaces.CachedTileLoader;
12import org.openstreetmap.gui.jmapviewer.interfaces.TileJob;
13import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
14import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
15import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
16import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
17import org.openstreetmap.josm.data.cache.HostLimitQueue;
18import org.openstreetmap.josm.data.preferences.IntegerProperty;
19import org.openstreetmap.josm.tools.Utils;
20
21/**
22 * @author Wiktor Niesiobędzki
23 *
24 * Wrapper class that bridges between JCS cache and Tile Loaders
25 *
26 */
27public class TMSCachedTileLoader implements TileLoader, CachedTileLoader {
28
29 protected final ICacheAccess<String, BufferedImageCacheEntry> cache;
30 protected final int connectTimeout;
31 protected final int readTimeout;
32 protected final Map<String, String> headers;
33 protected final TileLoaderListener listener;
34
35 /**
36 * overrides the THREAD_LIMIT in superclass, as we want to have separate limit and pool for TMS
37 */
38
39 public static final IntegerProperty THREAD_LIMIT = new IntegerProperty("imagery.tms.tmsloader.maxjobs", 25);
40
41 /**
42 * Limit definition for per host concurrent connections
43 */
44 public static final IntegerProperty HOST_LIMIT = new IntegerProperty("imagery.tms.tmsloader.maxjobsperhost", 6);
45
46
47 /**
48 * separate from JCS thread pool for TMS loader, so we can have different thread pools for default JCS
49 * and for TMS imagery
50 */
51 private static ThreadPoolExecutor DEFAULT_DOWNLOAD_JOB_DISPATCHER = getNewThreadPoolExecutor("TMS-downloader-%d");
52
53
54 private ThreadPoolExecutor downloadExecutor = DEFAULT_DOWNLOAD_JOB_DISPATCHER;
55
56 /**
57 * Constructor
58 * @param listener called when tile loading has finished
59 * @param cache of the cache
60 * @param connectTimeout to remote resource
61 * @param readTimeout to remote resource
62 * @param headers HTTP headers to be sent along with request
63 * @throws IOException when cache initialization fails
64 */
65 public TMSCachedTileLoader(TileLoaderListener listener, ICacheAccess<String, BufferedImageCacheEntry> cache,
66 int connectTimeout, int readTimeout, Map<String, String> headers) throws IOException {
67 this.cache = cache;
68 this.connectTimeout = connectTimeout;
69 this.readTimeout = readTimeout;
70 this.headers = headers;
71 this.listener = listener;
72 }
73
74 /**
75 * @param nameFormat see {@link Utils#newThreadFactory(String, int)}
76 * @param workers number of worker thread to keep
77 * @return new ThreadPoolExecutor that will use a @see HostLimitQueue based queue
78 */
79 public static ThreadPoolExecutor getNewThreadPoolExecutor(String nameFormat, int workers) {
80 return new ThreadPoolExecutor(
81 workers, // keep the thread number constant
82 workers, // do not this number of threads
83 30, // keepalive for thread
84 TimeUnit.SECONDS,
85 new HostLimitQueue(HOST_LIMIT.get().intValue()),
86 Utils.newThreadFactory(nameFormat, Thread.NORM_PRIORITY)
87 );
88 }
89
90 /**
91 * @param name name of threads
92 * @return new ThreadPoolExecutor that will use a @see HostLimitQueue based queue, with default number of threads
93 */
94 public static ThreadPoolExecutor getNewThreadPoolExecutor(String name) {
95 return getNewThreadPoolExecutor(name, THREAD_LIMIT.get().intValue());
96 }
97
98 @Override
99 public TileJob createTileLoaderJob(Tile tile) {
100 return new TMSCachedTileLoaderJob(listener, tile, cache,
101 connectTimeout, readTimeout, headers, getDownloadExecutor());
102 }
103
104 @Override
105 public void clearCache(TileSource source) {
106 this.cache.remove(source.getName() + ':');
107 }
108
109 /**
110 * @return cache statistics as string
111 */
112 public String getStats() {
113 return cache.getStats();
114 }
115
116 /**
117 * cancels all outstanding tasks in the queue. This rollbacks the state of the tiles in the queue
118 * to loading = false / loaded = false
119 */
120 @Override
121 public void cancelOutstandingTasks() {
122 for (Runnable r: downloadExecutor.getQueue()) {
123 if (downloadExecutor.remove(r) && r instanceof TMSCachedTileLoaderJob) {
124 ((TMSCachedTileLoaderJob) r).handleJobCancellation();
125 }
126 }
127 }
128
129 /**
130 * Sets the download executor that will be used to download tiles instead of default one.
131 * You can use {@link #getNewThreadPoolExecutor} to create a new download executor with separate
132 * queue from default.
133 *
134 * @param downloadExecutor download executor that will be used to download tiles
135 */
136 public void setDownloadExecutor(ThreadPoolExecutor downloadExecutor) {
137 this.downloadExecutor = downloadExecutor;
138 }
139
140 /**
141 * @return download executor that is used by this factory
142 */
143 public ThreadPoolExecutor getDownloadExecutor() {
144 return downloadExecutor;
145 }
146}
Note: See TracBrowser for help on using the repository browser.