Author: toad
Date: 2008-06-13 19:21:11 +0000 (Fri, 13 Jun 2008)
New Revision: 20326
Added:
branches/db4o/freenet/src/freenet/client/ArchiveHandlerImpl.java
Modified:
branches/db4o/freenet/src/freenet/client/ArchiveManager.java
branches/db4o/freenet/src/freenet/client/ArchiveStoreContext.java
branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java
Log:
Split ArchiveStoreContext and ArchiveHandlerImpl up. The latter is persistent
and is a public interface, the former just contains the cached data for a
single key.
Note that this also fixes a minor performance bug, because the force-refetch
logic is now effectively on the client side, so one client asking for a refetch
because of a binary blob doesn't cause the others to wait when they don't need
to.
Added: branches/db4o/freenet/src/freenet/client/ArchiveHandlerImpl.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/ArchiveHandlerImpl.java
(rev 0)
+++ branches/db4o/freenet/src/freenet/client/ArchiveHandlerImpl.java
2008-06-13 19:21:11 UTC (rev 20326)
@@ -0,0 +1,66 @@
+package freenet.client;
+
+import freenet.keys.FreenetURI;
+import freenet.support.Logger;
+import freenet.support.api.Bucket;
+
+public class ArchiveHandlerImpl implements ArchiveHandler {
+
+ private final FreenetURI key;
+ private final short archiveType;
+ private boolean forceRefetchArchive;
+
+ ArchiveHandlerImpl(FreenetURI key, short archiveType, boolean
forceRefetchArchive) {
+ this.key = key;
+ this.archiveType = archiveType;
+ this.forceRefetchArchive = forceRefetchArchive;
+ }
+
+ public Bucket get(String internalName, ArchiveContext archiveContext,
+ ClientMetadata dm, int recursionLevel,
+ boolean dontEnterImplicitArchives, ArchiveManager
manager)
+ throws ArchiveFailureException, ArchiveRestartException,
+ MetadataParseException, FetchException {
+
+ // Do loop detection on the archive that we are about to fetch.
+ archiveContext.doLoopDetection(key);
+
+ if(forceRefetchArchive) return null;
+
+ Bucket data;
+
+ // Fetch from cache
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "Checking cache: "+key+ ' '
+internalName);
+ if((data = manager.getCached(key, internalName)) != null) {
+ return data;
+ }
+
+ return null;
+ }
+
+ public Bucket getMetadata(ArchiveContext archiveContext, ClientMetadata
dm,
+ int recursionLevel, boolean dontEnterImplicitArchives,
+ ArchiveManager manager) throws ArchiveFailureException,
+ ArchiveRestartException, MetadataParseException,
FetchException {
+ return get(".metadata", archiveContext, dm, recursionLevel,
dontEnterImplicitArchives, manager);
+ }
+
+ public void extractToCache(Bucket bucket, ArchiveContext actx,
+ String element, ArchiveExtractCallback callback,
+ ArchiveManager manager) throws ArchiveFailureException,
+ ArchiveRestartException {
+ forceRefetchArchive = false; // now we don't need to force
refetch any more
+ ArchiveStoreContext ctx = manager.makeContext(key, archiveType,
false);
+ manager.extractToCache(key, archiveType, bucket, actx, ctx,
element, callback);
+ }
+
+ public short getArchiveType() {
+ return archiveType;
+ }
+
+ public FreenetURI getKey() {
+ return key;
+ }
+
+}
Modified: branches/db4o/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/ArchiveManager.java
2008-06-13 18:42:01 UTC (rev 20325)
+++ branches/db4o/freenet/src/freenet/client/ArchiveManager.java
2008-06-13 19:21:11 UTC (rev 20326)
@@ -90,7 +90,7 @@
}
/** Add an ArchiveHandler by key */
- private synchronized void putCached(FreenetURI key, ArchiveHandler zip)
{
+ private synchronized void putCached(FreenetURI key, ArchiveStoreContext
zip) {
if(logMINOR) Logger.minor(this, "Put cached AH for "+key+" :
"+zip);
archiveHandlers.push(key, zip);
while(archiveHandlers.size() > maxArchiveHandlers)
@@ -98,9 +98,9 @@
}
/** Get an ArchiveHandler by key */
- public ArchiveHandler getCached(FreenetURI key) {
+ ArchiveStoreContext getCached(FreenetURI key) {
if(logMINOR) Logger.minor(this, "Get cached AH for "+key);
- ArchiveHandler handler = (ArchiveHandler)
archiveHandlers.get(key);
+ ArchiveStoreContext handler = (ArchiveStoreContext)
archiveHandlers.get(key);
if(handler == null) return null;
archiveHandlers.push(key, handler);
return handler;
@@ -115,17 +115,30 @@
* @param archiveType The archive type, defined in Metadata.
* @return An archive handler.
*/
- public synchronized ArchiveHandler makeHandler(FreenetURI key, short
archiveType, boolean returnNullIfNotFound, boolean forceRefetchArchive) {
- ArchiveHandler handler = null;
- if(!forceRefetchArchive) handler = getCached(key);
+ synchronized ArchiveStoreContext makeContext(FreenetURI key, short
archiveType, boolean returnNullIfNotFound) {
+ ArchiveStoreContext handler = null;
+ handler = getCached(key);
if(handler != null) return handler;
if(returnNullIfNotFound) return null;
- handler = new ArchiveStoreContext(key, archiveType,
forceRefetchArchive);
+ handler = new ArchiveStoreContext(key, archiveType);
putCached(key, handler);
return handler;
}
/**
+ * Create an archive handler. This does not need to know how to
+ * fetch the key, because the methods called later will ask.
+ * It will try to serve from cache, but if that fails, will
+ * re-fetch.
+ * @param key The key of the archive that we are extracting data from.
+ * @param archiveType The archive type, defined in Metadata.
+ * @return An archive handler.
+ */
+ public ArchiveHandler makeHandler(FreenetURI key, short archiveType,
boolean forceRefetch) {
+ return new ArchiveHandlerImpl(key, archiveType, forceRefetch);
+ }
+
+ /**
* Get a cached, previously extracted, file from an archive.
* @param key The key used to fetch the archive.
* @param filename The name of the file within the archive.
@@ -183,7 +196,6 @@
MutableBoolean gotElement = element != null ? new
MutableBoolean() : null;
if(logMINOR) Logger.minor(this, "Extracting "+key);
- ctx.onExtract();
ctx.removeAllCachedItems(this); // flush cache anyway
long expectedSize = ctx.getLastSize();
long archiveSize = data.size();
Modified: branches/db4o/freenet/src/freenet/client/ArchiveStoreContext.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/ArchiveStoreContext.java
2008-06-13 18:42:01 UTC (rev 20325)
+++ branches/db4o/freenet/src/freenet/client/ArchiveStoreContext.java
2008-06-13 19:21:11 UTC (rev 20326)
@@ -5,8 +5,6 @@
import freenet.keys.FreenetURI;
import freenet.support.DoublyLinkedListImpl;
-import freenet.support.Logger;
-import freenet.support.api.Bucket;
/**
* Tracks all files currently in the cache from a given key.
@@ -16,15 +14,11 @@
* subject to the above.
*
* Always take the lock on ArchiveStoreContext before the lock on
ArchiveManager, NOT the other way around.
- *
- * Not normally to be used directly by external packages, but public for
- * ArchiveManager.extractToCache. FIXME.
*/
-public class ArchiveStoreContext implements ArchiveHandler {
+public class ArchiveStoreContext {
private FreenetURI key;
private short archiveType;
- private boolean forceRefetchArchive;
/** Archive size */
private long lastSize = -1;
/** Archive hash */
@@ -35,47 +29,12 @@
* the inner lock to avoid deadlocks. */
private final DoublyLinkedListImpl myItems;
- ArchiveStoreContext(FreenetURI key, short archiveType, boolean
forceRefetchArchive) {
+ ArchiveStoreContext(FreenetURI key, short archiveType) {
this.key = key;
this.archiveType = archiveType;
myItems = new DoublyLinkedListImpl();
- this.forceRefetchArchive = forceRefetchArchive;
}
- /**
- * Get the metadata for a given archive.
- * @return A Bucket containing the metadata, in binary format, for the
archive.
- */
- public Bucket getMetadata(ArchiveContext archiveContext, ClientMetadata
dm, int recursionLevel,
- boolean dontEnterImplicitArchives, ArchiveManager
manager) throws ArchiveFailureException, ArchiveRestartException,
MetadataParseException, FetchException {
- return get(".metadata", archiveContext, dm, recursionLevel,
dontEnterImplicitArchives, manager);
- }
-
- /**
- * Fetch a file in an archive.
- * @return A Bucket containing the data. This will not be freed until
the
- * client is finished with it i.e. calls free() or it is finalized.
- */
- public Bucket get(String internalName, ArchiveContext archiveContext,
ClientMetadata dm, int recursionLevel,
- boolean dontEnterImplicitArchives, ArchiveManager
manager) throws ArchiveFailureException, ArchiveRestartException,
MetadataParseException, FetchException {
-
- // Do loop detection on the archive that we are about to fetch.
- archiveContext.doLoopDetection(key);
-
- if(forceRefetchArchive) return null;
-
- Bucket data;
-
- // Fetch from cache
- if(Logger.shouldLog(Logger.MINOR, this))
- Logger.minor(this, "Checking cache: "+key+ ' '
+internalName);
- if((data = manager.getCached(key, internalName)) != null) {
- return data;
- }
-
- return null;
- }
-
/** Returns the size of the archive last time we fetched it, or -1 */
long getLastSize() {
return lastSize;
@@ -136,12 +95,4 @@
return key;
}
- public void extractToCache(Bucket bucket, ArchiveContext actx, String
element, ArchiveExtractCallback callback, ArchiveManager manager) throws
ArchiveFailureException, ArchiveRestartException {
- manager.extractToCache(key, archiveType, bucket, actx, this,
element, callback);
- }
-
- /** Called just before extracting this container to the cache */
- void onExtract() {
- forceRefetchArchive = false;
- }
}
Modified: branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java
2008-06-13 18:42:01 UTC (rev 20325)
+++ branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java
2008-06-13 19:21:11 UTC (rev 20326)
@@ -271,7 +271,7 @@
// It's more efficient to keep the existing ah
if we can, and it is vital in
// the case of binary blobs.
if(ah == null || !ah.getKey().equals(thisKey))
- ah = (ArchiveStoreContext)
context.archiveManager.makeHandler(thisKey, metadata.getArchiveType(), false,
+ ah =
context.archiveManager.makeHandler(thisKey, metadata.getArchiveType(),
(parent instanceof
ClientGetter ? ((ClientGetter)parent).collectingBinaryBlob() : false));
archiveMetadata = metadata;
// ah is set. This means we are currently
handling an archive.