This commit is contained in:
Hannes Janetzek 2013-01-21 03:18:57 +01:00
parent ddc5466789
commit 04cf5e76aa

View File

@ -30,6 +30,7 @@ import java.net.SocketException;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.net.URL; import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Arrays;
import org.oscim.core.BoundingBox; import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint; import org.oscim.core.GeoPoint;
@ -104,7 +105,7 @@ public class MapDatabase implements IMapDatabase {
File f = null; File f = null;
mBufferSize = 0; mBufferFill = 0;
mBufferPos = 0; mBufferPos = 0;
mReadPos = 0; mReadPos = 0;
@ -124,17 +125,17 @@ public class MapDatabase implements IMapDatabase {
cacheBegin(tile, f); cacheBegin(tile, f);
decode(); decode();
} else { } else {
Log.d(TAG, "Network Error: " + tile); Log.d(TAG, tile + " Network Error");
result = QueryResult.FAILED; result = QueryResult.FAILED;
} }
} catch (SocketException ex) { } catch (SocketException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage()); Log.d(TAG, tile + " Socket exception: " + ex.getMessage());
result = QueryResult.FAILED; result = QueryResult.FAILED;
} catch (SocketTimeoutException ex) { } catch (SocketTimeoutException ex) {
Log.d(TAG, "Socket Timeout exception: " + ex.getMessage()); Log.d(TAG, tile + " Socket Timeout exception: " + ex.getMessage());
result = QueryResult.FAILED; result = QueryResult.FAILED;
} catch (UnknownHostException ex) { } catch (UnknownHostException ex) {
Log.d(TAG, "no network"); Log.d(TAG, tile + " no network");
result = QueryResult.FAILED; result = QueryResult.FAILED;
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
@ -267,7 +268,8 @@ public class MapDatabase implements IMapDatabase {
} }
// /////////////// hand sewed tile protocol buffers decoder /////////////// // /////////////// hand sewed tile protocol buffers decoder ///////////////
private int BUFFER_SIZE = 65536; private final int MAX_WAY_COORDS = 16384;
private final int BUFFER_SIZE = 65536;
private byte[] mReadBuffer = new byte[BUFFER_SIZE]; private byte[] mReadBuffer = new byte[BUFFER_SIZE];
@ -275,7 +277,7 @@ public class MapDatabase implements IMapDatabase {
private int mBufferPos; private int mBufferPos;
// bytes available in buffer // bytes available in buffer
private int mBufferSize; private int mBufferFill;
// overall bytes of content processed // overall bytes of content processed
private int mBytesProcessed; private int mBytesProcessed;
@ -302,9 +304,8 @@ public class MapDatabase implements IMapDatabase {
private short[] mTmpKeys = new short[100]; private short[] mTmpKeys = new short[100];
private short[] mIndices = new short[10]; private short[] mIndices = new short[10];
private Tag[] mTmpTags = new Tag[10]; private Tag[] mTmpTags = new Tag[20];
private int MAX_WAY_COORDS = 32768;
private float[] mTmpCoords = new float[MAX_WAY_COORDS]; private float[] mTmpCoords = new float[MAX_WAY_COORDS];
private boolean decode() throws IOException { private boolean decode() throws IOException {
@ -312,7 +313,7 @@ public class MapDatabase implements IMapDatabase {
mCurTagCnt = 0; mCurTagCnt = 0;
if (debug) if (debug)
Log.d(TAG, "Content length " + mContentLenth); Log.d(TAG, mTile + " Content length " + mContentLenth);
mBytesProcessed = 0; mBytesProcessed = 0;
int val; int val;
@ -345,7 +346,7 @@ public class MapDatabase implements IMapDatabase {
break; break;
default: default:
Log.d(TAG, "invalid type for tile: " + tag); Log.d(TAG, mTile + " invalid type for tile: " + tag);
return false; return false;
} }
} }
@ -363,7 +364,7 @@ public class MapDatabase implements IMapDatabase {
else else
tag = new Tag(key, tagString, true); tag = new Tag(key, tagString, true);
if (debug) if (debug)
Log.d(TAG, "add tag: " + curTag + " " + tag); Log.d(TAG, mTile + " add tag: " + curTag + " " + tag);
curTags[curTag] = tag; curTags[curTag] = tag;
return true; return true;
@ -384,7 +385,7 @@ public class MapDatabase implements IMapDatabase {
boolean skip = false; boolean skip = false;
boolean fail = false; boolean fail = false;
if (debug) if (debug)
Log.d(TAG, "decode element: " + type); Log.d(TAG, mTile + " decode element: " + type);
if (type == TAG_TILE_POINT) if (type == TAG_TILE_POINT)
coordCnt = 2; coordCnt = 2;
@ -404,8 +405,6 @@ public class MapDatabase implements IMapDatabase {
case TAG_ELEM_NUM_INDICES: case TAG_ELEM_NUM_INDICES:
indexCnt = decodeVarint32(); indexCnt = decodeVarint32();
if (debug)
Log.d(TAG, "elem num index: " + indexCnt);
break; break;
case TAG_ELEM_INDEX: case TAG_ELEM_INDEX:
@ -422,19 +421,17 @@ public class MapDatabase implements IMapDatabase {
if (indexCnt < index.length) if (indexCnt < index.length)
index[indexCnt] = -1; index[indexCnt] = -1;
} }
if (debug)
Log.d(TAG, "elem index: " + coordCnt);
break; break;
case TAG_ELEM_COORDS: case TAG_ELEM_COORDS:
if (coordCnt == 0) { if (coordCnt == 0) {
Log.d(TAG, "skipping way"); Log.d(TAG, mTile + " skipping way");
skip = true; skip = true;
} }
int cnt = decodeWayCoordinates(skip, coordCnt); int cnt = decodeWayCoordinates(skip, coordCnt);
if (cnt != coordCnt) { if (cnt != coordCnt) {
Log.d(TAG, "X wrong number of coordintes"); Log.d(TAG, mTile + " wrong number of coordintes");
fail = true; fail = true;
} }
break; break;
@ -448,14 +445,14 @@ public class MapDatabase implements IMapDatabase {
break; break;
default: default:
Log.d(TAG, "X invalid type for way: " + tag); Log.d(TAG, mTile + " invalid type for way: " + tag);
} }
} }
if (fail || tags == null || indexCnt == 0) { if (fail || tags == null || indexCnt == 0) {
Log.d(TAG, "failed reading way: bytes:" + bytes + " index:" Log.d(TAG, mTile + " failed reading way: bytes:" + bytes + " index:"
+ (index == null ? "null" : index.toString()) + " tag:" + (index != null ? Arrays.toString(index) : "null") + " tag:"
+ (tags != null ? tags.toString() : "...") + " " + (tags != null ? Arrays.deepToString(tags) : "null") + " "
+ indexCnt + " " + coordCnt); + indexCnt + " " + coordCnt);
return false; return false;
} }
@ -467,11 +464,7 @@ public class MapDatabase implements IMapDatabase {
else if (type == TAG_TILE_POLY) else if (type == TAG_TILE_POLY)
mMapGenerator.renderWay((byte) layer, tags, coords, index, true, prio); mMapGenerator.renderWay((byte) layer, tags, coords, index, true, prio);
else { else {
if (debug)
Log.d(TAG, "add poi " + coords[1] + " " + coords[0] + " " + tags[0]);
mMapGenerator.renderPointOfInterest((byte) layer, tags, coords[1], coords[0]); mMapGenerator.renderPointOfInterest((byte) layer, tags, coords[1], coords[0]);
// for (int i = 0; i < index[0]; i++)
} }
return true; return true;
@ -536,38 +529,34 @@ public class MapDatabase implements IMapDatabase {
int cnt = 0; int cnt = 0;
int result; int result;
int x, lastX = 0; int lastX = 0;
int y, lastY = 0; int lastY = 0;
boolean even = true; boolean even = true;
float scale = mScaleFactor; float scale = mScaleFactor;
if (nodes * 2 > coords.length) { if (nodes * 2 > coords.length) {
Log.d(TAG, "increase way coord buffer " + mTile + " to " + (nodes * 2)); Log.d(TAG, mTile + " increase way coord buffer to " + (nodes * 2));
float[] tmp = new float[nodes * 2]; float[] tmp = new float[nodes * 2];
mTmpCoords = coords = tmp; mTmpCoords = coords = tmp;
} }
// read repeated sint32 // read repeated sint32
while (pos < end) { while (pos < end) {
if (buf[pos] >= 0) { if (buf[pos] >= 0) {
result = buf[pos++]; result = buf[pos++];
} else if (buf[pos + 1] >= 0) { } else if (buf[pos + 1] >= 0) {
result = (buf[pos] & 0x7f) result = (buf[pos++] & 0x7f)
| buf[pos + 1] << 7; | buf[pos++] << 7;
pos += 2;
} else if (buf[pos + 2] >= 0) { } else if (buf[pos + 2] >= 0) {
result = (buf[pos] & 0x7f) result = (buf[pos++] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7 | (buf[pos++] & 0x7f) << 7
| (buf[pos + 2]) << 14; | (buf[pos++]) << 14;
pos += 3;
} else if (buf[pos + 3] >= 0) { } else if (buf[pos + 3] >= 0) {
result = (buf[pos] & 0x7f) result = (buf[pos++] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7 | (buf[pos++] & 0x7f) << 7
| (buf[pos + 2] & 0x7f) << 14 | (buf[pos++] & 0x7f) << 14
| (buf[pos + 3]) << 21; | (buf[pos++]) << 21;
pos += 4;
} else { } else {
result = (buf[pos] & 0x7f) result = (buf[pos] & 0x7f)
| (buf[pos + 1] & 0x7f) << 7 | (buf[pos + 1] & 0x7f) << 7
@ -581,17 +570,19 @@ public class MapDatabase implements IMapDatabase {
i++; i++;
if (i == 10) if (i == 10)
throw new IOException("X malformed VarInt32"); throw new IOException("X malformed VarInt32 in " + mTile);
} }
// zigzag decoding
int s = ((result >>> 1) ^ -(result & 1));
if (even) { if (even) {
x = ((result >>> 1) ^ -(result & 1)); lastX = lastX + s;
lastX = lastX + x;
coords[cnt++] = lastX / scale; coords[cnt++] = lastX / scale;
even = false; even = false;
} else { } else {
y = ((result >>> 1) ^ -(result & 1)); lastY = lastY + s;
lastY = lastY + y;
coords[cnt++] = lastY / scale; coords[cnt++] = lastY / scale;
even = true; even = true;
} }
@ -604,75 +595,64 @@ public class MapDatabase implements IMapDatabase {
} }
private void readBuffer(int size) throws IOException { private void readBuffer(int size) throws IOException {
//int read = 0;
// check if buffer already contains the request bytes // check if buffer already contains the request bytes
if (mBufferPos + size < mBufferSize) if (mBufferPos + size < mBufferFill)
return;// mBufferSize - mBufferPos; return;
// check if inputstream is read to the end // check if inputstream is read to the end
if (mReadPos == mContentLenth) if (mReadPos == mContentLenth)
return; // mBufferSize - mBufferPos; return;
int maxSize = mReadBuffer.length;
if (size > BUFFER_SIZE) { if (size > maxSize) {
// FIXME throw exception for now, but frankly better Log.d(TAG, mTile + "increase read buffer to " + size + " bytes");
// sanitize tile data on compilation. this should only maxSize = size;
// happen with strings or one ways coordinates are byte[] tmp = new byte[maxSize];
// larger than 64kb
//throw new IOException("X requested size too large " + mTile);
BUFFER_SIZE = size;
byte[] tmp = new byte[BUFFER_SIZE];
mBufferSize -= mBufferPos; mBufferFill -= mBufferPos;
System.arraycopy(mReadBuffer, mBufferPos, tmp, 0, mBufferSize); System.arraycopy(mReadBuffer, mBufferPos, tmp, 0, mBufferFill);
mBufferPos = 0; mBufferPos = 0;
mReadBuffer = tmp; mReadBuffer = tmp;
Log.d(TAG, mTile + "increase read buffer to " + size + " bytes");
} }
if (mBufferSize == mBufferPos) { if (mBufferFill == mBufferPos) {
mBufferPos = 0; mBufferPos = 0;
mBufferSize = 0; mBufferFill = 0;
} else if (mBufferPos + size > BUFFER_SIZE) { } else if (mBufferPos + size > maxSize) {
// Log.d(TAG, "wrap buffer - read:" + size // copy bytes left to the beginning of buffer
// + " cur size:" + mBufferSize mBufferFill -= mBufferPos;
// + " cur pos:" + mBufferPos); System.arraycopy(mReadBuffer, mBufferPos, mReadBuffer, 0, mBufferFill);
// copy bytes left to read to the beginning of buffer
mBufferSize -= mBufferPos;
System.arraycopy(mReadBuffer, mBufferPos, mReadBuffer, 0, mBufferSize);
mBufferPos = 0; mBufferPos = 0;
} }
int max = BUFFER_SIZE - mBufferSize; int max = maxSize - mBufferFill;
while ((mBufferSize - mBufferPos) < size && max > 0) { while ((mBufferFill - mBufferPos) < size && max > 0) {
max = BUFFER_SIZE - mBufferSize; max = maxSize - mBufferFill;
if (max > mContentLenth - mReadPos) if (max > mContentLenth - mReadPos)
max = (int) (mContentLenth - mReadPos); max = (int) (mContentLenth - mReadPos);
// read until requested size is available in buffer // read until requested size is available in buffer
int len = mInputStream.read(mReadBuffer, mBufferSize, max); int len = mInputStream.read(mReadBuffer, mBufferFill, max);
if (len < 0) { if (len < 0) {
// finished reading, mark end // finished reading, mark end
mReadBuffer[mBufferSize] = 0; mReadBuffer[mBufferFill] = 0;
break; break;
} }
//read += len;
mReadPos += len; mReadPos += len;
if (mCacheFile != null) if (mCacheFile != null)
mCacheFile.write(mReadBuffer, mBufferSize, len); mCacheFile.write(mReadBuffer, mBufferFill, len);
if (mReadPos == mContentLenth) if (mReadPos == mContentLenth)
break; break;
mBufferSize += len; mBufferFill += len;
} }
return; // read;
} }
private short[] decodeShortArray(int num, short[] array) throws IOException { private short[] decodeShortArray(int num, short[] array) throws IOException {
@ -725,7 +705,7 @@ public class MapDatabase implements IMapDatabase {
i++; i++;
if (i == 10) if (i == 10)
throw new IOException("X malformed VarInt32"); throw new IOException("X malformed VarInt32 in " + mTile);
} }
@ -741,7 +721,7 @@ public class MapDatabase implements IMapDatabase {
private int decodeVarint32() throws IOException { private int decodeVarint32() throws IOException {
int pos = mBufferPos; int pos = mBufferPos;
if (pos + 10 > mBufferSize) { if (pos + 10 > mBufferFill) {
readBuffer(4096); readBuffer(4096);
pos = mBufferPos; pos = mBufferPos;
} }
@ -788,7 +768,7 @@ public class MapDatabase implements IMapDatabase {
read++; read++;
if (read == 10) if (read == 10)
throw new IOException("X malformed VarInt32"); throw new IOException("X malformed VarInt32 in " + mTile);
mBufferPos += read; mBufferPos += read;
mBytesProcessed += read; mBytesProcessed += read;
@ -878,7 +858,7 @@ public class MapDatabase implements IMapDatabase {
mContentLenth = decodeInt(buf, end); mContentLenth = decodeInt(buf, end);
// buffer fill // buffer fill
mBufferSize = read; mBufferFill = read;
// start of content // start of content
mBufferPos = end + 4; mBufferPos = end + 4;
// bytes of content already read into buffer // bytes of content already read into buffer
@ -941,7 +921,7 @@ public class MapDatabase implements IMapDatabase {
mCommandStream.flush(); mCommandStream.flush();
return true; return true;
} catch (IOException e) { } catch (IOException e) {
Log.d(TAG, "retry - recreate connection"); Log.d(TAG, mTile + " recreate connection");
} }
lwHttpConnect(); lwHttpConnect();
@ -1040,7 +1020,7 @@ public class MapDatabase implements IMapDatabase {
if (mReadPos > 0) { if (mReadPos > 0) {
try { try {
mCacheFile.write(mReadBuffer, mBufferPos, mCacheFile.write(mReadBuffer, mBufferPos,
mBufferSize - mBufferPos); mBufferFill - mBufferPos);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();