diff options
Diffstat (limited to 'altosuilib/AltosSiteMapCache.java')
| -rw-r--r-- | altosuilib/AltosSiteMapCache.java | 304 | 
1 files changed, 162 insertions, 142 deletions
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; -		}  	}  }  | 
