Author: toad
Date: 2006-05-20 01:54:17 +0000 (Sat, 20 May 2006)
New Revision: 8793
Modified:
trunk/freenet/src/freenet/client/ArchiveContext.java
trunk/freenet/src/freenet/client/ArchiveKey.java
trunk/freenet/src/freenet/client/ArchiveManager.java
trunk/freenet/src/freenet/client/ArchiveStoreContext.java
trunk/freenet/src/freenet/client/ClientMetadata.java
trunk/freenet/src/freenet/client/FetcherContext.java
trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
trunk/freenet/src/freenet/client/Metadata.java
trunk/freenet/src/freenet/client/RealArchiveStoreItem.java
trunk/freenet/src/freenet/client/async/ClientGetter.java
trunk/freenet/src/freenet/client/async/ClientPutter.java
trunk/freenet/src/freenet/client/async/ManifestElement.java
trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
trunk/freenet/src/freenet/client/async/SingleFileInserter.java
trunk/freenet/src/freenet/client/async/SplitFileInserter.java
trunk/freenet/src/freenet/keys/FreenetURI.java
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/Version.java
trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
trunk/freenet/src/freenet/support/LRUHashtable.java
Log:
731: Basic zip manifest support.
Modified: trunk/freenet/src/freenet/client/ArchiveContext.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveContext.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/ArchiveContext.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -12,15 +12,17 @@
public class ArchiveContext {
HashSet soFar = new HashSet();
- int maxArchiveLevels;
+ final int maxArchiveLevels;
+ public ArchiveContext(int max) {
+ this.maxArchiveLevels = max;
+ }
+
/**
* Check for a loop.
* The URI provided is expected to be a reasonably unique identifier
for the archive.
*/
public synchronized void doLoopDetection(FreenetURI key) throws
ArchiveFailureException {
- if(!soFar.add(key))
- throw new ArchiveFailureException("Archive loop
detected");
if(soFar.size() > maxArchiveLevels)
throw new
ArchiveFailureException(ArchiveFailureException.TOO_MANY_LEVELS);
}
Modified: trunk/freenet/src/freenet/client/ArchiveKey.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveKey.java 2006-05-19 22:36:32 UTC
(rev 8792)
+++ trunk/freenet/src/freenet/client/ArchiveKey.java 2006-05-20 01:54:17 UTC
(rev 8793)
@@ -22,4 +22,8 @@
public int hashCode() {
return key.hashCode() ^ filename.hashCode();
}
+
+ public String toString() {
+ return key+":"+filename;
+ }
}
\ No newline at end of file
Modified: trunk/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveManager.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/ArchiveManager.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -70,6 +70,7 @@
/** Add an ArchiveHandler by key */
private synchronized void putCached(FreenetURI key, ArchiveHandler zip)
{
+ Logger.minor(this, "Put cached AH for "+key+" : "+zip);
archiveHandlers.push(key, zip);
while(archiveHandlers.size() > maxArchiveHandlers)
archiveHandlers.popKey(); // dump it
@@ -77,7 +78,9 @@
/** Get an ArchiveHandler by key */
public ArchiveHandler getCached(FreenetURI key) {
+ Logger.minor(this, "Get cached AH for "+key);
ArchiveHandler handler = (ArchiveHandler)
archiveHandlers.get(key);
+ if(handler == null) return null;
archiveHandlers.push(key, handler);
return handler;
}
@@ -126,6 +129,7 @@
* @throws ArchiveFailureException
*/
public synchronized Bucket getCached(FreenetURI key, String filename)
throws ArchiveFailureException {
+ Logger.minor(this, "Fetch cached: "+key+" "+filename);
ArchiveKey k = new ArchiveKey(key, filename);
ArchiveStoreItem asi = (ArchiveStoreItem) storedData.get(k);
if(asi == null) return null;
@@ -155,6 +159,9 @@
* changed.
*/
public void extractToCache(FreenetURI key, short archiveType, Bucket
data, ArchiveContext archiveContext, ArchiveStoreContext ctx) throws
ArchiveFailureException, ArchiveRestartException {
+
+ Logger.minor(this, "Extracting "+key);
+
ctx.removeAllCachedItems(); // flush cache anyway
long expectedSize = ctx.getLastSize();
long archiveSize = data.size();
@@ -188,14 +195,16 @@
zis = new ZipInputStream(data.getInputStream());
// MINOR: Assumes the first entry in the zip is a
directory.
- ZipEntry entry = zis.getNextEntry();
+ ZipEntry entry;
byte[] buf = new byte[4096];
HashSet names = new HashSet();
boolean gotMetadata = false;
-outer: while(entry != null) {
+outer: while(true) {
entry = zis.getNextEntry();
+ if(entry == null) break;
+ if(entry.isDirectory()) continue;
String name = entry.getName();
if(names.contains(name)) {
Logger.error(this, "Duplicate key
"+name+" in archive "+key);
@@ -351,6 +360,7 @@
*/
private void addErrorElement(ArchiveStoreContext ctx, FreenetURI key,
String name, String error) {
ErrorArchiveStoreItem element = new ErrorArchiveStoreItem(ctx,
key, name, error);
+ Logger.minor(this, "Adding error element: "+element+" for
"+key+" "+name);
synchronized(storedData) {
storedData.push(element.key, element);
}
@@ -358,10 +368,10 @@
/**
* Add a store element.
- * @return True if this was the metadata element.
*/
private void addStoreElement(ArchiveStoreContext ctx, FreenetURI key,
String name, TempStoreElement temp) {
RealArchiveStoreItem element = new RealArchiveStoreItem(this,
ctx, key, name, temp);
+ Logger.minor(this, "Adding store element: "+element+" ( "+key+"
"+name+" )");
synchronized(storedData) {
storedData.push(element.key, element);
trimStoredData();
Modified: trunk/freenet/src/freenet/client/ArchiveStoreContext.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveStoreContext.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/ArchiveStoreContext.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -3,6 +3,7 @@
import freenet.keys.FreenetURI;
import freenet.support.Bucket;
import freenet.support.DoublyLinkedListImpl;
+import freenet.support.Logger;
/**
* Tracks all files currently in the cache from a given key.
@@ -43,8 +44,7 @@
}
/**
- * Fetch a file in an archive. Will check the cache first, then fetch
the archive if
- * necessary.
+ * Fetch a file in an archive.
*/
public Bucket get(String internalName, ArchiveContext archiveContext,
ClientMetadata dm, int recursionLevel,
boolean dontEnterImplicitArchives) throws
ArchiveFailureException, ArchiveRestartException, MetadataParseException,
FetchException {
@@ -55,6 +55,7 @@
Bucket data;
// Fetch from cache
+ Logger.minor(this, "Checking cache: "+key+" "+internalName);
if((data = manager.getCached(key, internalName)) != null) {
return data;
}
Modified: trunk/freenet/src/freenet/client/ClientMetadata.java
===================================================================
--- trunk/freenet/src/freenet/client/ClientMetadata.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/ClientMetadata.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -3,7 +3,7 @@
/**
* Stores the metadata that the client might actually be interested in.
*/
-public class ClientMetadata {
+public class ClientMetadata implements Cloneable {
/** The document MIME type */
private String mimeType;
@@ -37,4 +37,12 @@
public boolean isTrivial() {
return (mimeType == null || mimeType.equals(""));
}
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new Error(e);
+ }
+ }
}
Modified: trunk/freenet/src/freenet/client/FetcherContext.java
===================================================================
--- trunk/freenet/src/freenet/client/FetcherContext.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/FetcherContext.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -22,6 +22,7 @@
public USKManager uskManager;
public int maxRecursionLevel;
public int maxArchiveRestarts;
+ public int maxArchiveLevels;
public boolean dontEnterImplicitArchives;
public int maxSplitfileThreads;
public int maxSplitfileBlockRetries;
@@ -44,7 +45,7 @@
public boolean returnZIPManifests;
public FetcherContext(long curMaxLength,
- long curMaxTempLength, int maxMetadataSize, int
maxRecursionLevel, int maxArchiveRestarts,
+ long curMaxTempLength, int maxMetadataSize, int
maxRecursionLevel, int maxArchiveRestarts, int maxArchiveLevels,
boolean dontEnterImplicitArchives, int
maxSplitfileThreads,
int maxSplitfileBlockRetries, int
maxNonSplitfileRetries,
boolean allowSplitfiles, boolean followRedirects,
boolean localRequestOnly,
@@ -59,6 +60,7 @@
this.bucketFactory = bucketFactory;
this.maxRecursionLevel = maxRecursionLevel;
this.maxArchiveRestarts = maxArchiveRestarts;
+ this.maxArchiveLevels = maxArchiveLevels;
this.dontEnterImplicitArchives = dontEnterImplicitArchives;
this.random = random;
this.maxSplitfileThreads = maxSplitfileThreads;
@@ -88,6 +90,7 @@
this.bucketFactory = ctx.bucketFactory;
this.maxRecursionLevel = ctx.maxRecursionLevel;
this.maxArchiveRestarts = ctx.maxArchiveRestarts;
+ this.maxArchiveLevels = ctx.maxArchiveLevels;
this.dontEnterImplicitArchives =
ctx.dontEnterImplicitArchives;
this.random = ctx.random;
this.maxSplitfileThreads = ctx.maxSplitfileThreads;
@@ -109,6 +112,7 @@
this.bucketFactory = ctx.bucketFactory;
this.maxRecursionLevel = 1;
this.maxArchiveRestarts = 0;
+ this.maxArchiveLevels = ctx.maxArchiveLevels;
this.dontEnterImplicitArchives = true;
this.random = ctx.random;
this.maxSplitfileThreads = 0;
@@ -130,6 +134,7 @@
this.bucketFactory = ctx.bucketFactory;
this.maxRecursionLevel = ctx.maxRecursionLevel;
this.maxArchiveRestarts = ctx.maxArchiveRestarts;
+ this.maxArchiveLevels = ctx.maxArchiveLevels;
this.dontEnterImplicitArchives =
ctx.dontEnterImplicitArchives;
this.random = ctx.random;
this.maxSplitfileThreads = ctx.maxSplitfileThreads;
@@ -151,6 +156,7 @@
this.bucketFactory = ctx.bucketFactory;
this.maxRecursionLevel = ctx.maxRecursionLevel;
this.maxArchiveRestarts = ctx.maxArchiveRestarts;
+ this.maxArchiveLevels = ctx.maxArchiveLevels;
this.dontEnterImplicitArchives =
ctx.dontEnterImplicitArchives;
this.random = ctx.random;
this.maxSplitfileThreads = ctx.maxSplitfileThreads;
@@ -172,6 +178,7 @@
this.bucketFactory = ctx.bucketFactory;
this.maxRecursionLevel = ctx.maxRecursionLevel;
this.maxArchiveRestarts = ctx.maxArchiveRestarts;
+ this.maxArchiveLevels = ctx.maxArchiveLevels;
this.dontEnterImplicitArchives =
ctx.dontEnterImplicitArchives;
this.random = ctx.random;
this.maxSplitfileThreads = ctx.maxSplitfileThreads;
Modified: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
2006-05-19 22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
2006-05-20 01:54:17 UTC (rev 8793)
@@ -35,6 +35,7 @@
private final boolean cacheLocalRequests;
static final int MAX_RECURSION = 10;
static final int MAX_ARCHIVE_RESTARTS = 2;
+ static final int MAX_ARCHIVE_LEVELS = 4;
static final boolean DONT_ENTER_IMPLICIT_ARCHIVES = true;
/** Number of threads used by a splitfile fetch */
static final int SPLITFILE_THREADS = 20;
@@ -163,7 +164,7 @@
}
return
new FetcherContext(maxLength, maxTempLength,
curMaxMetadataLength,
- MAX_RECURSION, MAX_ARCHIVE_RESTARTS,
DONT_ENTER_IMPLICIT_ARCHIVES,
+ MAX_RECURSION, MAX_ARCHIVE_RESTARTS,
MAX_ARCHIVE_LEVELS, DONT_ENTER_IMPLICIT_ARCHIVES,
SPLITFILE_THREADS, SPLITFILE_BLOCK_RETRIES,
NON_SPLITFILE_RETRIES,
FETCH_SPLITFILES, FOLLOW_REDIRECTS,
LOCAL_REQUESTS_ONLY,
MAX_SPLITFILE_BLOCKS_PER_SEGMENT,
MAX_SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
Modified: trunk/freenet/src/freenet/client/Metadata.java
===================================================================
--- trunk/freenet/src/freenet/client/Metadata.java 2006-05-19 22:36:32 UTC
(rev 8792)
+++ trunk/freenet/src/freenet/client/Metadata.java 2006-05-20 01:54:17 UTC
(rev 8793)
@@ -40,8 +40,8 @@
public static final byte SIMPLE_REDIRECT = 0;
static final byte MULTI_LEVEL_METADATA = 1;
static final byte SIMPLE_MANIFEST = 2;
- static final byte ZIP_MANIFEST = 3;
- static final byte ZIP_INTERNAL_REDIRECT = 4;
+ public static final byte ZIP_MANIFEST = 3;
+ public static final byte ZIP_INTERNAL_REDIRECT = 4;
// 2 bytes of flags
/** Is a splitfile */
@@ -107,7 +107,6 @@
FreenetURI[] splitfileCheckKeys;
// Manifests
- int manifestEntryCount;
/** Manifest entries by name */
HashMap manifestEntries;
@@ -148,7 +147,7 @@
Metadata m;
try {
DataInputStream dis = new DataInputStream(is);
- m = new Metadata(dis, false, data.size());
+ m = new Metadata(dis, data.size());
} finally {
is.close();
}
@@ -158,12 +157,12 @@
/** Parse some metadata from a byte[].
* @throws IOException If the data is incomplete, or something wierd
happens. */
private Metadata(byte[] data) throws IOException {
- this(new DataInputStream(new ByteArrayInputStream(data)),
false, data.length);
+ this(new DataInputStream(new ByteArrayInputStream(data)),
data.length);
}
/** Parse some metadata from a DataInputStream
* @throws IOException If an I/O error occurs, or the data is
incomplete. */
- public Metadata(DataInputStream dis, boolean
acceptZipInternalRedirects, long length) throws IOException,
MetadataParseException {
+ public Metadata(DataInputStream dis, long length) throws IOException,
MetadataParseException {
long magic = dis.readLong();
if(magic != FREENET_METADATA_MAGIC)
throw new MetadataParseException("Invalid magic
"+magic);
@@ -171,13 +170,13 @@
if(version != 0)
throw new MetadataParseException("Unsupported version
"+version);
documentType = dis.readByte();
- if(documentType < 0 || documentType > 5 ||
- (documentType == ZIP_INTERNAL_REDIRECT &&
!acceptZipInternalRedirects))
+ if(documentType < 0 || documentType > 5)
throw new MetadataParseException("Unsupported document
type: "+documentType);
+ Logger.minor(this, "Document type: "+documentType);
boolean compressed = false;
if(documentType == SIMPLE_REDIRECT || documentType ==
MULTI_LEVEL_METADATA
- || documentType == ZIP_MANIFEST) {
+ || documentType == ZIP_MANIFEST || documentType
== ZIP_INTERNAL_REDIRECT) {
short flags = dis.readShort();
splitfile = (flags & FLAGS_SPLITFILE) ==
FLAGS_SPLITFILE;
dbr = (flags & FLAGS_DBR) == FLAGS_DBR;
@@ -190,12 +189,14 @@
}
if(documentType == ZIP_MANIFEST) {
+ Logger.minor(this, "Zip manifest");
archiveType = dis.readShort();
if(archiveType != ARCHIVE_ZIP)
throw new MetadataParseException("Unrecognized
archive type "+archiveType);
}
if(splitfile) {
+ Logger.minor(this, "Splitfile");
dataLength = dis.readLong();
if(dataLength < -1)
throw new MetadataParseException("Invalid real
content length "+dataLength);
@@ -261,7 +262,7 @@
clientMetadata = new ClientMetadata(mimeType);
- if((!splitfile) && documentType == SIMPLE_REDIRECT ||
documentType == ZIP_MANIFEST) {
+ if((!splitfile) && (documentType == SIMPLE_REDIRECT ||
documentType == ZIP_MANIFEST)) {
simpleRedirectKey = readKey(dis);
} else if(splitfile) {
splitfileAlgorithm = dis.readShort();
@@ -304,7 +305,7 @@
}
if(documentType == SIMPLE_MANIFEST) {
- manifestEntryCount = dis.readInt();
+ int manifestEntryCount = dis.readInt();
if(manifestEntryCount < 0)
throw new MetadataParseException("Invalid
manifest entry count: "+manifestEntryCount);
@@ -317,6 +318,7 @@
byte[] buf = new byte[nameLength];
dis.readFully(buf);
String name = new String(buf, "UTF-8");
+ Logger.minor(this, "Entry "+i+" name "+name);
short len = dis.readShort();
if(len < 0)
throw new
MetadataParseException("Invalid manifest entry size: "+len);
@@ -335,8 +337,11 @@
if(documentType == ZIP_INTERNAL_REDIRECT) {
int len = dis.readShort();
+ Logger.minor(this, "Reading zip internal redirect
length "+len);
byte[] buf = new byte[len];
+ dis.readFully(buf);
nameInArchive = new String(buf, "UTF-8");
+ Logger.minor(this, "Zip internal redirect:
"+nameInArchive+" ("+len+")");
}
}
@@ -378,8 +383,6 @@
} else throw new IllegalArgumentException("Not String
nor HashMap: "+o);
manifestEntries.put(key, target);
}
- manifestEntryCount = count;
-
}
/**
@@ -432,7 +435,6 @@
manifestEntries.put(key, subMap);
}
}
- manifestEntryCount = count;
}
/**
@@ -457,13 +459,12 @@
Metadata target;
if(o instanceof String) {
// Zip internal redirect
- target = new Metadata(ZIP_INTERNAL_REDIRECT,
key);
+ target = new Metadata(ZIP_INTERNAL_REDIRECT,
key, new ClientMetadata(DefaultMIMETypes.guessMIMEType(key)));
} else if(o instanceof HashMap) {
target = new Metadata((HashMap)o);
} else throw new IllegalArgumentException("Not String
nor HashMap: "+o);
manifestEntries.put(key, target);
}
- manifestEntryCount = count;
}
/**
@@ -488,13 +489,12 @@
Metadata target;
if(o instanceof String) {
// Zip internal redirect
- target = new Metadata(ZIP_INTERNAL_REDIRECT,
key);
+ target = new Metadata(ZIP_INTERNAL_REDIRECT,
key, new ClientMetadata(DefaultMIMETypes.guessMIMEType(key)));
} else if(o instanceof HashMap) {
target = new Metadata((HashMap)o);
} else throw new IllegalArgumentException("Not String
nor HashMap: "+o);
manifestEntries.put(key, target);
}
- manifestEntryCount = count;
}
/**
@@ -504,12 +504,12 @@
* @param arg The argument; in the case of ZIP_INTERNAL_REDIRECT, the
filename in
* the archive to read from.
*/
- public Metadata(byte docType, String arg) {
+ public Metadata(byte docType, String arg, ClientMetadata cm) {
if(docType == ZIP_INTERNAL_REDIRECT) {
documentType = docType;
// Determine MIME type
- setMIMEType(DefaultMIMETypes.guessMIMEType(arg));
- clientMetadata = new ClientMetadata(mimeType);
+ this.clientMetadata = cm;
+ this.setMIMEType(cm.getMIMEType());
nameInArchive = arg;
} else
throw new IllegalArgumentException();
@@ -522,7 +522,7 @@
* @param cm The client metadata, if any.
*/
public Metadata(byte docType, FreenetURI uri, ClientMetadata cm) {
- if(docType == SIMPLE_REDIRECT) {
+ if(docType == SIMPLE_REDIRECT || docType == ZIP_MANIFEST) {
documentType = docType;
clientMetadata = cm;
if(cm != null && !cm.isTrivial()) {
@@ -538,11 +538,14 @@
throw new IllegalArgumentException();
}
- public Metadata(short algo, FreenetURI[] dataURIs, FreenetURI[]
checkURIs, int segmentSize, int checkSegmentSize, ClientMetadata cm, long
dataLength, short compressionAlgo, boolean isMetadata) {
+ public Metadata(short algo, FreenetURI[] dataURIs, FreenetURI[]
checkURIs, int segmentSize, int checkSegmentSize, ClientMetadata cm, long
dataLength, short compressionAlgo, boolean isMetadata, boolean
insertAsArchiveManifest) {
if(isMetadata)
documentType = MULTI_LEVEL_METADATA;
- else
- documentType = SIMPLE_REDIRECT;
+ else {
+ if(insertAsArchiveManifest)
+ documentType = ZIP_MANIFEST;
+ else documentType = SIMPLE_REDIRECT;
+ }
splitfile = true;
splitfileAlgorithm = algo;
this.dataLength = dataLength;
@@ -725,7 +728,7 @@
dos.writeShort(0); // version
dos.writeByte(documentType);
if(documentType == SIMPLE_REDIRECT || documentType ==
MULTI_LEVEL_METADATA
- || documentType == ZIP_MANIFEST) {
+ || documentType == ZIP_MANIFEST || documentType
== ZIP_INTERNAL_REDIRECT) {
short flags = 0;
if(splitfile) flags |= FLAGS_SPLITFILE;
if(dbr) flags |= FLAGS_DBR;
@@ -772,7 +775,7 @@
if(extraMetadata)
throw new UnsupportedOperationException("No extra
metadata support yet");
- if((!splitfile) && documentType == SIMPLE_REDIRECT ||
documentType == ZIP_MANIFEST) {
+ if((!splitfile) && (documentType == SIMPLE_REDIRECT ||
documentType == ZIP_MANIFEST)) {
writeKey(dos, simpleRedirectKey);
} else if(splitfile) {
dos.writeShort(splitfileAlgorithm);
@@ -791,7 +794,7 @@
}
if(documentType == SIMPLE_MANIFEST) {
- dos.writeInt(manifestEntryCount);
+ dos.writeInt(manifestEntries.size());
boolean kill = false;
LinkedList unresolvedMetadata = null;
for(Iterator
i=manifestEntries.keySet().iterator();i.hasNext();) {
@@ -891,4 +894,8 @@
byte[] buf = writeToByteArray();
return BucketTools.makeImmutableBucket(bf, buf);
}
+
+ public boolean isResolved() {
+ return resolvedURI != null;
+ }
}
Modified: trunk/freenet/src/freenet/client/RealArchiveStoreItem.java
===================================================================
--- trunk/freenet/src/freenet/client/RealArchiveStoreItem.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/RealArchiveStoreItem.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -31,6 +31,7 @@
this.underBucket = temp.underBucket;
underBucket.dontDeleteOnFinalize();
underBucket.setReadOnly();
+ this.myFilename = underBucket.getFile();
this.manager.cachedData += spaceUsed();
}
Modified: trunk/freenet/src/freenet/client/async/ClientGetter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientGetter.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/async/ClientGetter.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -48,7 +48,7 @@
this.uri = uri;
this.ctx = ctx;
this.finished = false;
- this.actx = new ArchiveContext();
+ this.actx = new ArchiveContext(ctx.maxArchiveLevels);
archiveRestarts = 0;
}
Modified: trunk/freenet/src/freenet/client/async/ClientPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientPutter.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/async/ClientPutter.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -54,7 +54,7 @@
public void start() throws InserterException {
try {
currentState =
- new SingleFileInserter(this, this, new
InsertBlock(data, cm, targetURI), isMetadata, ctx, false, getCHKOnly, false,
null);
+ new SingleFileInserter(this, this, new
InsertBlock(data, cm, targetURI), isMetadata, ctx, false, getCHKOnly, false,
null, false);
((SingleFileInserter)currentState).start();
} catch (InserterException e) {
finished = true;
Modified: trunk/freenet/src/freenet/client/async/ManifestElement.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ManifestElement.java 2006-05-19
22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/async/ManifestElement.java 2006-05-20
01:54:17 UTC (rev 8793)
@@ -11,6 +11,8 @@
/** Filename */
final String name;
+ final String fullName;
+
/** Data to be inserted. Can be null, if the insert has completed. */
final Bucket data;
@@ -23,16 +25,27 @@
/** Redirect target */
final FreenetURI targetURI;
+ public ManifestElement(String name, String fullName, Bucket data,
String mimeOverride, long size) {
+ this.name = name;
+ this.fullName = fullName;
+ this.data = data;
+ this.mimeOverride = mimeOverride;
+ this.dataSize = size;
+ this.targetURI = null;
+ }
+
public ManifestElement(String name, Bucket data, String mimeOverride,
long size) {
this.name = name;
+ this.fullName = name;
this.data = data;
this.mimeOverride = mimeOverride;
this.dataSize = size;
this.targetURI = null;
}
- public ManifestElement(ManifestElement me, String fullName) {
- this.name = fullName;
+ public ManifestElement(ManifestElement me, String newName) {
+ this.name = newName;
+ this.fullName = me.fullName;
this.data = me.data;
this.mimeOverride = me.mimeOverride;
this.dataSize = me.dataSize;
@@ -41,6 +54,7 @@
public ManifestElement(String name, FreenetURI targetURI, String
mimeOverride) {
this.name = name;
+ this.fullName = name;
this.data = null;
this.mimeOverride = mimeOverride;
this.dataSize = -1;
Modified: trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
2006-05-19 22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
2006-05-20 01:54:17 UTC (rev 8793)
@@ -1,10 +1,14 @@
package freenet.client.async;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Vector;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
import freenet.client.ClientMetadata;
import freenet.client.DefaultMIMETypes;
@@ -29,10 +33,11 @@
super(SimpleManifestPutter.this.getPriorityClass(),
SimpleManifestPutter.this.chkScheduler, SimpleManifestPutter.this.sskScheduler,
SimpleManifestPutter.this.client);
this.name = name;
this.cm = cm;
+ this.data = data;
InsertBlock block =
new InsertBlock(data, cm,
FreenetURI.EMPTY_CHK_URI);
this.origSFI =
- new SingleFileInserter(this, this, block,
false, ctx, false, getCHKOnly, true, null);
+ new SingleFileInserter(this, this, block,
false, ctx, false, getCHKOnly, true, null, false);
currentState = origSFI;
metadata = null;
}
@@ -41,19 +46,33 @@
super(SimpleManifestPutter.this.getPriorityClass(),
SimpleManifestPutter.this.chkScheduler, SimpleManifestPutter.this.sskScheduler,
SimpleManifestPutter.this.client);
this.name = name;
this.cm = cm;
+ this.data = null;
Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT,
target, cm);
- cm = null;
metadata = m;
origSFI = null;
currentState = null;
}
+ protected PutHandler(String name, String targetInZip,
ClientMetadata cm, Bucket data) {
+ super(SimpleManifestPutter.this.getPriorityClass(),
SimpleManifestPutter.this.chkScheduler, SimpleManifestPutter.this.sskScheduler,
SimpleManifestPutter.this.client);
+ this.name = name;
+ this.cm = cm;
+ this.data = data;
+ this.targetInZip = targetInZip;
+ Metadata m = new
Metadata(Metadata.ZIP_INTERNAL_REDIRECT, targetInZip, cm);
+ metadata = m;
+ origSFI = null;
+ currentState = null;
+ }
+
private SingleFileInserter origSFI;
private ClientPutState currentState;
private ClientMetadata cm;
private final String name;
private Metadata metadata;
private boolean finished;
+ private String targetInZip;
+ private final Bucket data;
public void start() throws InserterException {
if(origSFI == null && metadata != null) return;
@@ -174,8 +193,10 @@
private long totalSize;
private boolean metadataBlockSetFinalized;
private Metadata baseMetadata;
+ private boolean hasResolvedBase = false;
private final static String[] defaultDefaultNames =
new String[] { "index.html", "index.htm", "default.html",
"default.htm" };
+ private LinkedList elementsToPutInZip;
public SimpleManifestPutter(ClientCallback cb, ClientRequestScheduler
chkSched,
ClientRequestScheduler sskSched, HashMap
manifestElements, short prioClass, FreenetURI target,
@@ -191,9 +212,16 @@
putHandlersWaitingForMetadata = new HashSet();
waitingForBlockSets = new HashSet();
metadataPuttersByMetadata = new HashMap();
+ elementsToPutInZip = new LinkedList();
makePutHandlers(manifestElements, putHandlersByName);
+ checkZips();
}
+ private void checkZips() {
+ // If there are too few files in the zip, then insert them
directly instead.
+ // FIXME do something.
+ }
+
public void start() throws InserterException {
PutHandler[] running;
synchronized(this) {
@@ -235,16 +263,27 @@
ph = new PutHandler(name,
element.targetURI, cm);
// Just a placeholder, don't actually
run it
} else {
- try {
- ph = new PutHandler(name, data,
cm, getCHKOnly);
- } catch (InserterException e) {
- cancelAndFinish();
- throw e;
+ // Decide whether to put it in the ZIP.
+ // FIXME support multiple ZIPs and size
limits.
+ // FIXME support better heuristics.
+ if(data.size() <= 65536) { // totally
dumb heuristic!
+ // Put it in the zip.
+ ph = new PutHandler(name,
element.fullName, cm, data);
+ elementsToPutInZip.addLast(ph);
+ numberOfFiles++;
+ totalSize += data.size();
+ } else {
+ try {
+ ph = new
PutHandler(name, data, cm, getCHKOnly);
+ } catch (InserterException e) {
+ cancelAndFinish();
+ throw e;
+ }
+ runningPutHandlers.add(ph);
+
putHandlersWaitingForMetadata.add(ph);
+ numberOfFiles++;
+ totalSize += data.size();
}
- runningPutHandlers.add(ph);
- putHandlersWaitingForMetadata.add(ph);
- numberOfFiles++;
- totalSize += data.size();
}
putHandlersByName.put(name, ph);
}
@@ -283,12 +322,17 @@
baseMetadata =
Metadata.mkRedirectionManifestWithMetadata(namesToByteArrays);
resolveAndStartBase();
+
}
+
+ private void startMetadataInsert() {
+ resolveAndStartBase();
+ }
private void resolveAndStartBase() {
Bucket bucket = null;
synchronized(this) {
-
if(this.metadataPuttersByMetadata.containsKey(baseMetadata)) return;
+ if(hasResolvedBase) return;
}
while(true) {
try {
@@ -309,11 +353,64 @@
}
}
if(bucket == null) return;
- InsertBlock block =
- new InsertBlock(bucket, null, targetURI);
+ synchronized(this) {
+ if(hasResolvedBase) return;
+ hasResolvedBase = true;
+ }
+ InsertBlock block;
+ boolean isMetadata = true;
+ boolean insertAsArchiveManifest = false;
+ if(!(elementsToPutInZip.isEmpty())) {
+ // There is a zip to insert.
+ // We want to include the metadata.
+ // We have the metadata, fortunately enough, because
everything has been resolve()d.
+ // So all we need to do is create the actual ZIP.
+ try {
+
+ // FIXME support formats other than .zip.
+ // Only the *decoding* is generic at present.
+
+ Bucket zipBucket = ctx.bf.makeBucket(-1);
+ OutputStream os = zipBucket.getOutputStream();
+ ZipOutputStream zos = new ZipOutputStream(os);
+ ZipEntry ze;
+
+ for(Iterator
i=elementsToPutInZip.iterator();i.hasNext();) {
+ PutHandler ph = (PutHandler) i.next();
+ ze = new ZipEntry(ph.targetInZip);
+ ze.setTime(0);
+ zos.putNextEntry(ze);
+ BucketTools.copyTo(ph.data, zos,
ph.data.size());
+ }
+
+ // Add .metadata - after the rest.
+ ze = new ZipEntry(".metadata");
+ ze.setTime(0); // -1 = now, 0 = 1970.
+ zos.putNextEntry(ze);
+ BucketTools.copyTo(bucket, zos, bucket.size());
+
+ zos.closeEntry();
+ // Both finish() and close() are necessary.
+ zos.finish();
+ zos.close();
+
+ // Now we have to insert the ZIP.
+
+ // Can we just insert it, and not bother with a
redirect to it?
+ // Thereby exploiting implicit manifest
support, which will pick up on .metadata??
+ // We ought to be able to !!
+ block = new InsertBlock(zipBucket, new
ClientMetadata("application/zip"), targetURI);
+ isMetadata = false;
+ insertAsArchiveManifest = true;
+ } catch (IOException e) {
+ fail(new
InserterException(InserterException.BUCKET_ERROR, e, null));
+ return;
+ }
+ } else
+ block = new InsertBlock(bucket, null, targetURI);
try {
SingleFileInserter metadataInserter =
- new SingleFileInserter(this, this, block, true,
ctx, false, getCHKOnly, false, baseMetadata);
+ new SingleFileInserter(this, this, block,
isMetadata, ctx, false, getCHKOnly, false, baseMetadata,
insertAsArchiveManifest);
Logger.minor(this, "Inserting main metadata:
"+metadataInserter);
this.metadataPuttersByMetadata.put(baseMetadata,
metadataInserter);
metadataInserter.start();
@@ -322,18 +419,22 @@
}
}
- private void resolve(MetadataUnresolvedException e) throws
InserterException, IOException {
+ private boolean resolve(MetadataUnresolvedException e) throws
InserterException, IOException {
Metadata[] metas = e.mustResolve;
+ boolean mustWait = false;
for(int i=0;i<metas.length;i++) {
Metadata m = metas[i];
+ if(!m.isResolved())
+ mustWait = true;
synchronized(this) {
if(metadataPuttersByMetadata.containsKey(m))
continue;
}
try {
Bucket b = m.toBucket(ctx.bf);
+
InsertBlock ib = new InsertBlock(b, null,
FreenetURI.EMPTY_CHK_URI);
SingleFileInserter metadataInserter =
- new SingleFileInserter(this, this, ib,
true, ctx, false, getCHKOnly, false, m);
+ new SingleFileInserter(this, this, ib,
true, ctx, false, getCHKOnly, false, m, false);
Logger.minor(this, "Inserting subsidiary
metadata: "+metadataInserter+" for "+m);
synchronized(this) {
this.metadataPuttersByMetadata.put(m,
metadataInserter);
@@ -343,6 +444,7 @@
resolve(e1);
}
}
+ return mustWait;
}
private void namesToByteArrays(HashMap putHandlersByName, HashMap
namesToByteArrays) {
Modified: trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
2006-05-19 22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
2006-05-20 01:54:17 UTC (rev 8793)
@@ -36,6 +36,7 @@
final GetCompletionCallback rcb;
final ClientMetadata clientMetadata;
private Metadata metadata;
+ private Metadata archiveMetadata;
final ArchiveContext actx;
/** Archive handler. We can only have one archive handler at a time. */
private ArchiveStoreContext ah;
@@ -90,7 +91,7 @@
this.dontTellClientGet = fetcher.dontTellClientGet;
this.actx = fetcher.actx;
this.ah = fetcher.ah;
- this.clientMetadata = fetcher.clientMetadata;
+ this.clientMetadata = (ClientMetadata)
fetcher.clientMetadata.clone();
this.metadata = newMeta;
this.metaStrings = fetcher.metaStrings;
this.rcb = callback;
@@ -186,12 +187,14 @@
private void handleMetadata() throws FetchException,
MetadataParseException, ArchiveFailureException, ArchiveRestartException {
while(true) {
if(metadata.isSimpleManifest()) {
+ Logger.minor(this, "Is simple manifest");
String name;
if(metaStrings.isEmpty())
throw new
FetchException(FetchException.NOT_ENOUGH_METASTRINGS);
else
name = (String)
metaStrings.removeFirst();
// Since metadata is a document, we just
replace metadata here
+ Logger.minor(this, "Next meta-string: "+name);
if(name == null) {
metadata =
metadata.getDefaultDocument();
if(metadata == null)
@@ -204,6 +207,7 @@
}
continue; // loop
} else if(metadata.isArchiveManifest()) {
+ Logger.minor(this, "Is archive manifest");
if(metaStrings.isEmpty() &&
ctx.returnZIPManifests) {
// Just return the archive, whole.
metadata.setSimpleRedirect();
@@ -213,6 +217,7 @@
// Then parse it.
// Then we may need to fetch something from
inside the archive.
ah = (ArchiveStoreContext)
ctx.archiveManager.makeHandler(thisKey, metadata.getArchiveType(), false);
+ archiveMetadata = metadata;
// ah is set. This means we are currently
handling an archive.
Bucket metadataBucket;
metadataBucket = ah.getMetadata(actx, null,
recursionLevel+1, true);
@@ -224,19 +229,21 @@
throw new
FetchException(FetchException.BUCKET_ERROR, e);
}
} else {
- fetchArchive(false); // will result in
this function being called again
+ fetchArchive(false, archiveMetadata);
// will result in this function being called again
return;
}
continue;
} else if(metadata.isArchiveInternalRedirect()) {
-
clientMetadata.mergeNoOverwrite(metadata.getClientMetadata()); // even
splitfiles can have mime types!
+ Logger.minor(this, "Is archive-internal
redirect");
+
clientMetadata.mergeNoOverwrite(metadata.getClientMetadata());
// Fetch it from the archive
if(ah == null)
throw new
FetchException(FetchException.UNKNOWN_METADATA, "Archive redirect not in an
archive");
- if(metaStrings.isEmpty())
- throw new
FetchException(FetchException.NOT_ENOUGH_METASTRINGS);
- Bucket dataBucket = ah.get((String)
metaStrings.removeFirst(), actx, null, recursionLevel+1, true);
+ String filename = metadata.getZIPInternalName();
+ Logger.minor(this, "Fetching "+filename);
+ Bucket dataBucket = ah.get(filename, actx,
null, recursionLevel+1, true);
if(dataBucket != null) {
+ Logger.minor(this, "Returning data");
// The client may free it, which is
bad, or it may hang on to it for so long that it gets
// freed by us, which is also bad.
// So copy it.
@@ -256,14 +263,16 @@
onSuccess(new
FetchResult(this.clientMetadata, out));
return;
} else {
+ Logger.minor(this, "Fetching archive");
// Metadata cannot contain pointers to
files which don't exist.
// We enforce this in ArchiveHandler.
// Therefore, the archive needs to be
fetched.
- fetchArchive(true);
+ fetchArchive(true, archiveMetadata);
// Will call back into this function
when it has been fetched.
return;
}
} else if(metadata.isMultiLevelMetadata()) {
+ Logger.minor(this, "Is multi-level metadata");
// Fetch on a second SingleFileFetcher, like
with archives.
Metadata newMeta = (Metadata) metadata.clone();
newMeta.setSimpleRedirect();
@@ -271,6 +280,7 @@
f.handleMetadata();
return;
} else if(metadata.isSingleFileRedirect()) {
+ Logger.minor(this, "Is single-file redirect");
clientMetadata.mergeNoOverwrite(metadata.getClientMetadata()); // even
splitfiles can have mime types!
// FIXME implement implicit archive support
@@ -356,14 +366,14 @@
decompressors.addLast(codec);
}
- private void fetchArchive(boolean forData) throws FetchException,
MetadataParseException, ArchiveFailureException, ArchiveRestartException {
+ private void fetchArchive(boolean forData, Metadata meta) throws
FetchException, MetadataParseException, ArchiveFailureException,
ArchiveRestartException {
// Fetch the archive
// How?
// Spawn a separate SingleFileFetcher,
// which fetches the archive, then calls
// our Callback, which unpacks the archive, then
// reschedules us.
- Metadata newMeta = (Metadata) metadata.clone();
+ Metadata newMeta = (Metadata) meta.clone();
newMeta.setSimpleRedirect();
SingleFileFetcher f;
f = new SingleFileFetcher(this, newMeta, new
ArchiveFetcherCallback(forData), new FetcherContext(ctx,
FetcherContext.SET_RETURN_ARCHIVES, true));
Modified: trunk/freenet/src/freenet/client/async/SingleFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileInserter.java
2006-05-19 22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/async/SingleFileInserter.java
2006-05-20 01:54:17 UTC (rev 8793)
@@ -39,6 +39,7 @@
final boolean metadata;
final PutCompletionCallback cb;
final boolean getCHKOnly;
+ final boolean insertAsArchiveManifest;
/** If true, we are not the top level request, and should not
* update our parent to point to us as current put-stage. */
private boolean cancelled = false;
@@ -54,11 +55,12 @@
* @param dontCompress
* @param getCHKOnly
* @param reportMetadataOnly If true, don't insert the metadata, just
report it.
+ * @param insertAsArchiveManifest If true, insert the metadata as an
archive manifest.
* @throws InserterException
*/
SingleFileInserter(BaseClientPutter parent, PutCompletionCallback cb,
InsertBlock block,
boolean metadata, InserterContext ctx, boolean
dontCompress,
- boolean getCHKOnly, boolean reportMetadataOnly, Object
token) throws InserterException {
+ boolean getCHKOnly, boolean reportMetadataOnly, Object
token, boolean insertAsArchiveManifest) throws InserterException {
this.reportMetadataOnly = reportMetadataOnly;
this.token = token;
this.parent = parent;
@@ -67,6 +69,7 @@
this.metadata = metadata;
this.cb = cb;
this.getCHKOnly = getCHKOnly;
+ this.insertAsArchiveManifest = insertAsArchiveManifest;
}
public void start() throws InserterException {
@@ -164,7 +167,7 @@
if(block.getData().size() > Integer.MAX_VALUE)
throw new
InserterException(InserterException.INTERNAL_ERROR, "2GB+ should not encode to
one block!", null);
- if((block.clientMetadata == null ||
block.clientMetadata.isTrivial())) {
+ if((block.clientMetadata == null ||
block.clientMetadata.isTrivial()) && !insertAsArchiveManifest) {
if(data.size() < blockSize) {
// Just insert it
ClientPutState bi =
@@ -179,7 +182,7 @@
// Insert single block, then insert pointer to it
if(reportMetadataOnly) {
SingleBlockInserter dataPutter = new
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx,
cb, metadata, (int)origSize, -1, getCHKOnly, true, true, token);
- Metadata meta = new
Metadata(Metadata.SIMPLE_REDIRECT, dataPutter.getURI(), block.clientMetadata);
+ Metadata meta = new
Metadata(insertAsArchiveManifest ? Metadata.ZIP_MANIFEST :
Metadata.SIMPLE_REDIRECT, dataPutter.getURI(), block.clientMetadata);
cb.onMetadata(meta, this);
cb.onTransition(this, dataPutter);
dataPutter.schedule();
@@ -188,7 +191,7 @@
MultiPutCompletionCallback mcb =
new MultiPutCompletionCallback(cb,
parent, token);
SingleBlockInserter dataPutter = new
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx,
mcb, metadata, (int)origSize, -1, getCHKOnly, true, false, token);
- Metadata meta = new
Metadata(Metadata.SIMPLE_REDIRECT, dataPutter.getURI(), block.clientMetadata);
+ Metadata meta = new
Metadata(insertAsArchiveManifest ? Metadata.ZIP_MANIFEST :
Metadata.SIMPLE_REDIRECT, dataPutter.getURI(), block.clientMetadata);
Bucket metadataBucket;
try {
metadataBucket =
BucketTools.makeImmutableBucket(ctx.bf, meta.writeToByteArray());
@@ -217,12 +220,12 @@
// insert it. Then when the splitinserter has finished, and the
// metadata insert has finished too, tell the master callback.
if(reportMetadataOnly) {
- SplitFileInserter sfi = new SplitFileInserter(parent,
cb, data, bestCodec, block.clientMetadata, ctx, getCHKOnly, metadata, token);
+ SplitFileInserter sfi = new SplitFileInserter(parent,
cb, data, bestCodec, block.clientMetadata, ctx, getCHKOnly, metadata, token,
insertAsArchiveManifest);
cb.onTransition(this, sfi);
sfi.start();
} else {
SplitHandler sh = new SplitHandler();
- SplitFileInserter sfi = new SplitFileInserter(parent,
sh, data, bestCodec, block.clientMetadata, ctx, getCHKOnly, metadata, token);
+ SplitFileInserter sfi = new SplitFileInserter(parent,
sh, data, bestCodec, block.clientMetadata, ctx, getCHKOnly, metadata, token,
insertAsArchiveManifest);
sh.sfi = sfi;
cb.onTransition(this, sh);
sfi.start();
@@ -325,7 +328,7 @@
}
InsertBlock newBlock = new
InsertBlock(metadataBucket, null, block.desiredURI);
try {
- metadataPutter = new
SingleFileInserter(parent, this, newBlock, true, ctx, false, getCHKOnly, false,
token);
+ metadataPutter = new
SingleFileInserter(parent, this, newBlock, true, ctx, false, getCHKOnly, false,
token, false);
Logger.minor(this, "Putting
metadata on "+metadataPutter);
} catch (InserterException e) {
cb.onFailure(e, this);
Modified: trunk/freenet/src/freenet/client/async/SplitFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserter.java
2006-05-19 22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserter.java
2006-05-20 01:54:17 UTC (rev 8793)
@@ -35,9 +35,11 @@
final boolean isMetadata;
private boolean finished;
public final Object token;
+ final boolean insertAsArchiveManifest;
- public SplitFileInserter(BaseClientPutter put, PutCompletionCallback
cb, Bucket data, Compressor bestCodec, ClientMetadata clientMetadata,
InserterContext ctx, boolean getCHKOnly, boolean isMetadata, Object token)
throws InserterException {
+ public SplitFileInserter(BaseClientPutter put, PutCompletionCallback
cb, Bucket data, Compressor bestCodec, ClientMetadata clientMetadata,
InserterContext ctx, boolean getCHKOnly, boolean isMetadata, Object token,
boolean insertAsArchiveManifest) throws InserterException {
this.parent = put;
+ this.insertAsArchiveManifest = insertAsArchiveManifest;
this.token = token;
this.finished = false;
this.isMetadata = isMetadata;
@@ -149,7 +151,7 @@
if(!missingURIs) {
// Create Metadata
- m = new Metadata(splitfileAlgorithm, dataURIs,
checkURIs, segmentSize, checkSegmentSize, cm, dataLength, compressionCodec,
isMetadata);
+ m = new Metadata(splitfileAlgorithm, dataURIs,
checkURIs, segmentSize, checkSegmentSize, cm, dataLength, compressionCodec,
isMetadata, insertAsArchiveManifest);
}
haveSentMetadata = true;
}
Modified: trunk/freenet/src/freenet/keys/FreenetURI.java
===================================================================
--- trunk/freenet/src/freenet/keys/FreenetURI.java 2006-05-19 22:36:32 UTC
(rev 8792)
+++ trunk/freenet/src/freenet/keys/FreenetURI.java 2006-05-20 01:54:17 UTC
(rev 8793)
@@ -12,6 +12,7 @@
import java.util.Vector;
import freenet.support.Base64;
+import freenet.support.Fields;
import freenet.support.HexUtil;
import freenet.support.IllegalBase64Exception;
import freenet.support.Logger;
@@ -63,6 +64,29 @@
private final String[] metaStr;
private final byte[] routingKey, cryptoKey, extra;
private final long suggestedEdition; // for USKs
+ private boolean hasHashCode;
+ private int hashCode;
+
+ public int hashCode() {
+ if(hasHashCode) return hashCode;
+ int x = keyType.hashCode();
+ if(docName != null) x ^= docName.hashCode();
+ if(metaStr != null) {
+ for(int i=0;i<metaStr.length;i++)
+ x ^= metaStr[i].hashCode();
+ }
+ if(routingKey != null)
+ x ^= Fields.hashCode(routingKey);
+ if(cryptoKey != null)
+ x ^= Fields.hashCode(cryptoKey);
+ if(extra != null)
+ x ^= Fields.hashCode(extra);
+ if(keyType.equals("USK"))
+ x ^= suggestedEdition;
+ hashCode = x;
+ hasHashCode = true;
+ return x;
+ }
public boolean equals(Object o) {
if(!(o instanceof FreenetURI))
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2006-05-19 22:36:32 UTC (rev
8792)
+++ trunk/freenet/src/freenet/node/Node.java 2006-05-20 01:54:17 UTC (rev
8793)
@@ -85,7 +85,6 @@
import freenet.keys.NodeSSK;
import freenet.keys.SSKBlock;
import freenet.keys.SSKVerifyException;
-import freenet.node.TextModeClientInterfaceServer.TMCIBindtoCallback;
import freenet.node.fcp.FCPServer;
import freenet.pluginmanager.PluginManager;
import freenet.store.BerkeleyDBFreenetStore;
@@ -547,7 +546,7 @@
// Client stuff that needs to be configged - FIXME
static final int MAX_ARCHIVE_HANDLERS = 200; // don't take up much RAM...
FIXME
static final long MAX_CACHED_ARCHIVE_DATA = 32*1024*1024; // make a fixed
fraction of the store by default? FIXME
- static final long MAX_ARCHIVE_SIZE = 1024*1024; // ??? FIXME
+ static final long MAX_ARCHIVE_SIZE = 2*1024*1024; // ??? FIXME
static final long MAX_ARCHIVED_FILE_SIZE = 1024*1024; // arbitrary... FIXME
static final int MAX_CACHED_ELEMENTS = 1024; // equally arbitrary! FIXME
hopefully we can cache many of these though
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-05-19 22:36:32 UTC (rev
8792)
+++ trunk/freenet/src/freenet/node/Version.java 2006-05-20 01:54:17 UTC (rev
8793)
@@ -18,7 +18,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 730;
+ private static final int buildNumber = 731;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 698;
Modified: trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
2006-05-19 22:36:32 UTC (rev 8792)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
2006-05-20 01:54:17 UTC (rev 8793)
@@ -47,7 +47,7 @@
throws MessageInvalidException {
// Create a directory listing of Buckets of data, mapped to
ManifestElement's.
// Directories are sub-HashMap's.
- HashMap buckets = makeBucketsByName(dirname);
+ HashMap buckets = makeBucketsByName(dirname, "");
handler.startClientPutDir(this, buckets);
}
@@ -56,7 +56,7 @@
* and its subdirs.
* @throws MessageInvalidException
*/
- private HashMap makeBucketsByName(File thisdir) throws
MessageInvalidException {
+ private HashMap makeBucketsByName(File thisdir, String prefix) throws
MessageInvalidException {
Logger.minor(this, "Listing directory: "+thisdir);
@@ -74,9 +74,9 @@
FileBucket bucket = new FileBucket(f, true,
false, false, false);
- ret.put(f.getName(), new
ManifestElement(f.getName(), bucket, null, f.length()));
+ ret.put(f.getName(), new
ManifestElement(f.getName(), prefix + f.getName(), bucket, null, f.length()));
} else if(filelist[i].isDirectory()) {
- HashMap subdir = makeBucketsByName(new
File(thisdir, filelist[i].getName()));
+ HashMap subdir = makeBucketsByName(new
File(thisdir, filelist[i].getName()), prefix + filelist[i].getName() + "/" );
ret.put(filelist[i].getName(), subdir);
} else if(!allowUnreadableFiles) {
throw new
MessageInvalidException(ProtocolErrorMessage.FILE_NOT_FOUND, "Not directory and
not file: "+filelist[i], identifier);
Modified: trunk/freenet/src/freenet/support/LRUHashtable.java
===================================================================
--- trunk/freenet/src/freenet/support/LRUHashtable.java 2006-05-19 22:36:32 UTC
(rev 8792)
+++ trunk/freenet/src/freenet/support/LRUHashtable.java 2006-05-20 01:54:17 UTC
(rev 8793)
@@ -30,7 +30,7 @@
insert.value = value;
list.remove(insert);
}
- Logger.minor(this, "Pushed "+insert);
+ Logger.minor(this, "Pushed "+insert+" ( "+key+" "+value+" )");
list.unshift(insert);
}