On Tuesday 14 April 2009 20:24:13 sa...@freenetproject.org wrote:
> Author: saces
> Date: 2009-04-14 19:24:13 +0000 (Tue, 14 Apr 2009)
> New Revision: 26799
> 
> Added:
>    trunk/freenet/src/freenet/client/async/BaseManifestPutter.java
> Log:
> new ManifestPutter infrastructure
> this class BaseManifestPutter contains all the code to insert the stuff and 
provide helpers functions to add elements,
> but does not have any 'pack logic'. this needs to be implemented in sub 
classes.
> 
> 
> Added: trunk/freenet/src/freenet/client/async/BaseManifestPutter.java
> ===================================================================
> --- trunk/freenet/src/freenet/client/async/BaseManifestPutter.java            
>                 
(rev 0)
> +++ trunk/freenet/src/freenet/client/async/BaseManifestPutter.java    
2009-04-14 19:24:13 UTC (rev 26799)
> @@ -0,0 +1,1864 @@
> +package freenet.client.async;
> +
> +import java.io.IOException;
> +import java.util.ArrayList;
> +import java.util.HashMap;
> +import java.util.HashSet;
> +import java.util.Iterator;
> +import java.util.List;
> +import java.util.Map;
> +import java.util.Stack;
> +import java.util.Vector;
> +
> +import com.db4o.ObjectContainer;
> +
> +import freenet.client.ClientMetadata;
> +import freenet.client.DefaultMIMETypes;
> +import freenet.client.InsertBlock;
> +import freenet.client.InsertContext;
> +import freenet.client.InsertException;
> +import freenet.client.Metadata;
> +import freenet.client.MetadataUnresolvedException;
> +import freenet.client.ArchiveManager.ARCHIVE_TYPE;
> +import freenet.client.events.SplitfileProgressEvent;
> +import freenet.keys.BaseClientKey;
> +import freenet.keys.FreenetURI;
> +import freenet.node.RequestClient;
> +import freenet.support.LogThresholdCallback;
> +import freenet.support.Logger;
> +import freenet.support.api.Bucket;
> +import freenet.support.io.BucketTools;
> +import freenet.support.io.NativeThread;
> +
> +public abstract class BaseManifestPutter extends BaseClientPutter 
implements PutCompletionCallback {
> +
> +     private static volatile boolean logMINOR;
> +     private static volatile boolean logDEBUG;
> +     
> +     static {
> +             Logger.registerLogThresholdCallback(new LogThresholdCallback() {
> +                     
> +                     @Override
> +                     public void shouldUpdate() {
> +                             logMINOR = Logger.shouldLog(Logger.MINOR, this);
> +                             logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
> +                     }
> +             });
> +     }
> +     
> +     // Only implements PutCompletionCallback for the final metadata insert
> +     protected class PutHandler extends BaseClientPutter implements 
PutCompletionCallback {
> +             
> +             protected PutHandler(final BaseManifestPutter smp, String name, 
> Bucket 
data, ClientMetadata cm, boolean getCHKOnly) {
> +                     this(smp, null, name, data, cm, getCHKOnly);
> +             }
> +                     
> +             protected PutHandler(final BaseManifestPutter smp, PutHandler 
> parent, 
String name, Bucket data, ClientMetadata cm, boolean getCHKOnly) {
> +                     super(smp.priorityClass, smp.client);
> +                     this.persistent = BaseManifestPutter.this.persistent();
> +                     this.cm = cm;
> +                     this.name = name;
> +                     InsertBlock block = 
> +                             new InsertBlock(data, cm, persistent() ? 
FreenetURI.EMPTY_CHK_URI.clone() : FreenetURI.EMPTY_CHK_URI);
> +                     this.origSFI =
> +                             new SingleFileInserter(this, this, block, 
> false, ctx, false, 
getCHKOnly, true, null, null, false, null, earlyEncode);
> +                     metadata = null;
> +                     parentContainerHandle = parent;
> +                     isArchive = isContainer = false;
> +             }
> +             
> +             //protected PutHandler(final SimpleManifestPutter smp, String 
> name, 
HashMap<String, Object> data, ClientMetadata cm, boolean getCHKOnly) {
> +             //      this(smp, null, name, data, cm, getCHKOnly);
> +             //}
> +                             
> +             protected PutHandler(final BaseManifestPutter smp, PutHandler 
> parent, 
String name, HashMap<String, Object> data, ClientMetadata cm, boolean 
getCHKOnly, boolean isArchive2) {
> +                     super(smp.priorityClass, smp.client);
> +                     this.persistent = BaseManifestPutter.this.persistent();
> +                     this.cm = cm;
> +                     this.name = name;
> +                     this.origSFI =
> +                             new ContainerInserter(this, this, data, 
> (persistent ? 
FreenetURI.EMPTY_CHK_URI.clone() : FreenetURI.EMPTY_CHK_URI), ctx, false, 
getCHKOnly, !isArchive2, null, ARCHIVE_TYPE.TAR, false, earlyEncode);
> +                     metadata = null;
> +                     parentContainerHandle = parent;
> +                     isContainer = true;
> +                     isArchive = isArchive2;
> +             }
> +
> +             protected PutHandler(final BaseManifestPutter smp, String name, 
FreenetURI target, ClientMetadata cm) {
> +                     this(smp, null, name, name, target, cm);
> +             }
> +                             
> +             protected PutHandler(final BaseManifestPutter smp, PutHandler 
> parent, 
String name, String targetInArchive2, FreenetURI target, ClientMetadata cm) {
> +                     super(smp.getPriorityClass(), smp.client);
> +                     this.persistent = BaseManifestPutter.this.persistent();
> +                     this.cm = cm;
> +                     this.name = name;
> +                     Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
> null, null, target, 
cm);
> +                     metadata = m;
> +                     if(logMINOR) Logger.minor(this, "Simple redirect 
> metadata: "+m);
> +                     origSFI = null;
> +                     parentContainerHandle = parent;
> +                     isArchive = isContainer = false;
> +                     targetInArchive = targetInArchive2;
> +             }
> +             
> +             private ClientPutState origSFI;
> +             private ClientPutState currentState;
> +             private ClientMetadata cm;
> +             private Metadata metadata;
> +             private String targetInArchive;
> +             private final String name;
> +             private final boolean persistent;
> +             private final PutHandler parentContainerHandle;

Why is this not a ContainerInserter?

> +             private final boolean isContainer;
> +             private final boolean isArchive;
> +             
> +             public void start(ObjectContainer container, ClientContext 
> context) 
throws InsertException {
> +                     if (logDEBUG)
> +                             Logger.debug(this, "Starting a PutHandler for 
> '"+this.name+"' 
(isRootContainer="+ (this==rootContainerPutHandler)+", 
isArchive="+this.isArchive+") " + this);
> +                     
> +                     if (origSFI == null) {
> +                              Logger.error(this, "origSFI is null on 
> start(), should be impossible", 
new Exception("debug"));
> +                              return;
> +                     }
> +                     if (metadata != null) {
> +                             Logger.error(this, "metdata=" + metadata + " on 
> start(), should be 
impossible", new Exception("debug"));
> +                             return;
> +                     }
> +                     ClientPutState sfi;
> +                     synchronized(this) {
> +                             sfi = origSFI;
> +                             currentState = sfi;
> +                             origSFI = null;
> +                     }
> +                     if(persistent) {
> +                             container.activate(sfi, 1);
> +                             container.store(this);
> +                     }
> +                     sfi.schedule(container, context);
> +                     if(persistent) {
> +                             container.deactivate(sfi, 1);
> +                     }
> +             }
> +             
> +             @Override
> +             public void cancel(ObjectContainer container, ClientContext 
> context) {
> +                     if(logMINOR) Logger.minor(this, "Cancelling "+this, new 
Exception("debug"));
> +                     ClientPutState oldState = null;
> +                     synchronized(this) {
> +                             if(cancelled) return;
> +                             super.cancel();
> +                             oldState = currentState;
> +                     }
> +                     if(persistent()) {
> +                             container.store(this);
> +                             if(oldState != null)
> +                                     container.activate(oldState, 1);
> +                     }
> +                     if(oldState != null) oldState.cancel(container, 
> context);
> +                     onFailure(new 
> InsertException(InsertException.CANCELLED), null, 
container, context);
> +             }
> +             
> +             @Override
> +             public FreenetURI getURI() {
> +                     return null;
> +             }
> +
> +             @Override
> +             public boolean isFinished() {
> +                     if(logMINOR) Logger.minor(this, "Finished "+this, new 
Exception("debug"));
> +                     return BaseManifestPutter.this.finished || cancelled || 
BaseManifestPutter.this.cancelled;
> +             }
> +
> +             public void onSuccess(ClientPutState state, ObjectContainer 
> container, 
ClientContext context) {
> +                     if(logMINOR) Logger.minor(this, "Completed 
> '"+this.name+"' "+this);
> +                     
> +                     
> +                     if (isArchive) {
> +                             
> +                             Vector<PutHandler> phv = 
> putHandlersArchiveTransformMap.get(this);

You probably need to activate BaseManifestPutter and 
putHandlersArchiveTransformMap, right? (Always activate maps to depth 2)

> +                             for (PutHandler ph: phv) {
> +//                                   
> +                                     
perContainerPutHandlersWaitingForFetchable.get(ph.parentContainerHandle).remove(this);
> +//                                   Metadata m = new 
> Metadata(Metadata.SIMPLE_REDIRECT, null, null, 
archiveURI.setDocName(targetInArchive), cm);
> +//                                   hm.put(ph.name, m);
> +//                                   putHandlersTransformMap.remove(ph);
> +                                     try {
> +                                             
> maybeStartParentContainer(ph.parentContainerHandle, container, 
context);
> +                                     } catch (InsertException e) {
> +                                             fail(new 
> InsertException(InsertException.INTERNAL_ERROR, e, null), 
container, context);
> +                                             return;
> +                                     }
> +                             }
> +                             return;
> +                     }
> +                     
> +                     if(persistent) {
> +                             container.activate(BaseManifestPutter.this, 1);
> +                             container.activate(runningPutHandlers, 2);
> +                     }
> +                     BaseManifestPutter.this.onFetchable(this, container);
> +                     ClientPutState oldState;
> +                     boolean insertedAllFiles = true;
> +                     synchronized(this) {
> +                             oldState = currentState;
> +                             currentState = null;
> +                     }
> +                     synchronized(BaseManifestPutter.this) {
> +                             if(persistent) container.store(this);
> +                             runningPutHandlers.remove(this);
> +                             if(persistent) {
> +                                     
> container.ext().store(runningPutHandlers, 2);
> +                                     
> container.activate(putHandlersWaitingForMetadata, 2);
> +                             }
> +                             
> if(putHandlersWaitingForMetadata.contains(this)) {
> +                                     
> putHandlersWaitingForMetadata.remove(this);
> +                                     
> container.ext().store(putHandlersWaitingForMetadata, 2);
> +                                     Logger.error(this, "PutHandler 
> '"+this.name+"' was in 
waitingForMetadata in onSuccess() on "+this+" for "+BaseManifestPutter.this);
> +                             }
> +                             
> +                             if(persistent) {
> +                                     
> container.deactivate(putHandlersWaitingForMetadata, 1);
> +                                     container.activate(waitingForBlockSets, 
> 2);
> +                             }
> +                             if(waitingForBlockSets.contains(this)) {
> +                                     waitingForBlockSets.remove(this);
> +                                     container.store(waitingForBlockSets);
> +                                     Logger.error(this, "PutHandler was in 
> waitingForBlockSets in 
onSuccess() on "+this+" for "+BaseManifestPutter.this);
> +                             }
> +                             if(persistent) {
> +                                     
> container.deactivate(waitingForBlockSets, 1);
> +                                     
> container.deactivate(putHandlersWaitingForFetchable, 1);
> +                                     
> container.activate(putHandlersWaitingForFetchable, 2);
> +                             }
> +                             
> if(putHandlersWaitingForFetchable.contains(this)) {
> +                                     
> putHandlersWaitingForFetchable.remove(this);
> +                                     
> container.ext().store(putHandlersWaitingForFetchable, 2);
> +                                     // Not getting an onFetchable is not 
> unusual, just ignore it.
> +                                     if(logMINOR) Logger.minor(this, 
> "PutHandler was in waitingForFetchable 
in onSuccess() on "+this+" for "+BaseManifestPutter.this);
> +                             }

You already called onFetchable, won't that have removed it from 
putHandlersWaitingForFetchable ?

> +                             if(persistent)
> +                                     
> container.deactivate(putHandlersWaitingForFetchable, 1);
> +                             
> +                             if(!runningPutHandlers.isEmpty()) {
> +                                     if(logMINOR) {
> +                                             Logger.minor(this, "Running put 
handlers: "+runningPutHandlers.size());
> +                                             for(Object o : 
> runningPutHandlers) {
> +                                                     boolean activated = 
> true;
> +                                                     if(persistent) {
> +                                                             activated = 
> container.ext().isActive(o);
> +                                                             if(!activated) 
> container.activate(o, 1);
> +                                                     }
> +                                                     Logger.minor(this, 
> "Still running: "+o);
> +                                                     if(!activated)
> +                                                             
> container.deactivate(o, 1);
> +                                             }
> +                                     }
> +                                     insertedAllFiles = false;
> +                             }
> +                     }
> +                     if(oldState != null && oldState != state && persistent) 
> {
> +                             container.activate(oldState, 1);
> +                             oldState.removeFrom(container, context);
> +                     } else if(state != null && persistent) {
> +                             state.removeFrom(container, context);
> +                     }
> +                     if(insertedAllFiles)
> +                             insertedAllFiles(container, context);
> +                     if(persistent) {
> +                             container.deactivate(runningPutHandlers, 1);
> +                             container.deactivate(BaseManifestPutter.this, 
> 1);
> +                     }
> +             }
> +
> +             public void onFailure(InsertException e, ClientPutState state, 
ObjectContainer container, ClientContext context) {
> +                     ClientPutState oldState;
> +                     synchronized(this) {
> +                             oldState = currentState;
> +                             currentState = null;
> +                     }
> +                     if(oldState != null && oldState != state && persistent) 
> {
> +                             container.activate(oldState, 1);
> +                             oldState.removeFrom(container, context);
> +                     } else if(state != null && persistent) {
> +                             state.removeFrom(container, context);
> +                     }
> +                     if(logMINOR) Logger.minor(this, "Failed: "+this+" - 
> "+e, e);
> +                     if(persistent)
> +                             container.activate(BaseManifestPutter.this, 1);
> +                     fail(e, container, context);
> +                     if(persistent)
> +                             container.deactivate(BaseManifestPutter.this, 
> 1);
> +             }
> +
> +             public void onEncode(BaseClientKey key, ClientPutState state, 
ObjectContainer container, ClientContext context) {
> +                     if(logMINOR) Logger.minor(this, "onEncode("+key+") for 
> "+this);
> +                     System.out.println("Got a URI: 
> "+key.getURI().toString(false, false) + " 
for "+this);
> +                     if (isArchive) {
> +                             
> +                             FreenetURI archiveURI = key.getURI();
> +                             
> +                             Vector<PutHandler> phv = 
> putHandlersArchiveTransformMap.get(this);

Again, you need to activate BaseManifestPutter and 
putHandlersArchiveTransformMap.

> +                             for (PutHandler ph: phv) {
> +                                     HashMap<String, Object> hm = 
> putHandlersTransformMap.get(ph);
> +                                     
> +                                     
perContainerPutHandlersWaitingForFetchable.get(ph.parentContainerHandle).remove(this);

And you need to activate these too. Remember to use 
container.ext().activate(blah,2). Re the first one, maps inside maps are 
problematic with db4o, can get activation problems as activating a map to 
depth 1 makes it no longer activatable to depth 2 ... Could you put these on 
the ContainerInserter?

> +                                     if (ph.targetInArchive == null) throw 
> new NullPointerException();
> +                                     Metadata m = new 
> Metadata(Metadata.SIMPLE_REDIRECT, null, null, 
archiveURI.setMetaString(new String[]{ph.targetInArchive}), cm);
> +                                     hm.put(ph.name, m);
> +                                     putHandlersTransformMap.remove(ph);
> +                             }
> 
+                               
//perContainerPutHandlersWaitingForFetchable.get(parentContainerHandle).remove(this);
> +                             //putHandlersArchiveTransformMap.remove(this);
> +                             return;
> +                     }
> +
> +                     if(metadata == null) {
> +                             // The file was too small to have its own 
> metadata, we get this 
instead.
> +                             // So we make the key into metadata.

> +                             if(persistent) {
> +                                     container.activate(key, 5);
> +                                     
> container.activate(BaseManifestPutter.this, 1);
> +                             }
> +                             Metadata m =
> +                                     new Metadata(Metadata.SIMPLE_REDIRECT, 
> null, null, key.getURI(), cm);
> +                             onMetadata(m, null, container, context);
> +                             if(persistent) {
> +                                     
> container.deactivate(BaseManifestPutter.this, 1);
> +                             }
> +                     }
> +             }
> +
> +             /**
> +              * The caller of onTransition removes the old state, so we 
> don't have to.
> +              * However, in onSuccess or onFailure, we need to remove the 
> new state, 
even if
> +              * what is passed in is different (in which case we remove that 
> too).
> +              */
> +             public void onTransition(ClientPutState oldState, 
> ClientPutState 
newState, ObjectContainer container) {
> +                     if(newState == null) throw new NullPointerException();
> +                     
> +                     // onTransition is *not* responsible for removing the 
> old state, the 
caller is.
> +                     synchronized (this) {
> +                             if (currentState == oldState) {
> +                                     currentState = newState;
> +                                     if(persistent())
> +                                             container.store(this);
> +                                     if(logMINOR)
> +                                             Logger.minor(this, 
> "onTransition: cur=" + currentState + ", old=" + 
oldState + ", new=" + newState+" for "+this);
> +                                     return;
> +                             }
> +                             Logger.error(this, "Ignoring onTransition: 
> cur=" + currentState + ", 
old=" + oldState + ", new=" + newState+" for "+this);
> +                     }
> +             }
> +
> +             public void onMetadata(Metadata m, ClientPutState state, 
> ObjectContainer 
container, ClientContext context) {
> +                     if(logMINOR) Logger.minor(this, "Assigning metadata: 
> "+m+" 
for '"+this.name+"' "+this+" from "+state+" persistent="+persistent);
> +                     if(metadata != null) {
> +                             Logger.error(this, "Reassigning metadata", new 
> Exception("debug"));
> +                             return;
> +                     }
> +                     metadata = m;
> +                     
> +                     if (parentContainerHandle != null) {
> +                             // it is a subcontainer/archive, but not the 
> root container
> +                             
perContainerPutHandlersWaitingForMetadata.get(parentContainerHandle).remove(this);

Again you need to activate, and may have problems with nested HashMap's.

> +                             HashMap<String, Object> hm = 
> putHandlersTransformMap.get(this);
> +                             hm.put(name, m);
> +                             putHandlersTransformMap.remove(this);
> +                             try {
> +                                     
> maybeStartParentContainer(parentContainerHandle, container, context);
> +                             } catch (InsertException e) {
> +                                     fail(new 
> InsertException(InsertException.INTERNAL_ERROR, e, null), 
container, context);
> +                             }
> +                             return;
> +                     }
> +                     
> +                     if (this==rootContainerPutHandler) {
> +                             baseMetadata = m;
> +                             resolveAndStartBase(container, context);
> +                             return;
> +                     }
> +                     
> +                     if (containerMode) {
> +                             try {
> +                                     
> rootContainerPutHandler.start(container, context);
> +                             } catch (InsertException e) {
> +                                     fail(new 
> InsertException(InsertException.INTERNAL_ERROR, e, null), 
container, context);
> +                             }
> +                             return;
> +                     }

What's going on here? If we have got here, then ... what?

Does rootContainerPutHandler.start() replace the below code? How does it get 
the metadata? It looks like it will be called repeatedly for every file that 
isn't in the root container because it is too big, and they will not report 
their metadata?
> +                     
> +                     if(persistent) {
> +                             container.activate(BaseManifestPutter.this, 1);
> +                             
> container.activate(putHandlersWaitingForMetadata, 2);
> +                     }
> +                     boolean allMetadatas = false;
> +                     
> +                     synchronized(BaseManifestPutter.this) {
> +                             putHandlersWaitingForMetadata.remove(this);
> +                             if(persistent) {
> +                                     
> container.ext().store(putHandlersWaitingForMetadata, 2);
> +                                     container.store(this);
> +                             }
> +                             allMetadatas = 
> putHandlersWaitingForMetadata.isEmpty();
> +                             if(!allMetadatas) {
> +                                     if(logMINOR)
> +                                             Logger.minor(this, "Still 
> waiting for 
metadata: "+putHandlersWaitingForMetadata.size());
> +                             }
> +                     }
> +                     if(allMetadatas) {
> +                             // Will resolve etc.
> +                             gotAllMetadata(container, context);
> +                     } else {
> +                             // Resolve now to speed up the insert.
> +                             try {
> +                                     byte[] buf = m.writeToByteArray();
> +                                     if(buf.length > 
> Metadata.MAX_SIZE_IN_MANIFEST)
> +                                             throw new 
> MetadataUnresolvedException(new Metadata[] { m }, "Too 
big");
> +                             } catch (MetadataUnresolvedException e) {
> +                                     try {
> +                                             resolve(e, container, context);
> +                                     } catch (IOException e1) {
> +                                             fail(new 
> InsertException(InsertException.BUCKET_ERROR, e1, null), 
container, context);
> +                                             return;
> +                                     } catch (InsertException e1) {
> +                                             fail(e1, container, context);
> +                                     }
> +                             }
> +                     }
> +                     if(persistent) {
> +                             
> container.deactivate(putHandlersWaitingForMetadata, 1);
> +                             container.deactivate(BaseManifestPutter.this, 
> 1);
> +                     }
> +             }
> +
...
> +
> +             public void onBlockSetFinished(ClientPutState state, 
> ObjectContainer 
container, ClientContext context) {
> +                     if(persistent) {
> +                             container.activate(BaseManifestPutter.this, 1);
> +                             container.activate(waitingForBlockSets, 2);
> +                     }
> +                     boolean allBlockSets = false;
> +                     synchronized(BaseManifestPutter.this) {
> +                             waitingForBlockSets.remove(this);
> +                             if(persistent)
> +                                     container.store(waitingForBlockSets);

container.ext().store(waitingForBlockSets, 2)
Necessary or it will update stuff to depth.

> +                             allBlockSets = waitingForBlockSets.isEmpty();
> +                     }
> +                     if(allBlockSets)
> +                             
> BaseManifestPutter.this.blockSetFinalized(container, context);
> +                     if(persistent) {
> +                             container.deactivate(waitingForBlockSets, 1);
> +                             container.deactivate(BaseManifestPutter.this, 
> 1);
> +                     }
> +             }
> +
...

> +             @Override
> +             public void removeFrom(ObjectContainer container, ClientContext 
> context) 
{
> +                     if(logMINOR) Logger.minor(this, "Removing "+this);
> +                     ClientPutState oldSFI;
> +                     ClientPutState oldState;
> +                     synchronized(this) {
> +                             oldSFI = origSFI;
> +                             oldState = currentState;
> +                             oldSFI = null;
> +                             currentState = null;
> +                     }
> +                     if(oldSFI != null) {
> +                             Logger.error(this, "origSFI is set in 
> removeFrom() on "+this+" 
for "+BaseManifestPutter.this, new Exception("debug"));
> +                             container.activate(oldSFI, 1);
> +                             oldSFI.cancel(container, context);
> +                             oldSFI.removeFrom(container, context);
> +                             if(oldState == oldSFI) oldState = null;
> +                     }
> +                     if(oldState != null) {
> +                             Logger.error(this, "currentState is set in 
> removeFrom() on "+this+" 
for "+BaseManifestPutter.this, new Exception("debug"));
> +                             container.activate(oldState, 1);
> +                             oldState.cancel(container, context);
> +                             oldState.removeFrom(container, context);
> +                     }
> +                     if(cm != null) {
> +                             container.activate(cm, 5);
> +                             cm.removeFrom(container);
> +                     }
> +                     if(metadata != null) {
> +                             // Possible if cancelled
> +                             Logger.normal(this, "Metadata is set in 
> removeFrom() on "+this+" 
for "+BaseManifestPutter.this);
> +                             container.activate(metadata, 1);
> +                             metadata.removeFrom(container);
> +                     }
> +                     // Data is responsibility of original caller (usually 
> ClientPutDir), we 
don't support freeData atm
> +                     super.removeFrom(container, context);
> +             }

You will eventually need to debug, or get me to debug, database leaks 
resulting from the new code (e.g. who removes the ContainerInserter's?).
> +
> +     // if true top level metadata is a container
> +     private boolean containerMode = false;
> +     private ContainerBuilder rootContainer;
> +     private PutHandler rootContainerPutHandler;
> +     private HashSet<PutHandler> containerPutHandlers;
> +     private HashMap<PutHandler, HashSet<PutHandler>> 
perContainerPutHandlersWaitingForMetadata;
> +     private HashMap<PutHandler, HashSet<PutHandler>> 
perContainerPutHandlersWaitingForFetchable;
> +     private HashMap<PutHandler, HashMap<String, Object>> 
putHandlersTransformMap;
> +     private HashMap<PutHandler, Vector<PutHandler>> 
putHandlersArchiveTransformMap;
> +     
> +     private HashMap<String,Object> putHandlersByName;
> +     private HashSet<PutHandler> runningPutHandlers;
> +     private HashSet<PutHandler> putHandlersWaitingForMetadata;
> +     private HashSet<PutHandler> waitingForBlockSets;
> +     private HashSet<PutHandler> putHandlersWaitingForFetchable;
> +     private FreenetURI finalURI;
> +     private FreenetURI targetURI;
> +     private boolean finished;
> +     private final InsertContext ctx;
> +     final ClientCallback cb;
> +     private final boolean getCHKOnly;
> +     private boolean insertedAllFiles;
> +     private boolean insertedManifest;
> +     private final HashMap<Metadata,ClientPutState> 
> metadataPuttersByMetadata;
> +     private final HashMap<Metadata,ClientPutState> 
> metadataPuttersUnfetchable;

Do you need these? Hmmm, yes you do because you resolve() stuff rather than 
trying to put it into auxiliary .metadata.N's, which it turns out I didn't 
implement I just thought about ...
> +     
> +     private PutHandler[] getContainersToStart() {
> +             PutHandler[] maybeStartPH = containerPutHandlers.toArray(new 
PutHandler[containerPutHandlers.size()]);
> +             ArrayList<PutHandler> phToStart = new ArrayList<PutHandler>();
> +             
> +             for (PutHandler ph: maybeStartPH) {
> +                     if 
> (perContainerPutHandlersWaitingForMetadata.get(ph).isEmpty() && 
perContainerPutHandlersWaitingForFetchable.get(ph).isEmpty() ) {

More activation. I get the impression you haven't tested this with persistent 
site inserts? :)

> +                             phToStart.add(ph); 
> +                     }
> +             }
> +             if (maybeStartPH.length == 0) {
> +                     phToStart.add(rootContainer.selfHandle);
> +             }
> +             return phToStart.toArray(new PutHandler[phToStart.size()]);
> +     }
> +
...

> +     /**
> +      * Cancel all running inserters.
> +      */
> +     private void cancelAndFinish(ObjectContainer container, ClientContext 
context) {
> +             PutHandler[] running;
> +             boolean persistent = persistent();
> +             if(persistent)
> +                     container.activate(runningPutHandlers, 2);
> +             synchronized(this) {
> +                     running = runningPutHandlers.toArray(new 
PutHandler[runningPutHandlers.size()]);
> +             }
> +             
> +             if(logMINOR) Logger.minor(this, "PutHandler's to 
cancel: "+running.length);
> +             for(PutHandler putter : running) {
> +                     boolean active = true;
> +                     if(persistent) {
> +                             active = container.ext().isActive(putter);
> +                             if(!active) container.activate(putter, 1);
> +                     }
> +                     putter.cancel(container, context);
> +                     if(!active) container.deactivate(putter, 1);
> +                     if(persistent) container.activate(this, 1);
> +             }
> +             
> +             ClientPutState[] runningMeta;
> +             if(persistent())
> +                     container.activate(metadataPuttersByMetadata, 2);
> +             synchronized(this) {
> +                     runningMeta = 
> metadataPuttersByMetadata.values().toArray(new 
ClientPutState[metadataPuttersByMetadata.size()]);
> +             }
> +             
> +             if(logMINOR) Logger.minor(this, "Metadata putters to 
cancel: "+runningMeta.length);
> +             for(ClientPutState putter : runningMeta) {
> +                     boolean active = true;
> +                     if(persistent) {
> +                             active = container.ext().isActive(putter);
> +                             if(!active) container.activate(putter, 1);
> +                     }
> +                     putter.cancel(container, context);
> +                     if(!active) container.deactivate(putter, 1);
> +                     if(persistent) container.activate(this, 1);
> +             }
> +             
> +     }

What about running container inserters? The base container inserter?
> +
> +     private void maybeStartParentContainer(PutHandler containerHandle2, 
ObjectContainer container, ClientContext context) throws InsertException {
> +             if 
(perContainerPutHandlersWaitingForMetadata.get(containerHandle2).isEmpty() && 
perContainerPutHandlersWaitingForFetchable.get(containerHandle2).isEmpty()) {
> +                     containerHandle2.start(container, context);

More activation.
...
> +     
> +     public ContainerBuilder makeArchive() {
> +             return new ContainerBuilder(false, null, null, true);
> +     }
> +
> +     protected ContainerBuilder getRootContainer() {
> +             if (!containerMode) {
> +                     containerMode = true;
> +                     rootContainer = new ContainerBuilder(true);
> +                     putHandlersByName = null;
> +             }
> +             return rootContainer;
> +     }
> +     
> +     protected final class ContainerBuilder {
> +             
> +             private final HashMap<String, Object> rootDir;
> +             private HashMap<String, Object> currentDir;
> +             private final PutHandler selfHandle;
> +             
> +             private final Stack<HashMap<String, Object>> dirStack;
> +             
> +             private ContainerBuilder(boolean isRoot) {
> +                     this(isRoot, null, null, false);
> +             }
> +             
> +             private ContainerBuilder(PutHandler parent, String name) {
> +                     this(false, parent, name, false);
> +             }
> +             
> +             private ContainerBuilder(boolean isRoot, PutHandler parent, 
> String name, 
boolean isArchive) {
> +                     if (putHandlersByName != null && 
> putHandlersByName.size() > 0) {
> +                             throw new IllegalStateException("You can not 
> add containers in free 
form mode!");
> +                     }

Even more activation. :|

> +                     dirStack = new Stack<HashMap<String, Object>>();
> +                     rootDir = new HashMap<String, Object>();
> +                     selfHandle = new PutHandler(BaseManifestPutter.this, 
> parent, name, 
rootDir, null, getCHKOnly, isArchive);
> +                     currentDir = rootDir;
> +                     if (isRoot) {
> +                             rootContainerPutHandler = selfHandle;
> +                     } else {
> +                             containerPutHandlers.add(selfHandle);
> +                     }
> +                     
> perContainerPutHandlersWaitingForMetadata.put(selfHandle, new 
HashSet<PutHandler>());
> +                     
> perContainerPutHandlersWaitingForFetchable.put(selfHandle, new 
HashSet<PutHandler>());
> +                     if (isArchive) 
> putHandlersArchiveTransformMap.put(selfHandle, new 
Vector<PutHandler>());

And even more.
> +             }
> +             
> +             public ContainerBuilder makeSubContainer(String name) {
> +                     ContainerBuilder subCon = new 
> ContainerBuilder(selfHandle, name);
> +                     currentDir.put(name , subCon.selfHandle);
> +                     
perContainerPutHandlersWaitingForMetadata.get(selfHandle).add(subCon.selfHandle);
> +                     putHandlersTransformMap.put(subCon.selfHandle, 
> currentDir);

And more.
> 
+                       
//perContainerPutHandlersWaitingForFetchable.get(selfHandle).add(subCon.selfHandle);
> +                     return subCon;
> +             }
> +             
> +             public void makeSubDirCD(String name) {
> +                     currentDir = makeSubDir(currentDir, name);
> +             }
> +             
> +             private HashMap<String, Object> makeSubDir(HashMap<String, 
> Object> 
parentDir, String name) {
> +                     HashMap<String, Object> newDir = new HashMap<String, 
> Object>();
> +                     parentDir.put(name , newDir);
> +                     return newDir;
> +             }
> +             
> +             public void addItem(String name, String nameInArchive, String 
mimeOverride, Bucket data) {
> +                     addItem(name, nameInArchive, mimeOverride, data, false);
> +             }
> +             
> +             public void addItem(String name, String nameInArchive, String 
mimeOverride, Bucket data, boolean isDefaultDoc) {
> +                     ManifestElement element = new ManifestElement(name, 
> nameInArchive, data, 
mimeOverride, data.size());
> +                     addElement(name, element, isDefaultDoc);
> +             }
> +             
> +             public void addRedirect(String name, String mimeOverride, 
> FreenetURI 
targetURI2) {
> +                     addRedirect(name, mimeOverride, targetURI2, false);
> +             }
> +             
> +             public void addRedirect(String name, String mimeOverride, 
> FreenetURI 
targetURI2, boolean isDefaultDoc) {
> +                     ManifestElement element = new ManifestElement(name, 
> targetURI2, 
mimeOverride);
> +                     addElement(name, element, isDefaultDoc);
> +             }
> +             
> +             public void addExternal(String name, String mimeOverride, 
> Bucket data) {
> +                     addExternal(name, mimeOverride, data, false);
> +             }
> +             
> +             public void addExternal(String name, String mimeOverride, 
> Bucket data, 
boolean isDefaultDoc) {
> +                     PutHandler ph = new PutHandler(BaseManifestPutter.this, 
> selfHandle, 
name, data, guessMime(name, mimeOverride), getCHKOnly);
> +                     runningPutHandlers.add(ph);
> +                     
> perContainerPutHandlersWaitingForMetadata.get(selfHandle).add(ph);
> +                     putHandlersTransformMap.put(ph, currentDir);

And more. Storing more stuff than will fit in memory always sucks. :|

> +             }
> +             
> +             private void addElement(String name, ManifestElement element, 
> boolean 
isDefaultDoc) {
> +                     currentDir.put(name, element);
> +                     if (isDefaultDoc) currentDir.put("", element);
> +             }
> +
> +             public void addArchiveItem(ContainerBuilder archive, String 
> name, String 
nameInArchive, String mimeTypeOverride, Bucket data) {
> +                     addArchiveItem(archive, name, nameInArchive, 
> mimeTypeOverride, data, 
false);
> +             }
> +             
> +             public void addArchiveItem(ContainerBuilder archive, String 
> name, String 
nameInArchive, String mimeTypeOverride, Bucket data, boolean isDefaultDoc) {
> +                     archive.addItem(name, nameInArchive, mimeTypeOverride, 
> data, 
isDefaultDoc);
> +                     PutHandler ph = new PutHandler(BaseManifestPutter.this, 
> selfHandle, 
name, nameInArchive, FreenetURI.EMPTY_CHK_URI, guessMime(name, 
mimeTypeOverride));
> +                     putHandlersTransformMap.put(ph, currentDir);
> +                     
perContainerPutHandlersWaitingForFetchable.get(selfHandle).add(archive.selfHandle);
> +                     
> putHandlersArchiveTransformMap.get(archive.selfHandle).add(ph);

And again.

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Devl mailing list
Devl@freenetproject.org
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/devl

Reply via email to