X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosuilib%2FAltosSiteMapCache.java;h=7f436ef0729b595da087f7c706098dd854fc4eca;hp=cf93016a574ab5d233b0578abbaca034b990206a;hb=5c3991768d3cb17fc99ad32b2d6d8d11f0e37dfa;hpb=0a6c76fc0525d6588a1d88127f0085f13a02f1af diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index cf93016a..7f436ef0 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -22,85 +22,55 @@ import javax.imageio.ImageIO; import java.awt.image.*; import java.awt.*; import java.io.*; -import java.net.URL; -import java.net.URLConnection; - - -class AltosCacheImage { - Component component; - File file; - VolatileImage image; - int width; - int height; - long used; - - public void load_image() throws IOException { - BufferedImage bimg = ImageIO.read(file); - Graphics2D g = image.createGraphics(); - g.drawImage(bimg, 0, 0, null); - bimg.flush(); - } - - public Image validate() { - int returnCode; +import java.net.*; - if (image != null) - returnCode = image.validate(component.getGraphicsConfiguration()); - else - returnCode = VolatileImage.IMAGE_INCOMPATIBLE; - if (returnCode == VolatileImage.IMAGE_RESTORED) { - try { - load_image(); - } catch (IOException e) { - return null; - } - } else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) { - image = component.createVolatileImage(width, height); - try { - load_image(); - } catch (IOException e) { - return null; - } - } - return image; - } +public class AltosSiteMapCache { + static final long google_maps_ratelimit_ms = 1200; + // Google limits static map queries to 50 per minute per IP, so + // each query should take at least 1.2 seconds. - public void flush() { - image.flush(); - } + static final int success = 0; + static final int loading = 1; + static final int failed = 2; + static final int bad_request = 3; + static final int forbidden = 4; - public AltosCacheImage(Component component, File file, int w, int h) throws IOException { - this.component = component; - this.file = file; - width = w; - height = h; - image = component.createVolatileImage(w, h); - used = 0; + public static boolean has_map(File file, String url) { + return file.exists(); } -} -public class AltosSiteMapCache extends JLabel { - static final long google_maps_ratelimit_ms = 1200; - // Google limits static map queries to 50 per minute per IP, so - // each query should take at least 1.2 seconds. + static long forbidden_time; + static boolean forbidden_set = false; + static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; - public static boolean fetchMap(File file, String url) { - if (file.exists()) - return true; + static private Object fetch_lock = new Object(); + private static int fetch_one(File file, String url) { URL u; - long startTime = System.nanoTime(); try { u = new URL(url); } catch (java.net.MalformedURLException e) { - return false; + return bad_request; } byte[] data; + URLConnection uc = null; try { - URLConnection uc = u.openConnection(); + uc = u.openConnection(); + String type = uc.getContentType(); int contentLength = uc.getContentLength(); + if (uc instanceof HttpURLConnection) { + int response = ((HttpURLConnection) uc).getResponseCode(); + switch (response) { + case HttpURLConnection.HTTP_FORBIDDEN: + case HttpURLConnection.HTTP_PAYMENT_REQUIRED: + case HttpURLConnection.HTTP_UNAUTHORIZED: + forbidden_time = System.nanoTime(); + forbidden_set = true; + return forbidden; + } + } InputStream in = new BufferedInputStream(uc.getInputStream()); int bytesRead = 0; int offset = 0; @@ -113,11 +83,11 @@ public class AltosSiteMapCache extends JLabel { } in.close(); - if (offset != contentLength) { - return false; - } + if (offset != contentLength) + return failed; + } catch (IOException e) { - return false; + return failed; } try { @@ -126,69 +96,156 @@ public class AltosSiteMapCache extends JLabel { out.flush(); out.close(); } catch (FileNotFoundException e) { - return false; + return bad_request; } catch (IOException e) { - if (file.exists()) { + if (file.exists()) file.delete(); + return bad_request; + } + return success; + } + + public static int fetch_map(File file, String url) { + if (file.exists()) + return success; + + if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) + return forbidden; + + int status = bad_request; + + if (!AltosUIVersion.has_google_maps_api_key()) { + synchronized (fetch_lock) { + long startTime = System.nanoTime(); + status = fetch_one(file, url); + if (status == success) { + long duration_ms = (System.nanoTime() - startTime) / 1000000; + if (duration_ms < google_maps_ratelimit_ms) { + try { + Thread.sleep(google_maps_ratelimit_ms - duration_ms); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } } - return false; + } else { + status = fetch_one(file, url); } + return status; + } - long duration_ms = (System.nanoTime() - startTime) / 1000000; - if (duration_ms < google_maps_ratelimit_ms) { - try { - Thread.sleep(google_maps_ratelimit_ms - duration_ms); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + static final int min_cache_size = 9; + static final int max_cache_size = 24; + + static int cache_size = min_cache_size; + + static AltosSiteMapImage[] images = new AltosSiteMapImage[cache_size]; + + static Object cache_lock = new Object(); + + public static void set_cache_size(int new_size) { + if (new_size < min_cache_size) + new_size = min_cache_size; + if (new_size > max_cache_size) + new_size = max_cache_size; + if (new_size == cache_size) + return; + + synchronized(cache_lock) { + AltosSiteMapImage[] new_images = new AltosSiteMapImage[new_size]; + + for (int i = 0; i < cache_size; i++) { + if (i < new_size) + new_images[i] = images[i]; + else + images[i].flush(); } + images = new_images; + cache_size = new_size; } + } - return true; + static long used; + + private static Point tile_loc(AltosSiteMapTile tile) { + Rectangle r = tile.getBounds(); + int x = r.x / 512; + int y = r.y / 512; + + return new Point (x, y); } - static int cache_size = 9; + private static void dump_cache() { + int min_x = 1000, max_x = -1000, min_y = 1000, max_y = -1000; - static AltosCacheImage[] images; + for (int i = 0; i < cache_size; i++) { + AltosSiteMapImage image = images[i]; + if (image != null) { + Point p = tile_loc(image.tile); + min_x = min_x < p.x ? min_x : p.x; + max_x = max_x > p.x ? max_x : p.x; + min_y = min_y < p.y ? min_y : p.y; + max_y = max_y > p.y ? max_y : p.y; + System.out.printf ("entry %d %d,%d used %d\n", i, p.x, p.y, image.used); + } else { + System.out.printf ("entry %d empty\n", i); + } + } - static long used; + int[][] map = new int[max_x - min_x + 1][max_y - min_y + 1]; + for (int i = 0; i < cache_size; i++) { + AltosSiteMapImage image = images[i]; + if (image != null) { + Point p = tile_loc(image.tile); + map[p.x - min_x][p.y - min_y]++; + } + } - public static void set_cache_size(int cache_size) { - AltosSiteMapCache.cache_size = cache_size; - images = null; + for (int y = min_y; y <= max_y; y++) { + for (int x = min_x; x <= max_x; x++) + System.out.printf (" %2d", map[x - min_x][y - min_y]); + System.out.printf("\n"); + } } - public static Image get_image(Component component, File file, int width, int height) { + public static AltosSiteMapImage get_image(AltosSiteMapTile tile, File file, int width, int height) { int oldest = -1; long age = used; - AltosCacheImage image; - if (images == null) - images = new AltosCacheImage[cache_size]; - for (int i = 0; i < cache_size; i++) { - image = images[i]; - if (image == null) { - oldest = i; - break; + synchronized(cache_lock) { + AltosSiteMapImage image = null; + for (int i = 0; i < cache_size; i++) { + image = images[i]; + + if (image == null) { + oldest = i; + break; + } + if (image.tile == tile && file.equals(image.file)) { + image.used = used++; + return image; + } + if (image.used < age) { + oldest = i; + age = image.used; + } } - if (image.component == component && file.equals(image.file)) { + + try { + image = new AltosSiteMapImage(tile, file, width, height); image.used = used++; - return image.validate(); - } - if (image.used < age) { - oldest = i; - age = image.used; + if (images[oldest] != null) { +// dump_cache(); + AltosSiteMap.debug_component(images[oldest].tile, "replacing cache"); + AltosSiteMap.debug_component(tile, "replaced cache"); + images[oldest].flush(); + } + images[oldest] = image; + return image; + } catch (IOException e) { + return null; } } - - try { - image = new AltosCacheImage(component, file, width, height); - image.used = used++; - if (images[oldest] != null) - images[oldest].flush(); - images[oldest] = image; - return image.validate(); - } catch (IOException e) { - return null; - } } }