extract LwHttp from MapDatabase
This commit is contained in:
parent
99dafda4b9
commit
d25d967332
431
src/org/oscim/database/oscimap/LwHttp.java
Normal file
431
src/org/oscim/database/oscimap/LwHttp.java
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 OpenScienceMap
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.database.oscimap;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class LwHttp {
|
||||||
|
private static final String TAG = LwHttp.class.getName();
|
||||||
|
|
||||||
|
private String mHost;
|
||||||
|
private int mPort;
|
||||||
|
private long mContentLenth;
|
||||||
|
private InputStream mInputStream;
|
||||||
|
|
||||||
|
private final int BUFFER_SIZE = 65536;
|
||||||
|
|
||||||
|
byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
|
// position in buffer
|
||||||
|
int bufferPos;
|
||||||
|
|
||||||
|
// bytes available in buffer
|
||||||
|
int bufferFill;
|
||||||
|
|
||||||
|
// overall bytes of content read
|
||||||
|
private int mReadPos;
|
||||||
|
|
||||||
|
private int mMaxReq = 0;
|
||||||
|
private Socket mSocket;
|
||||||
|
private OutputStream mCommandStream;
|
||||||
|
private InputStream mResponseStream;
|
||||||
|
long mLastRequest = 0;
|
||||||
|
private SocketAddress mSockAddr;
|
||||||
|
|
||||||
|
private final static byte[] RESPONSE_HTTP_OK = "HTTP/1.1 200 OK".getBytes();
|
||||||
|
private final static int RESPONSE_EXPECTED_LIVES = 100;
|
||||||
|
private final static int RESPONSE_EXPECTED_TIMEOUT = 10000;
|
||||||
|
|
||||||
|
private byte[] REQUEST_GET_START;
|
||||||
|
private byte[] REQUEST_GET_END;
|
||||||
|
|
||||||
|
private byte[] mRequestBuffer;
|
||||||
|
|
||||||
|
boolean setServer(String urlString) {
|
||||||
|
URL url;
|
||||||
|
try {
|
||||||
|
url = new URL(urlString);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
//return new OpenResult("invalid url: " + options.get("url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = url.getPort();
|
||||||
|
if (port < 0)
|
||||||
|
port = 80;
|
||||||
|
|
||||||
|
String host = url.getHost();
|
||||||
|
String path = url.getPath();
|
||||||
|
Log.d(TAG, "open oscim database: " + host + " " + port + " " + path);
|
||||||
|
|
||||||
|
REQUEST_GET_START = ("GET " + path).getBytes();
|
||||||
|
REQUEST_GET_END = (".osmtile HTTP/1.1\n" +
|
||||||
|
"Host: " + host + "\n" +
|
||||||
|
"Connection: Keep-Alive\n\n").getBytes();
|
||||||
|
|
||||||
|
mHost = host;
|
||||||
|
mPort = port;
|
||||||
|
|
||||||
|
mRequestBuffer = new byte[1024];
|
||||||
|
System.arraycopy(REQUEST_GET_START, 0,
|
||||||
|
mRequestBuffer, 0, REQUEST_GET_START.length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
if (mSocket != null) {
|
||||||
|
try {
|
||||||
|
mSocket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
mSocket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int readHeader() throws IOException {
|
||||||
|
InputStream is = mResponseStream;
|
||||||
|
|
||||||
|
byte[] buf = buffer;
|
||||||
|
boolean first = true;
|
||||||
|
int read = 0;
|
||||||
|
int pos = 0;
|
||||||
|
int end = 0;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
// header cannot be larger than BUFFER_SIZE for this to work
|
||||||
|
for (; pos < read || (len = is.read(buf, read, BUFFER_SIZE - read)) >= 0; len = 0) {
|
||||||
|
read += len;
|
||||||
|
while (end < read && (buf[end] != '\n'))
|
||||||
|
end++;
|
||||||
|
|
||||||
|
if (buf[end] == '\n') {
|
||||||
|
if (first) {
|
||||||
|
// check only for OK
|
||||||
|
first = false;
|
||||||
|
if (!compareBytes(buf, pos, end, RESPONSE_HTTP_OK, 15))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
} else if (end - pos == 1) {
|
||||||
|
// check empty line (header end)
|
||||||
|
end += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// String line = new String(buf, pos, end - pos - 1);
|
||||||
|
// Log.d(TAG, ">" + line + "< " + resp_len);
|
||||||
|
|
||||||
|
pos += (end - pos) + 1;
|
||||||
|
end = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check 4 bytes available..
|
||||||
|
while ((read - end) < 4 && (len = is.read(buf, read, BUFFER_SIZE - read)) >= 0)
|
||||||
|
read += len;
|
||||||
|
|
||||||
|
if (read - len < 4)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int contentLength = decodeInt(buf, end);
|
||||||
|
mContentLenth = contentLength;
|
||||||
|
|
||||||
|
// buffer fill
|
||||||
|
bufferFill = read;
|
||||||
|
// start of content
|
||||||
|
bufferPos = end + 4;
|
||||||
|
// bytes of content already read into buffer
|
||||||
|
mReadPos = read - bufferPos;
|
||||||
|
|
||||||
|
mInputStream = mResponseStream;
|
||||||
|
|
||||||
|
return contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean sendRequest(Tile tile) throws IOException {
|
||||||
|
|
||||||
|
bufferFill = 0;
|
||||||
|
bufferPos = 0;
|
||||||
|
mReadPos = 0;
|
||||||
|
mCacheFile = null;
|
||||||
|
|
||||||
|
if (mSocket != null && ((mMaxReq-- <= 0)
|
||||||
|
|| (SystemClock.elapsedRealtime() - mLastRequest
|
||||||
|
> RESPONSE_EXPECTED_TIMEOUT))) {
|
||||||
|
try {
|
||||||
|
mSocket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log.d(TAG, "not alive - recreate connection " + mMaxReq);
|
||||||
|
mSocket = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSocket == null) {
|
||||||
|
lwHttpConnect();
|
||||||
|
// we know our server
|
||||||
|
mMaxReq = RESPONSE_EXPECTED_LIVES;
|
||||||
|
// Log.d(TAG, "create connection");
|
||||||
|
} else {
|
||||||
|
// should not be needed
|
||||||
|
int avail = mResponseStream.available();
|
||||||
|
if (avail > 0) {
|
||||||
|
Log.d(TAG, "Consume left-over bytes: " + avail);
|
||||||
|
mResponseStream.read(buffer, 0, avail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] request = mRequestBuffer;
|
||||||
|
int pos = REQUEST_GET_START.length;
|
||||||
|
|
||||||
|
pos = writeInt(tile.zoomLevel, pos, request);
|
||||||
|
request[pos++] = '/';
|
||||||
|
pos = writeInt(tile.tileX, pos, request);
|
||||||
|
request[pos++] = '/';
|
||||||
|
pos = writeInt(tile.tileY, pos, request);
|
||||||
|
|
||||||
|
int len = REQUEST_GET_END.length;
|
||||||
|
System.arraycopy(REQUEST_GET_END, 0, request, pos, len);
|
||||||
|
len += pos;
|
||||||
|
|
||||||
|
// this does the same but with a few more allocations:
|
||||||
|
// byte[] request = String.format(REQUEST,
|
||||||
|
// Integer.valueOf(tile.zoomLevel),
|
||||||
|
// Integer.valueOf(tile.tileX), Integer.valueOf(tile.tileY)).getBytes();
|
||||||
|
|
||||||
|
try {
|
||||||
|
mCommandStream.write(request, 0, len);
|
||||||
|
mCommandStream.flush();
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d(TAG, "recreate connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
lwHttpConnect();
|
||||||
|
|
||||||
|
mCommandStream.write(request, 0, len);
|
||||||
|
mCommandStream.flush();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean lwHttpConnect() throws IOException {
|
||||||
|
if (mSockAddr == null)
|
||||||
|
mSockAddr = new InetSocketAddress(mHost, mPort);
|
||||||
|
|
||||||
|
mSocket = new Socket();
|
||||||
|
mSocket.connect(mSockAddr, 30000);
|
||||||
|
mSocket.setTcpNoDelay(true);
|
||||||
|
|
||||||
|
mCommandStream = mSocket.getOutputStream(); //new BufferedOutputStream();
|
||||||
|
mResponseStream = mSocket.getInputStream();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write (positive) integer as char sequence to buffer
|
||||||
|
private static int writeInt(int val, int pos, byte[] buf) {
|
||||||
|
if (val == 0) {
|
||||||
|
buf[pos] = '0';
|
||||||
|
return pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (int n = val; n > 0; n = n / 10, i++)
|
||||||
|
buf[pos + i] = (byte) ('0' + n % 10);
|
||||||
|
|
||||||
|
// reverse bytes
|
||||||
|
for (int j = pos, end = pos + i - 1, mid = pos + i / 2; j < mid; j++, end--) {
|
||||||
|
byte tmp = buf[j];
|
||||||
|
buf[j] = buf[end];
|
||||||
|
buf[end] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean compareBytes(byte[] buffer, int position, int available,
|
||||||
|
byte[] string, int length) {
|
||||||
|
|
||||||
|
if (available - position < length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
if (buffer[position + i] != string[i])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int decodeInt(byte[] buffer, int offset) {
|
||||||
|
return buffer[offset] << 24 | (buffer[offset + 1] & 0xff) << 16
|
||||||
|
| (buffer[offset + 2] & 0xff) << 8
|
||||||
|
| (buffer[offset + 3] & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void readBuffer(int size) throws IOException {
|
||||||
|
|
||||||
|
// check if buffer already contains the request bytes
|
||||||
|
if (bufferPos + size < bufferFill)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check if inputstream is read to the end
|
||||||
|
if (mReadPos == mContentLenth)
|
||||||
|
return;
|
||||||
|
int maxSize = buffer.length;
|
||||||
|
|
||||||
|
if (size > maxSize) {
|
||||||
|
Log.d(TAG, "increase read buffer to " + size + " bytes");
|
||||||
|
maxSize = size;
|
||||||
|
byte[] tmp = new byte[maxSize];
|
||||||
|
|
||||||
|
bufferFill -= bufferPos;
|
||||||
|
System.arraycopy(buffer, bufferPos, tmp, 0, bufferFill);
|
||||||
|
bufferPos = 0;
|
||||||
|
buffer = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferFill == bufferPos) {
|
||||||
|
bufferPos = 0;
|
||||||
|
bufferFill = 0;
|
||||||
|
} else if (bufferPos + size > maxSize) {
|
||||||
|
// copy bytes left to the beginning of buffer
|
||||||
|
bufferFill -= bufferPos;
|
||||||
|
System.arraycopy(buffer, bufferPos, buffer, 0, bufferFill);
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max = maxSize - bufferFill;
|
||||||
|
|
||||||
|
while ((bufferFill - bufferPos) < size && max > 0) {
|
||||||
|
|
||||||
|
max = maxSize - bufferFill;
|
||||||
|
if (max > mContentLenth - mReadPos)
|
||||||
|
max = (int) (mContentLenth - mReadPos);
|
||||||
|
|
||||||
|
// read until requested size is available in buffer
|
||||||
|
int len = mInputStream.read(buffer, bufferFill, max);
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
// finished reading, mark end
|
||||||
|
buffer[bufferFill] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mReadPos += len;
|
||||||
|
|
||||||
|
// if (mCacheFile != null)
|
||||||
|
// mCacheFile.write(mReadBuffer, mBufferFill, len);
|
||||||
|
|
||||||
|
if (mReadPos == mContentLenth)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bufferFill += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileOutputStream mCacheFile;
|
||||||
|
|
||||||
|
boolean cacheRead(Tile tile, File f) {
|
||||||
|
if (f.exists() && f.length() > 0) {
|
||||||
|
FileInputStream in;
|
||||||
|
|
||||||
|
try {
|
||||||
|
in = new FileInputStream(f);
|
||||||
|
|
||||||
|
mContentLenth = f.length();
|
||||||
|
Log.d(TAG, tile + " - using cache: " + mContentLenth);
|
||||||
|
mInputStream = in;
|
||||||
|
|
||||||
|
//decode();
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
f.delete();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean cacheBegin(Tile tile, File f) {
|
||||||
|
if (MapDatabase.USE_CACHE) {
|
||||||
|
try {
|
||||||
|
Log.d(TAG, tile + " - writing cache");
|
||||||
|
mCacheFile = new FileOutputStream(f);
|
||||||
|
|
||||||
|
if (mReadPos > 0) {
|
||||||
|
try {
|
||||||
|
mCacheFile.write(buffer, bufferPos,
|
||||||
|
bufferFill - bufferPos);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
mCacheFile = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
mCacheFile = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cacheFinish(Tile tile, File file, boolean success) {
|
||||||
|
if (MapDatabase.USE_CACHE) {
|
||||||
|
if (success) {
|
||||||
|
try {
|
||||||
|
mCacheFile.flush();
|
||||||
|
mCacheFile.close();
|
||||||
|
Log.d(TAG, tile + " - cache written " + file.length());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCacheFile = null;
|
||||||
|
}
|
||||||
|
}
|
@ -15,19 +15,9 @@
|
|||||||
package org.oscim.database.oscimap;
|
package org.oscim.database.oscimap;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.net.URL;
|
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -52,48 +42,42 @@ import android.util.Log;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class MapDatabase implements IMapDatabase {
|
public class MapDatabase implements IMapDatabase {
|
||||||
private static final String TAG = "MapDatabase";
|
private static final String TAG = MapDatabase.class.getName();
|
||||||
|
|
||||||
|
static final boolean USE_CACHE = false;
|
||||||
|
|
||||||
private static final MapInfo mMapInfo =
|
private static final MapInfo mMapInfo =
|
||||||
new MapInfo(new BoundingBox(-180, -90, 180, 90),
|
new MapInfo(new BoundingBox(-180, -90, 180, 90),
|
||||||
new Byte((byte) 4), new GeoPoint(53.11, 8.85),
|
new Byte((byte) 4), new GeoPoint(53.11, 8.85),
|
||||||
null, 0, 0, 0, "de", "comment", "author", null);
|
null, 0, 0, 0, "de", "comment", "author", null);
|
||||||
|
|
||||||
private boolean mOpenFile = false;
|
|
||||||
|
|
||||||
private static final boolean USE_CACHE = false;
|
|
||||||
private static final String CACHE_DIRECTORY = "/Android/data/org.oscim.app/cache/";
|
private static final String CACHE_DIRECTORY = "/Android/data/org.oscim.app/cache/";
|
||||||
private static final String CACHE_FILE = "%d-%d-%d.tile";
|
private static final String CACHE_FILE = "%d-%d-%d.tile";
|
||||||
|
|
||||||
//private static String SERVER_ADDR = "city.informatik.uni-bremen.de";
|
|
||||||
//private static int PORT = 80;
|
|
||||||
//private static final String URL = "/osci/map-live/";
|
|
||||||
//private static String TILE_URL = "/osci/oscim/";
|
|
||||||
|
|
||||||
private final static float REF_TILE_SIZE = 4096.0f;
|
private final static float REF_TILE_SIZE = 4096.0f;
|
||||||
|
|
||||||
|
// 'open' state
|
||||||
|
private boolean mOpen = false;
|
||||||
private static File cacheDir;
|
private static File cacheDir;
|
||||||
|
|
||||||
private int MAX_TILE_TAGS = 100;
|
private final int MAX_TILE_TAGS = 100;
|
||||||
private Tag[] curTags = new Tag[MAX_TILE_TAGS];
|
private Tag[] curTags = new Tag[MAX_TILE_TAGS];
|
||||||
private int mCurTagCnt;
|
private int mCurTagCnt;
|
||||||
|
|
||||||
private IMapDatabaseCallback mMapGenerator;
|
private IMapDatabaseCallback mMapGenerator;
|
||||||
private float mScaleFactor;
|
private float mScaleFactor;
|
||||||
private JobTile mTile;
|
private JobTile mTile;
|
||||||
private FileOutputStream mCacheFile;
|
|
||||||
|
|
||||||
private String mHost;
|
|
||||||
private int mPort;
|
|
||||||
private long mContentLenth;
|
private long mContentLenth;
|
||||||
private InputStream mInputStream;
|
|
||||||
|
|
||||||
private final boolean debug = false;
|
private final boolean debug = false;
|
||||||
|
private LwHttp lwHttp;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
||||||
QueryResult result = QueryResult.SUCCESS;
|
QueryResult result = QueryResult.SUCCESS;
|
||||||
mCacheFile = null;
|
|
||||||
|
|
||||||
mTile = tile;
|
mTile = tile;
|
||||||
|
|
||||||
@ -104,24 +88,20 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
File f = null;
|
File f = null;
|
||||||
|
|
||||||
mBufferFill = 0;
|
|
||||||
mBufferPos = 0;
|
|
||||||
mReadPos = 0;
|
|
||||||
|
|
||||||
if (USE_CACHE) {
|
if (USE_CACHE) {
|
||||||
f = new File(cacheDir, String.format(CACHE_FILE,
|
f = new File(cacheDir, String.format(CACHE_FILE,
|
||||||
Integer.valueOf(tile.zoomLevel),
|
Integer.valueOf(tile.zoomLevel),
|
||||||
Integer.valueOf(tile.tileX),
|
Integer.valueOf(tile.tileX),
|
||||||
Integer.valueOf(tile.tileY)));
|
Integer.valueOf(tile.tileY)));
|
||||||
|
|
||||||
if (cacheRead(tile, f))
|
if (lwHttp.cacheRead(tile, f))
|
||||||
return QueryResult.SUCCESS;
|
return QueryResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (lwHttpSendRequest(tile) && lwHttpReadHeader() >= 0) {
|
if (lwHttp.sendRequest(tile) && (mContentLenth = lwHttp.readHeader()) >= 0) {
|
||||||
cacheBegin(tile, f);
|
lwHttp.cacheBegin(tile, f);
|
||||||
decode();
|
decode();
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, tile + " Network Error");
|
Log.d(TAG, tile + " Network Error");
|
||||||
@ -141,22 +121,14 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
result = QueryResult.FAILED;
|
result = QueryResult.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastRequest = SystemClock.elapsedRealtime();
|
lwHttp.mLastRequest = SystemClock.elapsedRealtime();
|
||||||
|
|
||||||
if (result == QueryResult.SUCCESS) {
|
if (result == QueryResult.SUCCESS) {
|
||||||
|
|
||||||
cacheFinish(tile, f, true);
|
lwHttp.cacheFinish(tile, f, true);
|
||||||
} else {
|
} else {
|
||||||
cacheFinish(tile, f, false);
|
lwHttp.cacheFinish(tile, f, false);
|
||||||
if (mSocket != null) {
|
lwHttp.close();
|
||||||
// clear connection, TODO cleanup properly
|
|
||||||
try {
|
|
||||||
mSocket.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
mSocket = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -173,47 +145,23 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOpen() {
|
public boolean isOpen() {
|
||||||
return mOpenFile;
|
return mOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenResult open(MapOptions options) {
|
public OpenResult open(MapOptions options) {
|
||||||
if (mOpenFile)
|
if (mOpen)
|
||||||
return OpenResult.SUCCESS;
|
return OpenResult.SUCCESS;
|
||||||
|
|
||||||
if (options == null || !options.containsKey("url"))
|
if (options == null || !options.containsKey("url"))
|
||||||
return new OpenResult("options missing");
|
return new OpenResult("options missing");
|
||||||
|
|
||||||
URL url;
|
lwHttp = new LwHttp();
|
||||||
try {
|
|
||||||
url = new URL(options.get("url"));
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
|
|
||||||
e.printStackTrace();
|
if (!lwHttp.setServer(options.get("url"))){
|
||||||
return new OpenResult("invalid url: " + options.get("url"));
|
return new OpenResult("invalid url: " + options.get("url"));
|
||||||
}
|
}
|
||||||
|
|
||||||
int port = url.getPort();
|
|
||||||
if (port < 0)
|
|
||||||
port = 80;
|
|
||||||
|
|
||||||
String host = url.getHost();
|
|
||||||
String path = url.getPath();
|
|
||||||
Log.d(TAG, "open oscim database: " + host + " " + port + " " + path);
|
|
||||||
|
|
||||||
REQUEST_GET_START = ("GET " + path).getBytes();
|
|
||||||
REQUEST_GET_END = (".osmtile HTTP/1.1\n" +
|
|
||||||
"Host: " + host + "\n" +
|
|
||||||
"Connection: Keep-Alive\n\n").getBytes();
|
|
||||||
|
|
||||||
mHost = host;
|
|
||||||
mPort = port;
|
|
||||||
//mSockAddr = new InetSocketAddress(host, port);
|
|
||||||
|
|
||||||
mRequestBuffer = new byte[1024];
|
|
||||||
System.arraycopy(REQUEST_GET_START, 0,
|
|
||||||
mRequestBuffer, 0, REQUEST_GET_START.length);
|
|
||||||
|
|
||||||
if (USE_CACHE) {
|
if (USE_CACHE) {
|
||||||
if (cacheDir == null) {
|
if (cacheDir == null) {
|
||||||
String externalStorageDirectory = Environment
|
String externalStorageDirectory = Environment
|
||||||
@ -224,7 +172,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mOpenFile = true;
|
mOpen = true;
|
||||||
|
|
||||||
initDecorder();
|
initDecorder();
|
||||||
|
|
||||||
@ -233,17 +181,9 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
mOpenFile = false;
|
mOpen = false;
|
||||||
|
|
||||||
if (mSocket != null) {
|
lwHttp.close();
|
||||||
try {
|
|
||||||
mSocket.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
mSocket = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (USE_CACHE) {
|
if (USE_CACHE) {
|
||||||
cacheDir = null;
|
cacheDir = null;
|
||||||
@ -270,21 +210,20 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
// /////////////// hand sewed tile protocol buffers decoder ///////////////
|
// /////////////// hand sewed tile protocol buffers decoder ///////////////
|
||||||
private final int MAX_WAY_COORDS = 16384;
|
private final int MAX_WAY_COORDS = 16384;
|
||||||
private final int BUFFER_SIZE = 65536;
|
|
||||||
|
|
||||||
private byte[] mReadBuffer = new byte[BUFFER_SIZE];
|
//private final byte[] mReadBuffer = new byte[BUFFER_SIZE];
|
||||||
|
|
||||||
// position in buffer
|
// position in buffer
|
||||||
private int mBufferPos;
|
// private int mBufferPos;
|
||||||
|
|
||||||
// bytes available in buffer
|
// bytes available in buffer
|
||||||
private int mBufferFill;
|
// private int mBufferFill;
|
||||||
|
|
||||||
// overall bytes of content processed
|
// overall bytes of content processed
|
||||||
private int mBytesProcessed;
|
private int mBytesProcessed;
|
||||||
|
|
||||||
// overall bytes of content read
|
// overall bytes of content read
|
||||||
private int mReadPos;
|
// private int mReadPos;
|
||||||
|
|
||||||
private static final int TAG_TILE_NUM_TAGS = 1;
|
private static final int TAG_TILE_NUM_TAGS = 1;
|
||||||
private static final int TAG_TILE_TAG_KEYS = 2;
|
private static final int TAG_TILE_TAG_KEYS = 2;
|
||||||
@ -305,7 +244,7 @@ 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[20];
|
private final Tag[] mTmpTags = new Tag[20];
|
||||||
|
|
||||||
private float[] mTmpCoords;
|
private float[] mTmpCoords;
|
||||||
|
|
||||||
@ -533,17 +472,17 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
private int decodeWayCoordinates(boolean skip, int nodes) throws IOException {
|
private int decodeWayCoordinates(boolean skip, int nodes) throws IOException {
|
||||||
int bytes = decodeVarint32();
|
int bytes = decodeVarint32();
|
||||||
|
|
||||||
readBuffer(bytes);
|
lwHttp.readBuffer(bytes);
|
||||||
|
|
||||||
if (skip) {
|
if (skip) {
|
||||||
mBufferPos += bytes;
|
lwHttp.bufferPos += bytes;
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pos = mBufferPos;
|
int pos = lwHttp.bufferPos;
|
||||||
int end = pos + bytes;
|
int end = pos + bytes;
|
||||||
float[] coords = mTmpCoords;
|
float[] coords = mTmpCoords;
|
||||||
byte[] buf = mReadBuffer;
|
byte[] buf = lwHttp.buffer;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
@ -606,73 +545,12 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mBufferPos = pos;
|
lwHttp.bufferPos = pos;
|
||||||
mBytesProcessed += bytes;
|
mBytesProcessed += bytes;
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBuffer(int size) throws IOException {
|
|
||||||
|
|
||||||
// check if buffer already contains the request bytes
|
|
||||||
if (mBufferPos + size < mBufferFill)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// check if inputstream is read to the end
|
|
||||||
if (mReadPos == mContentLenth)
|
|
||||||
return;
|
|
||||||
int maxSize = mReadBuffer.length;
|
|
||||||
|
|
||||||
if (size > maxSize) {
|
|
||||||
Log.d(TAG, mTile + "increase read buffer to " + size + " bytes");
|
|
||||||
maxSize = size;
|
|
||||||
byte[] tmp = new byte[maxSize];
|
|
||||||
|
|
||||||
mBufferFill -= mBufferPos;
|
|
||||||
System.arraycopy(mReadBuffer, mBufferPos, tmp, 0, mBufferFill);
|
|
||||||
mBufferPos = 0;
|
|
||||||
mReadBuffer = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mBufferFill == mBufferPos) {
|
|
||||||
mBufferPos = 0;
|
|
||||||
mBufferFill = 0;
|
|
||||||
} else if (mBufferPos + size > maxSize) {
|
|
||||||
// copy bytes left to the beginning of buffer
|
|
||||||
mBufferFill -= mBufferPos;
|
|
||||||
System.arraycopy(mReadBuffer, mBufferPos, mReadBuffer, 0, mBufferFill);
|
|
||||||
mBufferPos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int max = maxSize - mBufferFill;
|
|
||||||
|
|
||||||
while ((mBufferFill - mBufferPos) < size && max > 0) {
|
|
||||||
|
|
||||||
max = maxSize - mBufferFill;
|
|
||||||
if (max > mContentLenth - mReadPos)
|
|
||||||
max = (int) (mContentLenth - mReadPos);
|
|
||||||
|
|
||||||
// read until requested size is available in buffer
|
|
||||||
int len = mInputStream.read(mReadBuffer, mBufferFill, max);
|
|
||||||
|
|
||||||
if (len < 0) {
|
|
||||||
// finished reading, mark end
|
|
||||||
mReadBuffer[mBufferFill] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mReadPos += len;
|
|
||||||
|
|
||||||
if (mCacheFile != null)
|
|
||||||
mCacheFile.write(mReadBuffer, mBufferFill, len);
|
|
||||||
|
|
||||||
if (mReadPos == mContentLenth)
|
|
||||||
break;
|
|
||||||
|
|
||||||
mBufferFill += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private short[] decodeShortArray(int num, short[] array) throws IOException {
|
private short[] decodeShortArray(int num, short[] array) throws IOException {
|
||||||
int bytes = decodeVarint32();
|
int bytes = decodeVarint32();
|
||||||
|
|
||||||
@ -681,13 +559,13 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
index = new short[num];
|
index = new short[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
readBuffer(bytes);
|
lwHttp.readBuffer(bytes);
|
||||||
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
int pos = mBufferPos;
|
int pos = lwHttp.bufferPos;
|
||||||
int end = pos + bytes;
|
int end = pos + bytes;
|
||||||
byte[] buf = mReadBuffer;
|
byte[] buf = lwHttp.buffer;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
while (pos < end) {
|
while (pos < end) {
|
||||||
@ -730,40 +608,40 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
index[cnt++] = (short) result;
|
index[cnt++] = (short) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
mBufferPos = pos;
|
lwHttp.bufferPos = pos;
|
||||||
mBytesProcessed += bytes;
|
mBytesProcessed += bytes;
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int decodeVarint32() throws IOException {
|
private int decodeVarint32() throws IOException {
|
||||||
int pos = mBufferPos;
|
int pos = lwHttp.bufferPos;
|
||||||
|
|
||||||
if (pos + 10 > mBufferFill) {
|
if (pos + 10 > lwHttp.bufferFill) {
|
||||||
readBuffer(4096);
|
lwHttp.readBuffer(4096);
|
||||||
pos = mBufferPos;
|
pos = lwHttp.bufferPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] buf = mReadBuffer;
|
byte[] buf =lwHttp.buffer;
|
||||||
|
|
||||||
if (buf[pos] >= 0) {
|
if (buf[pos] >= 0) {
|
||||||
mBufferPos += 1;
|
lwHttp.bufferPos += 1;
|
||||||
mBytesProcessed += 1;
|
mBytesProcessed += 1;
|
||||||
return buf[pos];
|
return buf[pos];
|
||||||
} else if (buf[pos + 1] >= 0) {
|
} else if (buf[pos + 1] >= 0) {
|
||||||
mBufferPos += 2;
|
lwHttp.bufferPos += 2;
|
||||||
mBytesProcessed += 2;
|
mBytesProcessed += 2;
|
||||||
return (buf[pos] & 0x7f)
|
return (buf[pos] & 0x7f)
|
||||||
| (buf[pos + 1]) << 7;
|
| (buf[pos + 1]) << 7;
|
||||||
|
|
||||||
} else if (buf[pos + 2] >= 0) {
|
} else if (buf[pos + 2] >= 0) {
|
||||||
mBufferPos += 3;
|
lwHttp.bufferPos += 3;
|
||||||
mBytesProcessed += 3;
|
mBytesProcessed += 3;
|
||||||
return (buf[pos] & 0x7f)
|
return (buf[pos] & 0x7f)
|
||||||
| (buf[pos + 1] & 0x7f) << 7
|
| (buf[pos + 1] & 0x7f) << 7
|
||||||
| (buf[pos + 2]) << 14;
|
| (buf[pos + 2]) << 14;
|
||||||
} else if (buf[pos + 3] >= 0) {
|
} else if (buf[pos + 3] >= 0) {
|
||||||
mBufferPos += 4;
|
lwHttp.bufferPos += 4;
|
||||||
mBytesProcessed += 4;
|
mBytesProcessed += 4;
|
||||||
return (buf[pos] & 0x7f)
|
return (buf[pos] & 0x7f)
|
||||||
| (buf[pos + 1] & 0x7f) << 7
|
| (buf[pos + 1] & 0x7f) << 7
|
||||||
@ -788,7 +666,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
if (read == 10)
|
if (read == 10)
|
||||||
throw new IOException("X malformed VarInt32 in " + mTile);
|
throw new IOException("X malformed VarInt32 in " + mTile);
|
||||||
|
|
||||||
mBufferPos += read;
|
lwHttp.bufferPos += read;
|
||||||
mBytesProcessed += read;
|
mBytesProcessed += read;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -796,10 +674,10 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
|
|
||||||
private String decodeString() throws IOException {
|
private String decodeString() throws IOException {
|
||||||
final int size = decodeVarint32();
|
final int size = decodeVarint32();
|
||||||
readBuffer(size);
|
lwHttp.readBuffer(size);
|
||||||
final String result = new String(mReadBuffer, mBufferPos, size, "UTF-8");
|
final String result = new String(lwHttp.buffer, lwHttp.bufferPos, size, "UTF-8");
|
||||||
|
|
||||||
mBufferPos += size;
|
lwHttp.bufferPos += size;
|
||||||
mBytesProcessed += size;
|
mBytesProcessed += size;
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -811,264 +689,4 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
| (buffer[offset + 3] & 0xff);
|
| (buffer[offset + 3] & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ///////////////////////// Lightweight HttpClient ///////////////////////
|
|
||||||
|
|
||||||
private int mMaxReq = 0;
|
|
||||||
private Socket mSocket;
|
|
||||||
private OutputStream mCommandStream;
|
|
||||||
private InputStream mResponseStream;
|
|
||||||
private long mLastRequest = 0;
|
|
||||||
private SocketAddress mSockAddr;
|
|
||||||
|
|
||||||
private final static byte[] RESPONSE_HTTP_OK = "HTTP/1.1 200 OK".getBytes();
|
|
||||||
private final static int RESPONSE_EXPECTED_LIVES = 100;
|
|
||||||
private final static int RESPONSE_EXPECTED_TIMEOUT = 10000;
|
|
||||||
|
|
||||||
private byte[] REQUEST_GET_START;
|
|
||||||
private byte[] REQUEST_GET_END;
|
|
||||||
|
|
||||||
private byte[] mRequestBuffer;
|
|
||||||
|
|
||||||
int lwHttpReadHeader() throws IOException {
|
|
||||||
InputStream is = mResponseStream;
|
|
||||||
|
|
||||||
byte[] buf = mReadBuffer;
|
|
||||||
boolean first = true;
|
|
||||||
int read = 0;
|
|
||||||
int pos = 0;
|
|
||||||
int end = 0;
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
// header cannot be larger than BUFFER_SIZE for this to work
|
|
||||||
for (; pos < read || (len = is.read(buf, read, BUFFER_SIZE - read)) >= 0; len = 0) {
|
|
||||||
read += len;
|
|
||||||
while (end < read && (buf[end] != '\n'))
|
|
||||||
end++;
|
|
||||||
|
|
||||||
if (buf[end] == '\n') {
|
|
||||||
if (first) {
|
|
||||||
// check only for OK
|
|
||||||
first = false;
|
|
||||||
if (!compareBytes(buf, pos, end, RESPONSE_HTTP_OK, 15))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
} else if (end - pos == 1) {
|
|
||||||
// check empty line (header end)
|
|
||||||
end += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// String line = new String(buf, pos, end - pos - 1);
|
|
||||||
// Log.d(TAG, ">" + line + "< " + resp_len);
|
|
||||||
|
|
||||||
pos += (end - pos) + 1;
|
|
||||||
end = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check 4 bytes available..
|
|
||||||
while ((read - end) < 4 && (len = is.read(buf, read, BUFFER_SIZE - read)) >= 0)
|
|
||||||
read += len;
|
|
||||||
|
|
||||||
if (read - len < 4)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
mContentLenth = decodeInt(buf, end);
|
|
||||||
|
|
||||||
// buffer fill
|
|
||||||
mBufferFill = read;
|
|
||||||
// start of content
|
|
||||||
mBufferPos = end + 4;
|
|
||||||
// bytes of content already read into buffer
|
|
||||||
mReadPos = read - mBufferPos;
|
|
||||||
|
|
||||||
mInputStream = mResponseStream;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean lwHttpSendRequest(Tile tile) throws IOException {
|
|
||||||
|
|
||||||
if (mSocket != null && ((mMaxReq-- <= 0)
|
|
||||||
|| (SystemClock.elapsedRealtime() - mLastRequest
|
|
||||||
> RESPONSE_EXPECTED_TIMEOUT))) {
|
|
||||||
try {
|
|
||||||
mSocket.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log.d(TAG, "not alive - recreate connection " + mMaxReq);
|
|
||||||
mSocket = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSocket == null) {
|
|
||||||
lwHttpConnect();
|
|
||||||
// we know our server
|
|
||||||
mMaxReq = RESPONSE_EXPECTED_LIVES;
|
|
||||||
// Log.d(TAG, "create connection");
|
|
||||||
} else {
|
|
||||||
// should not be needed
|
|
||||||
int avail = mResponseStream.available();
|
|
||||||
if (avail > 0) {
|
|
||||||
Log.d(TAG, "Consume left-over bytes: " + avail);
|
|
||||||
mResponseStream.read(mReadBuffer, 0, avail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] request = mRequestBuffer;
|
|
||||||
int pos = REQUEST_GET_START.length;
|
|
||||||
|
|
||||||
pos = writeInt(tile.zoomLevel, pos, request);
|
|
||||||
request[pos++] = '/';
|
|
||||||
pos = writeInt(tile.tileX, pos, request);
|
|
||||||
request[pos++] = '/';
|
|
||||||
pos = writeInt(tile.tileY, pos, request);
|
|
||||||
|
|
||||||
int len = REQUEST_GET_END.length;
|
|
||||||
System.arraycopy(REQUEST_GET_END, 0, request, pos, len);
|
|
||||||
len += pos;
|
|
||||||
|
|
||||||
// this does the same but with a few more allocations:
|
|
||||||
// byte[] request = String.format(REQUEST,
|
|
||||||
// Integer.valueOf(tile.zoomLevel),
|
|
||||||
// Integer.valueOf(tile.tileX), Integer.valueOf(tile.tileY)).getBytes();
|
|
||||||
|
|
||||||
try {
|
|
||||||
mCommandStream.write(request, 0, len);
|
|
||||||
mCommandStream.flush();
|
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, mTile + " recreate connection");
|
|
||||||
}
|
|
||||||
|
|
||||||
lwHttpConnect();
|
|
||||||
|
|
||||||
mCommandStream.write(request, 0, len);
|
|
||||||
mCommandStream.flush();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean lwHttpConnect() throws IOException {
|
|
||||||
if (mSockAddr == null)
|
|
||||||
mSockAddr = new InetSocketAddress(mHost, mPort);
|
|
||||||
|
|
||||||
mSocket = new Socket();
|
|
||||||
mSocket.connect(mSockAddr, 30000);
|
|
||||||
mSocket.setTcpNoDelay(true);
|
|
||||||
|
|
||||||
mCommandStream = mSocket.getOutputStream(); //new BufferedOutputStream();
|
|
||||||
mResponseStream = mSocket.getInputStream();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write (positive) integer as char sequence to buffer
|
|
||||||
private static int writeInt(int val, int pos, byte[] buf) {
|
|
||||||
if (val == 0) {
|
|
||||||
buf[pos] = '0';
|
|
||||||
return pos + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (int n = val; n > 0; n = n / 10, i++)
|
|
||||||
buf[pos + i] = (byte) ('0' + n % 10);
|
|
||||||
|
|
||||||
// reverse bytes
|
|
||||||
for (int j = pos, end = pos + i - 1, mid = pos + i / 2; j < mid; j++, end--) {
|
|
||||||
byte tmp = buf[j];
|
|
||||||
buf[j] = buf[end];
|
|
||||||
buf[end] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean compareBytes(byte[] buffer, int position, int available,
|
|
||||||
byte[] string, int length) {
|
|
||||||
|
|
||||||
if (available - position < length)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
if (buffer[position + i] != string[i])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ///////////////////////// Tile cache /////////////////////////////////
|
|
||||||
|
|
||||||
private boolean cacheRead(Tile tile, File f) {
|
|
||||||
if (f.exists() && f.length() > 0) {
|
|
||||||
FileInputStream in;
|
|
||||||
|
|
||||||
try {
|
|
||||||
in = new FileInputStream(f);
|
|
||||||
|
|
||||||
mContentLenth = f.length();
|
|
||||||
Log.d(TAG, tile + " - using cache: " + mContentLenth);
|
|
||||||
mInputStream = in;
|
|
||||||
|
|
||||||
decode();
|
|
||||||
in.close();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
f.delete();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cacheBegin(Tile tile, File f) {
|
|
||||||
if (USE_CACHE) {
|
|
||||||
try {
|
|
||||||
Log.d(TAG, tile + " - writing cache");
|
|
||||||
mCacheFile = new FileOutputStream(f);
|
|
||||||
|
|
||||||
if (mReadPos > 0) {
|
|
||||||
try {
|
|
||||||
mCacheFile.write(mReadBuffer, mBufferPos,
|
|
||||||
mBufferFill - mBufferPos);
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
mCacheFile = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
mCacheFile = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cacheFinish(Tile tile, File file, boolean success) {
|
|
||||||
if (USE_CACHE) {
|
|
||||||
if (success) {
|
|
||||||
try {
|
|
||||||
mCacheFile.flush();
|
|
||||||
mCacheFile.close();
|
|
||||||
Log.d(TAG, tile + " - cache written " + file.length());
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mCacheFile = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user