X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosuilib%2FAltosSiteMapCache.java;h=6e6046bc7f3f31d071f956f48eb5ac1298a1e7b0;hp=42914debf78412d6cb8a8d4ef811450e7a944d9b;hb=e6cfa25702b3dc1d492c5f1a4d0b4ba4831d30bd;hpb=8e44580cbe978f1570d4d2ac13d3dd7cd470ecf7 diff --git a/altosuilib/AltosSiteMapCache.java b/altosuilib/AltosSiteMapCache.java index 42914deb..6e6046bc 100644 --- a/altosuilib/AltosSiteMapCache.java +++ b/altosuilib/AltosSiteMapCache.java @@ -24,62 +24,6 @@ import java.awt.*; import java.io.*; import java.net.*; -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); - if (bimg == null) - throw new IOException("Can't load image file"); - Graphics2D g = image.createGraphics(); - g.drawImage(bimg, 0, 0, null); - bimg.flush(); - bimg = null; - } - - public Image validate() { - int returnCode; - - 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 void flush() { - image.flush(); - } - - 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 class AltosSiteMapCache { static final long google_maps_ratelimit_ms = 1200; // Google limits static map queries to 50 per minute per IP, so @@ -99,121 +43,197 @@ public class AltosSiteMapCache { static boolean forbidden_set = false; static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; - public static synchronized int fetch_map(File file, String url) { + static private Object fetch_lock = new Object(); + + 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; - URL u; - long startTime = System.nanoTime(); + synchronized (fetch_lock) { + URL u; + long startTime = System.nanoTime(); - try { - u = new URL(url); - } catch (java.net.MalformedURLException e) { - return bad_request; - } + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return bad_request; + } - byte[] data; - URLConnection uc = null; - try { - 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; + byte[] data; + URLConnection uc = null; + try { + 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; - data = new byte[contentLength]; - while (offset < contentLength) { - bytesRead = in.read(data, offset, data.length - offset); - if (bytesRead == -1) - break; - offset += bytesRead; - } - in.close(); + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); - if (offset != contentLength) + if (offset != contentLength) + return failed; + + } catch (IOException e) { return failed; + } - } catch (IOException e) { - return failed; - } + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return bad_request; + } catch (IOException e) { + if (file.exists()) + file.delete(); + return bad_request; + } - try { - FileOutputStream out = new FileOutputStream(file); - out.write(data); - out.flush(); - out.close(); - } catch (FileNotFoundException e) { - return bad_request; - } catch (IOException e) { - if (file.exists()) - file.delete(); - return bad_request; + 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 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(); + 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 success; + 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 final int cache_size = 12; + 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 Image get_image(Component component, File file, int width, int height) { + 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 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; - } } }