cache added
This commit is contained in:
parent
576e70a606
commit
2cd4e23463
3 changed files with 101 additions and 20 deletions
|
@ -0,0 +1,77 @@
|
||||||
|
package net.osmand.plus.server;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.server.endpoints.TileEndpoint;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
public class MetaTileFileSystemCache {
|
||||||
|
private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class);
|
||||||
|
private static final Object TILES_FOLDER = "tiles";
|
||||||
|
private static final int MAX_IN_MEMORY_CACHE_SIZE = 4;
|
||||||
|
private static final int MAX_CACHE_SIZE = 4;
|
||||||
|
private final ConcurrentLinkedQueue<TileEndpoint.MetaTileCache> inMemoryCache = new ConcurrentLinkedQueue<>();
|
||||||
|
private final File externalCacheDir;
|
||||||
|
public boolean inMemoryCacheEnabled = false;
|
||||||
|
|
||||||
|
public MetaTileFileSystemCache(OsmandApplication application) {
|
||||||
|
externalCacheDir = new File(
|
||||||
|
application.getExternalCacheDir().getAbsoluteFile() + File.separator + TILES_FOLDER);
|
||||||
|
if (!externalCacheDir.exists()) {
|
||||||
|
externalCacheDir.mkdir();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(TileEndpoint.MetaTileCache tile) {
|
||||||
|
while (inMemoryCache.size() > MAX_IN_MEMORY_CACHE_SIZE) {
|
||||||
|
inMemoryCache.poll();
|
||||||
|
}
|
||||||
|
while (externalCacheDir.listFiles().length > MAX_CACHE_SIZE) {
|
||||||
|
//remove outdated files
|
||||||
|
for (int i = 0; i < externalCacheDir.listFiles().length - MAX_CACHE_SIZE; i++) {
|
||||||
|
externalCacheDir.listFiles()[i].delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String fileName = tile.getTileId();
|
||||||
|
File file = new File(externalCacheDir, fileName);
|
||||||
|
if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FileOutputStream out = new FileOutputStream(file);
|
||||||
|
tile.getBitmap().compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
if (inMemoryCacheEnabled) {
|
||||||
|
inMemoryCache.add(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TileEndpoint.MetaTileCache get(int zoom, int METATILE_SIZE, int x, int y) {
|
||||||
|
for (int tx = x - METATILE_SIZE + 1; tx < METATILE_SIZE + x - 1; tx++) {
|
||||||
|
for (int ty = y - METATILE_SIZE + 1; ty < METATILE_SIZE + y - 1; ty++) {
|
||||||
|
File file = new File(externalCacheDir, zoom + "_" + METATILE_SIZE + "_" + tx + "_" + ty);
|
||||||
|
if (file.exists()) {
|
||||||
|
TileEndpoint.MetaTileCache tile = new TileEndpoint.MetaTileCache(
|
||||||
|
BitmapFactory.decodeFile(file.getAbsolutePath()),
|
||||||
|
tx, ty, tx + METATILE_SIZE, ty + METATILE_SIZE, zoom
|
||||||
|
);
|
||||||
|
if (inMemoryCacheEnabled) {
|
||||||
|
inMemoryCache.add(tile);
|
||||||
|
}
|
||||||
|
return tile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,6 +62,7 @@ public class OsmAndHttpServer extends NanoHTTPD {
|
||||||
return e.getValue().process(session, uri);
|
return e.getValue().process(session, uri);
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
LOG.error("SERVER ERROR: " + exception.getMessage());
|
LOG.error("SERVER ERROR: " + exception.getMessage());
|
||||||
|
return ErrorResponses.response500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,13 @@ import net.osmand.PlatformUtil;
|
||||||
import net.osmand.data.RotatedTileBox;
|
import net.osmand.data.RotatedTileBox;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.resources.AsyncLoadingThread;
|
import net.osmand.plus.resources.AsyncLoadingThread;
|
||||||
|
import net.osmand.plus.server.MetaTileFileSystemCache;
|
||||||
import net.osmand.plus.server.OsmAndHttpServer;
|
import net.osmand.plus.server.OsmAndHttpServer;
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
|
|
||||||
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
|
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
|
||||||
|
|
||||||
|
@ -22,14 +22,12 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
||||||
private static final int TIMEOUT_STEP = 500;
|
private static final int TIMEOUT_STEP = 500;
|
||||||
private static final int TIMEOUT = 5000;
|
private static final int TIMEOUT = 5000;
|
||||||
private static final int METATILE_SIZE = 2;
|
private static final int METATILE_SIZE = 2;
|
||||||
private static final int MAX_CACHE_SIZE = 4;
|
|
||||||
|
|
||||||
private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class);
|
private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class);
|
||||||
private final MapActivity mapActivity;
|
private final MapActivity mapActivity;
|
||||||
// TODO store on file system
|
private final MetaTileFileSystemCache cache;
|
||||||
private final ConcurrentLinkedQueue<MetaTileCache> cache = new ConcurrentLinkedQueue<>();
|
|
||||||
|
|
||||||
private static class MetaTileCache {
|
public static class MetaTileCache {
|
||||||
Bitmap bmp;
|
Bitmap bmp;
|
||||||
int sx;
|
int sx;
|
||||||
int sy;
|
int sy;
|
||||||
|
@ -37,11 +35,28 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
||||||
int ey;
|
int ey;
|
||||||
int zoom;
|
int zoom;
|
||||||
|
|
||||||
|
public MetaTileCache() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetaTileCache(Bitmap bmp, int sx, int sy, int ex, int ey, int zoom) {
|
||||||
|
this.bmp = bmp;
|
||||||
|
this.sx = sx;
|
||||||
|
this.sy = sy;
|
||||||
|
this.ex = ex;
|
||||||
|
this.ey = ey;
|
||||||
|
this.zoom = zoom;
|
||||||
|
}
|
||||||
|
|
||||||
// to be used in file name
|
// to be used in file name
|
||||||
public String getTileId() {
|
public String getTileId() {
|
||||||
return zoom + "_" + METATILE_SIZE + "_" + sx + "_" + sy;
|
return zoom + "_" + METATILE_SIZE + "_" + sx + "_" + sy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Bitmap getBitmap() {
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
|
||||||
public Bitmap getSubtile(int x, int y) {
|
public Bitmap getSubtile(int x, int y) {
|
||||||
return Bitmap.createBitmap(bmp,
|
return Bitmap.createBitmap(bmp,
|
||||||
(x - sx) * TILE_SIZE_PX * TILE_DENSITY,
|
(x - sx) * TILE_SIZE_PX * TILE_DENSITY,
|
||||||
|
@ -52,13 +67,7 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
||||||
|
|
||||||
public TileEndpoint(MapActivity mapActivity) {
|
public TileEndpoint(MapActivity mapActivity) {
|
||||||
this.mapActivity = mapActivity;
|
this.mapActivity = mapActivity;
|
||||||
}
|
this.cache = new MetaTileFileSystemCache(mapActivity.getMyApplication());
|
||||||
|
|
||||||
private void addToMemoryCache(MetaTileCache res) {
|
|
||||||
while (cache.size() > MAX_CACHE_SIZE) {
|
|
||||||
cache.poll();
|
|
||||||
}
|
|
||||||
cache.add(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,13 +87,7 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
||||||
int zoom = Integer.parseInt(prms[1]);
|
int zoom = Integer.parseInt(prms[1]);
|
||||||
int x = Integer.parseInt(prms[2]);
|
int x = Integer.parseInt(prms[2]);
|
||||||
int y = Integer.parseInt(prms[3]);
|
int y = Integer.parseInt(prms[3]);
|
||||||
|
MetaTileCache res = cache.get(zoom, METATILE_SIZE, x, y);
|
||||||
MetaTileCache res = null;
|
|
||||||
for (MetaTileCache r : cache) {
|
|
||||||
if (r.zoom == zoom && r.ex >= x && r.ey >= y && r.sx <= x && r.sy <= y) {
|
|
||||||
res = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
res = requestMetatile(x, y, zoom);
|
res = requestMetatile(x, y, zoom);
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
|
@ -137,7 +140,7 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
||||||
res.zoom = zoom;
|
res.zoom = zoom;
|
||||||
Bitmap tempBmp = mapActivity.getMapView().getBufferBitmap();
|
Bitmap tempBmp = mapActivity.getMapView().getBufferBitmap();
|
||||||
res.bmp = tempBmp.copy(tempBmp.getConfig(), true);
|
res.bmp = tempBmp.copy(tempBmp.getConfig(), true);
|
||||||
addToMemoryCache(res);
|
cache.put(res);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
Loading…
Reference in a new issue