Fix http server

This commit is contained in:
Victor Shcherb 2020-09-11 11:01:58 +02:00
parent e070f5be94
commit dcc05f7129
2 changed files with 59 additions and 37 deletions

View file

@ -19,16 +19,14 @@ public class OsmAndHttpServer extends NanoHTTPD {
private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(OsmAndHttpServer.class); private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(OsmAndHttpServer.class);
private final Map<String, ApiEndpoint> endpoints = new HashMap<>(); private final Map<String, ApiEndpoint> endpoints = new HashMap<>();
private MapActivity mapActivity; private MapActivity mapActivity;
private RotatedTileBox mapTileBoxCopy;
private boolean mapLinkedToLocation;
private OsmandApplication app;
public OsmAndHttpServer(String hostname, int port) { public OsmAndHttpServer(String hostname, int port) {
super(hostname, port); super(hostname, port);
} }
@Override
public void stop() {
mapActivity.getMapView().setScreenViewDetached(false);
super.stop();
}
@Override @Override
public Response serve(IHTTPSession session) { public Response serve(IHTTPSession session) {
@ -44,9 +42,32 @@ public class OsmAndHttpServer extends NanoHTTPD {
public void start(MapActivity mapActivity) throws IOException { public void start(MapActivity mapActivity) throws IOException {
this.mapActivity = mapActivity; this.mapActivity = mapActivity;
// don't leak map activity with applciation
this.app = mapActivity.getMyApplication();
registerEndpoints(); registerEndpoints();
start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
mapActivity.getMapView().setScreenViewDetached(true); mapActivity.getMapView().setScreenViewDetached(true);
this.mapTileBoxCopy = mapActivity.getMapView().getCurrentRotatedTileBox().copy();
mapLinkedToLocation = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation();
mapActivity.getMapViewTrackingUtilities().setMapLinkedToLocation(false);
}
@Override
public void stop() {
mapActivity.getMapView().setScreenViewDetached(false);
mapActivity.getMapView().setCurrentViewport(mapTileBoxCopy);
mapActivity.getMapViewTrackingUtilities().setMapLinkedToLocation(mapLinkedToLocation);
mapActivity = null;
super.stop();
}
public MapActivity getMapActivity() {
return mapActivity;
}
public OsmandApplication getMyApplication() {
return app;
} }
public String getUrl() { public String getUrl() {

View file

@ -8,6 +8,7 @@ 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.OsmAndHttpServer; import net.osmand.plus.server.OsmAndHttpServer;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -20,25 +21,24 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
private static final int TIMEOUT_STEP = 150; private static final int TIMEOUT_STEP = 150;
private static final int TIMEOUT = 15000; private static final int TIMEOUT = 15000;
private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class); private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class);
@GuardedBy("this")
private static int lastZoom = -999;
//TODO restore mapState on Exit
private final RotatedTileBox mapTileBoxCopy;
private final MapActivity mapActivity;
private final MetaTileFileSystemCache cache;
public TileEndpoint(MapActivity mapActivity) { private final RotatedTileBox mapTileBoxCopy;
this.mapActivity = mapActivity; private final OsmAndHttpServer server;
this.cache = new MetaTileFileSystemCache(mapActivity.getMyApplication()); private final MetaTileFileSystemCache cache;
this.mapTileBoxCopy = mapActivity.getMapView().getCurrentRotatedTileBox().copy(); private int lastRequestedZoom;
//for debug
public TileEndpoint(OsmAndHttpServer server) {
this.server = server;
this.cache = new MetaTileFileSystemCache(server.getMyApplication());
this.mapTileBoxCopy = server.getMapActivity().getMapView().getCurrentRotatedTileBox().copy();
this.cache.clearCache(); this.cache.clearCache();
} }
@Override @Override
public NanoHTTPD.Response process(NanoHTTPD.IHTTPSession session, String url) { public NanoHTTPD.Response process(NanoHTTPD.IHTTPSession session, String url) {
// https://tile.osmand.net/hd/6/55/25.png // https://tile.osmand.net/hd/6/55/25.png
LOG.debug("SERVER: STARTED REQUEST");
int extInd = url.indexOf('.'); int extInd = url.indexOf('.');
if (extInd >= 0) { if (extInd >= 0) {
url = url.substring(0, extInd); url = url.substring(0, extInd);
@ -53,16 +53,11 @@ 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]);
synchronized (this){
if (zoom > lastZoom+1 || zoom < lastZoom-1){
lastZoom = zoom;
}
}
MetaTileFileSystemCache.MetaTileCache res = cache.get(zoom, x, y); MetaTileFileSystemCache.MetaTileCache res = cache.get(zoom, x, y);
if (res == null) { if (res == null) {
lastRequestedZoom = zoom;
res = requestMetatile(x, y, zoom); res = requestMetatile(x, y, zoom);
if (res == null) { if (res == null) {
LOG.error("SERVER: Cannot request metatile");
return OsmAndHttpServer.ErrorResponses.response500; return OsmAndHttpServer.ErrorResponses.response500;
} }
} }
@ -81,38 +76,44 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
str, str.available()); str, str.available());
} }
private synchronized MetaTileFileSystemCache.MetaTileCache requestMetatile(int x, int y, int zoom) { private synchronized MetaTileFileSystemCache.MetaTileCache requestMetatile(int x, int y, int zoom) {
long time2 = System.currentTimeMillis(); long tm = System.currentTimeMillis();
MapActivity mapActivity = server.getMapActivity();
if (mapActivity == null) {
return null;
}
MetaTileFileSystemCache.MetaTileCache cacheTile = this.cache.get(zoom, x, y); MetaTileFileSystemCache.MetaTileCache cacheTile = this.cache.get(zoom, x, y);
if (cacheTile != null) { if (cacheTile != null) {
return cacheTile; return cacheTile;
} }
if (zoom != lastZoom){
return null;
}
MetaTileFileSystemCache.MetaTileCache res = cache.createMetaTile(zoom, x, y); MetaTileFileSystemCache.MetaTileCache res = cache.createMetaTile(zoom, x, y);
mapActivity.getMapView().setCurrentViewport(res.bbox); mapActivity.getMapView().setCurrentViewport(res.bbox);
int timeout = 0; int timeout = 0;
try { try {
AsyncLoadingThread athread = mapActivity.getMyApplication().getResourceManager().getAsyncLoadingThread(); AsyncLoadingThread athread = mapActivity.getMyApplication().getResourceManager().getAsyncLoadingThread();
Thread.sleep(TIMEOUT_STEP); // TODO line should be removed in future Thread.sleep(TIMEOUT_STEP); // to do line should be removed in future
while (athread.areResourcesLoading() && timeout < TIMEOUT) { while (athread.areResourcesLoading() && timeout < TIMEOUT) {
if(lastRequestedZoom != zoom) {
return null;
}
Thread.sleep(TIMEOUT_STEP); Thread.sleep(TIMEOUT_STEP);
timeout += TIMEOUT_STEP; timeout += TIMEOUT_STEP;
} }
Bitmap tempBmp = mapActivity.getMapView().getBufferBitmap(); Bitmap rbmp = mapActivity.getMapView().getBufferBitmap();
if (timeout >= TIMEOUT) { if (timeout >= TIMEOUT) {
Canvas canvas = new Canvas(tempBmp); return null;
Paint paint = new Paint(); // Canvas canvas = new Canvas(tempBmp);
paint.setColor(Color.RED); // Paint paint = new Paint();
paint.setTextSize(12); // paint.setColor(Color.RED);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); // paint.setTextSize(12);
canvas.drawText("TIMEOUT", tempBmp.getWidth() / 2, tempBmp.getHeight() / 2, paint); // paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
// canvas.drawText("TIMEOUT", tempBmp.getWidth() / 2, tempBmp.getHeight() / 2, paint);
// here we could return stub // here we could return stub
} }
res.bmp = tempBmp.copy(tempBmp.getConfig(), true); res.bmp = rbmp.copy(rbmp.getConfig(), true);
this.cache.put(res); this.cache.put(res);
LOG.debug("SERVER: TIME TO REQUEST TILE: " + (System.currentTimeMillis() - time2)); LOG.debug("Render metatile: " + (System.currentTimeMillis() - tm)/1000.0f);
return res; return res;
} catch (InterruptedException e) { } catch (InterruptedException e) {
LOG.error(e); LOG.error(e);