X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altoslib%2FAltosMapStore.java;h=7e0f3fb8a7cc2f246307f7ceda5bb33adf5f33ef;hp=88412593e31513f2389b11662e92d59d3bb732ac;hb=ff5faf1cc710b7e9299dcaec719bc2421f4ca5b4;hpb=0cc03210d5d53d12604688f294b6ca39e3a025de diff --git a/altoslib/AltosMapStore.java b/altoslib/AltosMapStore.java index 88412593..7e0f3fb8 100644 --- a/altoslib/AltosMapStore.java +++ b/altoslib/AltosMapStore.java @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_7; +package org.altusmetrum.altoslib_13; import java.io.*; import java.net.*; @@ -28,13 +29,65 @@ public class AltosMapStore { int status; - public int status() { + private static File map_file(AltosLatLon center, int zoom, int maptype, int px_size, int scale) { + double lat = center.lat; + double lon = center.lon; + char chlat = lat < 0 ? 'S' : 'N'; + char chlon = lon < 0 ? 'W' : 'E'; + + if (lat < 0) lat = -lat; + if (lon < 0) lon = -lon; + String maptype_string = String.format("%s-", AltosMap.maptype_names[maptype]); + String format_string; + if (maptype == AltosMap.maptype_hybrid || maptype == AltosMap.maptype_satellite || maptype == AltosMap.maptype_terrain) + format_string = "jpg"; + else + format_string = "png"; + return new File(AltosPreferences.mapdir(), + String.format("map-%c%.6f,%c%.6f-%s%d%s.%s", + chlat, lat, chlon, lon, maptype_string, zoom, scale == 1 ? "" : String.format("-%d", scale), format_string)); + } + + public static String google_maps_api_key = null; + + private static String google_map_url(AltosLatLon center, int zoom, int maptype, int px_size, int scale, String format_string) { + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&scale=%d&sensor=false&maptype=%s&format=%s&key=%s", + center.lat, center.lon, zoom, px_size, px_size, scale, + AltosMap.maptype_names[maptype], format_string, google_maps_api_key); + } + + private static String altos_map_url(AltosLatLon center, int zoom, int maptype, int px_size, int scale, String format_string) { + return String.format("https://maps.altusmetrum.org/cgi-bin/altos-map?lat=%.6f&lon=%.6f&zoom=%d", + center.lat, center.lon, zoom); + } + + private static String map_url(AltosLatLon center, int zoom, int maptype, int px_size, int scale) { + String format_string; + + if (maptype == AltosMap.maptype_hybrid || maptype == AltosMap.maptype_satellite || maptype == AltosMap.maptype_terrain) + format_string = "jpg"; + else + format_string = "png32"; + + for (int s = 1; s < scale; s <<= 1) + zoom--; + + px_size /= scale; + + if (google_maps_api_key != null) + return google_map_url(center, zoom, maptype, px_size, scale, format_string); + else + return altos_map_url(center, zoom, maptype, px_size, scale, format_string); + } + + public synchronized int status() { return status; } public synchronized void add_listener(AltosMapStoreListener listener) { if (!listeners.contains(listener)) listeners.add(listener); + listener.notify_store(this, status); } public synchronized void remove_listener(AltosMapStoreListener listener) { @@ -50,6 +103,7 @@ public class AltosMapStore { static Object forbidden_lock = new Object(); static long forbidden_time; static boolean forbidden_set; + public static int forbidden_response; private int fetch_url() { URL u; @@ -75,6 +129,7 @@ public class AltosMapStore { synchronized (forbidden_lock) { forbidden_time = System.nanoTime(); forbidden_set = true; + forbidden_response = response; return AltosMapTile.forbidden; } } @@ -110,7 +165,7 @@ public class AltosMapStore { file.delete(); return AltosMapTile.bad_request; } - return AltosMapTile.success; + return AltosMapTile.fetched; } static Object fetch_lock = new Object(); @@ -118,49 +173,69 @@ public class AltosMapStore { static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; static final long google_maps_ratelimit_ms = 1200; - class loader implements Runnable { + static Object fetcher_lock = new Object(); - public void run() { - if (file.exists()) { - notify_listeners(AltosMapTile.success); - return; - } + static LinkedList waiting = new LinkedList(); + static LinkedList running = new LinkedList(); + + static final int concurrent_fetchers = 128; - synchronized(forbidden_lock) { - if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) { - notify_listeners(AltosMapTile.forbidden); + static void start_fetchers() { + while (!waiting.isEmpty() && running.size() < concurrent_fetchers) { + AltosMapStore s = waiting.remove(); + running.add(s); + Thread lt = s.make_fetcher_thread(); + lt.start(); + } + } + + void finish_fetcher() { + synchronized(fetcher_lock) { + running.remove(this); + start_fetchers(); + } + } + + void add_fetcher() { + synchronized(fetcher_lock) { + waiting.add(this); + start_fetchers(); + } + } + + class fetcher implements Runnable { + + public void run() { + try { + if (file.exists()) { + notify_listeners(AltosMapTile.fetched); return; } - } - int new_status; - - if (!AltosVersion.has_google_maps_api_key()) { - synchronized (fetch_lock) { - long startTime = System.nanoTime(); - new_status = fetch_url(); - if (new_status == AltosMapTile.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(); - } - } + synchronized(forbidden_lock) { + if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) { + notify_listeners(AltosMapTile.forbidden); + return; } } - } else { + + int new_status; + new_status = fetch_url(); + + notify_listeners(new_status); + } finally { + finish_fetcher(); } - notify_listeners(new_status); } } - private void load() { - loader l = new loader(); - Thread lt = new Thread(l); - lt.start(); + private Thread make_fetcher_thread() { + return new Thread(new fetcher()); + } + + private void fetch() { + add_fetcher(); } private AltosMapStore (String url, File file) { @@ -168,10 +243,10 @@ public class AltosMapStore { this.file = file; if (file.exists()) - status = AltosMapTile.success; + status = AltosMapTile.fetched; else { - status = AltosMapTile.loading; - load(); + status = AltosMapTile.fetching; + fetch(); } } @@ -192,16 +267,19 @@ public class AltosMapStore { static HashMap stores = new HashMap(); - public static AltosMapStore get(String url, File file) { + public static AltosMapStore get(AltosLatLon center, int zoom, int maptype, int px_size, int scale) { + String url = map_url(center, zoom, maptype, px_size, scale); + AltosMapStore store; synchronized(stores) { if (stores.containsKey(url)) { store = stores.get(url); } else { - store = new AltosMapStore(url, file); + store = new AltosMapStore(url, map_file(center, zoom, maptype, px_size, scale)); stores.put(url, store); } } return store; } + }