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
static final int bad_request = 3;
static final int forbidden = 4;
- public static synchronized boolean has_map(File file, String url) {
+ public static boolean has_map(File file, String url) {
return file.exists();
}
static boolean forbidden_set = false;
static final long forbidden_interval = 60l * 1000l * 1000l * 1000l;
- public static synchronized int fetch_map(File file, String url) {
- if (file.exists())
- return success;
-
- if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval)
- return forbidden;
+ 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);
file.delete();
return bad_request;
}
+ 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();
+ 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();
+ }
+ }
+ }
}
+ } else {
+ status = fetch_one(file, url);
}
-
- return success;
+ return status;
}
- static final int cache_size = 12;
+ 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 AltosCacheImage[] images;
+ 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;
+ }
+ }
static long used;
- public static synchronized Image get_image(Component component, File file, int width, int height) {
+ 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);
+ }
+
+/*
+ private static void dump_cache() {
+ int min_x = 1000, max_x = -1000, min_y = 1000, max_y = -1000;
+
+ 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);
+ }
+ }
+
+ 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]++;
+ }
+ }
+
+ 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;
- }
}
}