optimize featching source data

This commit is contained in:
Alexey Danilov
2015-09-11 15:37:21 +03:00
parent c0ef7dd1b1
commit f8f19c5a5c
11 changed files with 60 additions and 41 deletions

View File

@@ -150,6 +150,7 @@ public class HttpProxyCacheServer {
onError(new ProxyCacheException("Error processing request", e));
} finally {
releaseSocket(socket);
Log.d(LOG_TAG, "Opened connections: " + getClientsCount());
}
}
@@ -164,6 +165,16 @@ public class HttpProxyCacheServer {
}
}
private int getClientsCount() {
synchronized (clientsLock) {
int count = 0;
for (HttpProxyCacheServerClients clients : clientsMap.values()) {
count += clients.getClientsCount();
}
return count;
}
}
private void releaseSocket(Socket socket) {
closeSocketInput(socket);
closeSocketOutput(socket);

View File

@@ -34,16 +34,23 @@ final class HttpProxyCacheServerClients {
}
public void processRequest(GetRequest request, Socket socket) throws ProxyCacheException, IOException {
proxyCache = proxyCache == null ? newHttpProxyCache() : proxyCache;
startProcessRequest();
try {
clientsCount.incrementAndGet();
proxyCache.processRequest(request, socket);
} finally {
int count = clientsCount.decrementAndGet();
if (count <= 0) {
proxyCache.shutdown();
proxyCache = null;
}
finishProcessRequest();
}
}
private synchronized void startProcessRequest() throws ProxyCacheException {
proxyCache = proxyCache == null ? newHttpProxyCache() : proxyCache;
}
private synchronized void finishProcessRequest() {
if (clientsCount.decrementAndGet() <= 0) {
proxyCache.shutdown();
proxyCache = null;
}
}
@@ -65,6 +72,10 @@ final class HttpProxyCacheServerClients {
clientsCount.set(0);
}
public int getClientsCount() {
return clientsCount.get();
}
private HttpProxyCache newHttpProxyCache() throws ProxyCacheException {
HttpUrlSource source = new HttpUrlSource(url);
FileCache cache = new FileCache(fileNameGenerator.generate(url));

View File

@@ -3,12 +3,14 @@ package com.danikula.videocache;
import android.text.TextUtils;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.net.HttpURLConnection;
import java.net.URL;
import static com.danikula.videocache.ProxyCacheUtils.DEFAULT_BUFFER_SIZE;
import static com.danikula.videocache.ProxyCacheUtils.LOG_TAG;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.net.HttpURLConnection.HTTP_PARTIAL;
@@ -36,7 +38,7 @@ public class HttpUrlSource implements Source {
}
@Override
public int available() throws ProxyCacheException {
public synchronized int available() throws ProxyCacheException {
if (available == Integer.MIN_VALUE) {
fetchContentInfo();
}
@@ -52,7 +54,7 @@ public class HttpUrlSource implements Source {
connection.setRequestProperty("Range", "bytes=" + offset + "-");
}
mime = connection.getContentType();
inputStream = connection.getInputStream();
inputStream = new BufferedInputStream(connection.getInputStream(), DEFAULT_BUFFER_SIZE);
available = readSourceAvailableBytes(connection, offset);
} catch (IOException e) {
throw new ProxyCacheException("Error opening connection for " + url + " with offset " + offset, e);
@@ -91,22 +93,27 @@ public class HttpUrlSource implements Source {
private void fetchContentInfo() throws ProxyCacheException {
Log.d(LOG_TAG, "Read content info from " + url);
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.setConnectTimeout(10000);
urlConnection.setReadTimeout(10000);
urlConnection.setRequestMethod("HEAD");
available = urlConnection.getContentLength();
mime = urlConnection.getContentType();
Log.i(LOG_TAG, "Info read: " + this);
inputStream = urlConnection.getInputStream();
Log.i(LOG_TAG, "Content info for `" + url + "`: mime: " + mime + ", content-length: " + available);
} catch (IOException e) {
throw new ProxyCacheException("Error fetching Content-Length from " + url);
} finally {
ProxyCacheUtils.close(inputStream);
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
public String getMime() throws ProxyCacheException {
public synchronized String getMime() throws ProxyCacheException {
if (TextUtils.isEmpty(mime)) {
fetchContentInfo();
}
@@ -115,10 +122,6 @@ public class HttpUrlSource implements Source {
@Override
public String toString() {
return "HttpUrlSource{" +
"url='" + url + '\'' +
", available=" + available +
", mime='" + mime + '\'' +
'}';
return "HttpUrlSource{url='" + url + "}";
}
}

View File

@@ -40,19 +40,11 @@ class ProxyCache {
while (!cache.isCompleted() && cache.available() < (offset + length) && !stopped) {
readSourceAsync();
waitForSourceData();
checkIsCacheValid();
checkReadSourceErrorsCount();
}
return cache.read(buffer, offset, length);
}
private void checkIsCacheValid() throws ProxyCacheException {
int sourceAvailable = source.available();
if (sourceAvailable > 0 && cache.available() > sourceAvailable) {
throw new ProxyCacheException("Unexpected cache: cache [" + cache.available() + " bytes] > source[" + sourceAvailable + " bytes]");
}
}
private void checkReadSourceErrorsCount() throws ProxyCacheException {
int errorsCount = readSourceErrorsCount.get();
if (errorsCount >= MAX_READ_SOURCE_ATTEMPTS) {
@@ -76,10 +68,10 @@ class ProxyCache {
}
}
private void readSourceAsync() throws ProxyCacheException {
private synchronized void readSourceAsync() throws ProxyCacheException {
boolean readingInProgress = sourceReaderThread != null && sourceReaderThread.getState() != Thread.State.TERMINATED;
if (!stopped && !cache.isCompleted() && !readingInProgress) {
sourceReaderThread = new Thread(new SourceReaderRunnable(), "Source reader for ProxyCache");
sourceReaderThread = new Thread(new SourceReaderRunnable(), "Source reader for " + source);
sourceReaderThread.start();
}
}
@@ -102,7 +94,7 @@ class ProxyCache {
}
}
protected void onCacheAvailable(int percents){
protected void onCacheAvailable(int percents) {
}
private void readSource() {

View File

@@ -1,8 +1,10 @@
package com.danikula.videocache;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -74,4 +76,14 @@ class ProxyCacheUtils {
throw new RuntimeException("Error decoding url", e);
}
}
static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
Log.e(LOG_TAG, "Error closing resource", e);
}
}
}
}