From 154da99d40269e891c8e95dda53c769b9e8d74b7 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Tue, 21 Jan 2014 16:51:30 +0100
Subject: [PATCH] fix: LwHttp cache writes

---
 .../oscim/tiling/source/common/LwHttp.java    | 49 ++++++++++++-------
 .../source/common/UrlTileDataSource.java      | 34 +++++++------
 2 files changed, 48 insertions(+), 35 deletions(-)

diff --git a/vtm/src/org/oscim/tiling/source/common/LwHttp.java b/vtm/src/org/oscim/tiling/source/common/LwHttp.java
index 0ad8abc0..aeea40c8 100644
--- a/vtm/src/org/oscim/tiling/source/common/LwHttp.java
+++ b/vtm/src/org/oscim/tiling/source/common/LwHttp.java
@@ -57,7 +57,6 @@ public class LwHttp {
 	private Socket mSocket;
 	private OutputStream mCommandStream;
 	private Buffer mResponseStream;
-	private OutputStream mCacheOutputStream;
 	private long mLastRequest = 0;
 	private SocketAddress mSockAddr;
 
@@ -109,7 +108,7 @@ public class LwHttp {
 	// to avoid a copy in PbfDecoder one could manage the buffer
 	// array directly and provide access to it.
 	static class Buffer extends BufferedInputStream {
-		OutputStream mCacheOutputstream;
+		OutputStream mCache;
 		int sumRead = 0;
 		int mContentLength;
 
@@ -118,7 +117,7 @@ public class LwHttp {
 		}
 
 		public void setCache(OutputStream cache) {
-			mCacheOutputstream = cache;
+			mCache = cache;
 		}
 
 		public void start(int length) {
@@ -126,6 +125,10 @@ public class LwHttp {
 			mContentLength = length;
 		}
 
+		public boolean finishedReading() {
+			return sumRead == mContentLength;
+		}
+
 		@Override
 		public int read() throws IOException {
 			if (sumRead >= mContentLength)
@@ -138,8 +141,8 @@ public class LwHttp {
 			if (DBG)
 				log.debug("read {} {}", sumRead, mContentLength);
 
-			if (mCacheOutputstream != null)
-				mCacheOutputstream.write(data);
+			if (mCache != null)
+				mCache.write(data);
 
 			return data;
 		}
@@ -152,20 +155,20 @@ public class LwHttp {
 				return -1;
 
 			int len = super.read(buffer, offset, byteCount);
-			sumRead += len;
 
 			if (DBG)
 				log.debug("read {} {} {}", len, sumRead, mContentLength);
 
-			if (mCacheOutputstream != null)
-				mCacheOutputstream.write(buffer, offset, byteCount);
+			if (len <= 0)
+				return len;
+
+			sumRead += len;
+
+			if (mCache != null)
+				mCache.write(buffer, offset, len);
 
 			return len;
 		}
-
-		public byte[] getArray() {
-			return buf;
-		}
 	}
 
 	public void close() {
@@ -256,8 +259,6 @@ public class LwHttp {
 		is.reset();
 		is.mark(0);
 		is.skip(end);
-
-		is.setCache(mCacheOutputStream);
 		is.start(contentLength);
 
 		if (mInflateContent)
@@ -376,16 +377,26 @@ public class LwHttp {
 		return true;
 	}
 
-	public void setOutputStream(OutputStream outputStream) {
-		mCacheOutputStream = outputStream;
+	public void setCache(OutputStream os) {
+		mResponseStream.setCache(os);
 	}
 
-	public void requestCompleted(boolean keepConnection) {
+	public boolean requestCompleted(boolean success) {
 		mLastRequest = System.nanoTime();
-		mCacheOutputStream = null;
+		mResponseStream.setCache(null);
 
-		if (!keepConnection)
+		if (!mResponseStream.finishedReading()) {
+			log.debug("invalid buffer position");
 			close();
+			return false;
+		}
+
+		if (!success) {
+			close();
+			return false;
+		}
+
+		return true;
 	}
 
 	/**
diff --git a/vtm/src/org/oscim/tiling/source/common/UrlTileDataSource.java b/vtm/src/org/oscim/tiling/source/common/UrlTileDataSource.java
index c61012cd..ddbb5a25 100644
--- a/vtm/src/org/oscim/tiling/source/common/UrlTileDataSource.java
+++ b/vtm/src/org/oscim/tiling/source/common/UrlTileDataSource.java
@@ -24,6 +24,8 @@ import java.net.UnknownHostException;
 
 import org.oscim.tiling.MapTile;
 import org.oscim.tiling.source.ITileCache;
+import org.oscim.tiling.source.ITileCache.TileReader;
+import org.oscim.tiling.source.ITileCache.TileWriter;
 import org.oscim.tiling.source.ITileDataSink;
 import org.oscim.tiling.source.ITileDataSource;
 import org.oscim.tiling.source.ITileDecoder;
@@ -38,30 +40,27 @@ public class UrlTileDataSource implements ITileDataSource {
 	protected final LwHttp mConn;
 	protected final ITileDecoder mTileDecoder;
 	protected final ITileCache mTileCache;
+	protected final boolean mUseCache;
 
 	public UrlTileDataSource(TileSource tileSource, ITileDecoder tileDecoder, LwHttp conn) {
 		mTileDecoder = tileDecoder;
 		mTileCache = tileSource.tileCache;
+		mUseCache = (mTileCache != null);
 		mConn = conn;
 	}
 
 	@Override
 	public QueryResult executeQuery(MapTile tile, ITileDataSink sink) {
-
-		ITileCache.TileWriter cacheWriter = null;
-
-		if (mTileCache != null) {
-			ITileCache.TileReader c = mTileCache.getTile(tile);
-			if (c == null) {
-				cacheWriter = mTileCache.writeTile(tile);
-			} else {
+		if (mUseCache) {
+			TileReader c = mTileCache.getTile(tile);
+			if (c != null) {
 				InputStream is = c.getInputStream();
 				try {
-					if (mTileDecoder.decode(tile, sink, is)) {
+					if (mTileDecoder.decode(tile, sink, is))
 						return QueryResult.SUCCESS;
-					}
+
 				} catch (IOException e) {
-					e.printStackTrace();
+					log.debug("{} Cache read: {}", tile, e);
 				} finally {
 					IOUtils.closeQuietly(is);
 				}
@@ -69,16 +68,19 @@ public class UrlTileDataSource implements ITileDataSource {
 		}
 
 		boolean success = false;
+		TileWriter cache = null;
 		try {
-			if (cacheWriter != null)
-				mConn.setOutputStream(cacheWriter.getOutputStream());
-
 			InputStream is;
 			if (!mConn.sendRequest(tile)) {
 				log.debug("{} Request failed", tile);
 			} else if ((is = mConn.readHeader()) == null) {
 				log.debug("{} Network Error", tile);
 			} else {
+				if (mUseCache) {
+					cache = mTileCache.writeTile(tile);
+					mConn.setCache(cache.getOutputStream());
+				}
+
 				success = mTileDecoder.decode(tile, sink, is);
 			}
 		} catch (SocketException e) {
@@ -92,8 +94,8 @@ public class UrlTileDataSource implements ITileDataSource {
 		} finally {
 			mConn.requestCompleted(success);
 
-			if (cacheWriter != null)
-				cacheWriter.complete(success);
+			if (cache != null)
+				cache.complete(success);
 		}
 		return success ? QueryResult.SUCCESS : QueryResult.FAILED;
 	}