mirror of
https://github.com/zhigang1992/AndroidVideoCache.git
synced 2026-05-07 00:22:26 +08:00
optimize featching source data
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 + "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user