Author: toad
Date: 2008-08-29 23:38:45 +0000 (Fri, 29 Aug 2008)
New Revision: 22239

Modified:
   branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java
Log:
Improve too many decompressors workaround.
Deactivation.
Store SingleFileFetcher before running and deactivating.
Don't deactivate SFF.this if it was already active in some callbacks.
Trivial refactoring / removal of unnecessary code.
Logging.


Modified: branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java       
2008-08-29 23:33:28 UTC (rev 22238)
+++ branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java       
2008-08-29 23:38:45 UTC (rev 22239)
@@ -119,8 +119,8 @@
                if(recursionLevel > ctx.maxRecursionLevel)
                        throw new 
FetchException(FetchException.TOO_MUCH_RECURSION);
                this.thisKey = fetcher.thisKey;
-               // Copy the decompressors. Just because a multi-level metadata 
splitfile
-               // is compressed, that **doesn't** mean that the data we are 
eventually
+               // Copy the decompressors. Just because a multi-level metadata 
splitfile 
+               // is compressed, that **doesn't** mean that the data we are 
eventually 
                // going to fetch is!
                this.decompressors = new ArrayList(fetcher.decompressors);
                this.uri = fetcher.uri;
@@ -199,11 +199,17 @@
                }
                if(!decompressors.isEmpty()) {
                        Bucket data = result.asBucket();
+                       boolean tooManyDecompressors = decompressors.size() > 1;
                        while(!decompressors.isEmpty()) {
                                Compressor c = (Compressor) 
decompressors.remove(decompressors.size()-1);
                                try {
                                        long maxLen = 
Math.max(ctx.maxTempLength, ctx.maxOutputLength);
-                                       data = c.decompress(data, 
context.getBucketFactory(parent.persistent()), maxLen, maxLen * 4, 
decompressors.isEmpty() ? returnBucket : null);
+                                       Bucket out;
+                                       if(tooManyDecompressors)
+                                               out = null;
+                                       else
+                                               out = decompressors.isEmpty() ? 
returnBucket : null;
+                                       data = c.decompress(data, 
context.getBucketFactory(parent.persistent()), maxLen, maxLen * 4, out);
                                } catch (IOException e) {
                                        onFailure(new 
FetchException(FetchException.BUCKET_ERROR, e), false, container, context);
                                        return;
@@ -347,21 +353,29 @@
                                                                onFailure(new 
FetchException(FetchException.BUCKET_ERROR, e), false, container, context);
                                                                return;
                                                        }
+                                                       if(persistent)
+                                                               
container.deactivate(SingleFileFetcher.this, 1);
                                                }
                                                public void 
notInArchive(ObjectContainer container, ClientContext context) {
                                                        if(persistent)
                                                                
container.activate(SingleFileFetcher.this, 1);
                                                        onFailure(new 
FetchException(FetchException.INTERNAL_ERROR, "No metadata in container! Cannot 
happen as ArchiveManager should synthesise some!"), false, container, context);
+                                                       if(persistent)
+                                                               
container.deactivate(SingleFileFetcher.this, 1);
                                                }
                                                public void 
onFailed(ArchiveRestartException e, ObjectContainer container, ClientContext 
context) {
                                                        if(persistent)
                                                                
container.activate(SingleFileFetcher.this, 1);
                                                        
SingleFileFetcher.this.onFailure(new FetchException(e), false, container, 
context);
+                                                       if(persistent)
+                                                               
container.deactivate(SingleFileFetcher.this, 1);
                                                }
                                                public void 
onFailed(ArchiveFailureException e, ObjectContainer container, ClientContext 
context) {
                                                        if(persistent)
                                                                
container.activate(SingleFileFetcher.this, 1);
                                                        
SingleFileFetcher.this.onFailure(new FetchException(e), false, container, 
context);
+                                                       if(persistent)
+                                                               
container.deactivate(SingleFileFetcher.this, 1);
                                                }
                                        }, container, context); // will result 
in this function being called again
                                        if(persistent) container.set(this);
@@ -432,21 +446,29 @@
                                                        }
                                                        // Return the data
                                                        onSuccess(new 
FetchResult(clientMetadata, out), container, context);
+                                                       if(persistent)
+                                                               
container.deactivate(SingleFileFetcher.this, 1);
                                                }
                                                public void 
notInArchive(ObjectContainer container, ClientContext context) {
                                                        if(persistent)
                                                                
container.activate(SingleFileFetcher.this, 1);
                                                        onFailure(new 
FetchException(FetchException.NOT_IN_ARCHIVE), false, container, context);
+                                                       if(persistent)
+                                                               
container.deactivate(SingleFileFetcher.this, 1);
                                                }
                                                public void 
onFailed(ArchiveRestartException e, ObjectContainer container, ClientContext 
context) {
                                                        if(persistent)
                                                                
container.activate(SingleFileFetcher.this, 1);
                                                        
SingleFileFetcher.this.onFailure(new FetchException(e), false, container, 
context);
+                                                       if(persistent)
+                                                               
container.deactivate(SingleFileFetcher.this, 1);
                                                }
                                                public void 
onFailed(ArchiveFailureException e, ObjectContainer container, ClientContext 
context) {
                                                        if(persistent)
                                                                
container.activate(SingleFileFetcher.this, 1);
                                                        
SingleFileFetcher.this.onFailure(new FetchException(e), false, container, 
context);
+                                                       if(persistent)
+                                                               
container.deactivate(SingleFileFetcher.this, 1);
                                                }
                                        }, container, context);
                                        // Will call back into this function 
when it has been fetched.
@@ -462,6 +484,7 @@
                                if(persistent) container.set(this);
                                if(persistent) container.set(f);
                                f.wrapHandleMetadata(true, container, context);
+                               if(persistent) container.deactivate(f, 1);
                                return;
                        } else if(metadata.isSingleFileRedirect()) {
                                if(logMINOR) Logger.minor(this, "Is single-file 
redirect");
@@ -660,11 +683,13 @@
                newMeta.setSimpleRedirect();
                final SingleFileFetcher f;
                f = new SingleFileFetcher(this, newMeta, new 
ArchiveFetcherCallback(forData, element, callback), new FetchContext(ctx, 
FetchContext.SET_RETURN_ARCHIVES, true), container, context);
+               if(persistent) container.set(f);
                if(logMINOR) Logger.minor(this, "fetchArchive(): "+f);
                // Fetch the archive. The archive fetcher callback will unpack 
it, and either call the element 
                // callback, or just go back around handleMetadata() on this, 
which will see that the data is now
                // available.
                f.wrapHandleMetadata(true, container, context);
+               if(persistent) container.deactivate(f, 1);
        }

        /**
@@ -725,22 +750,21 @@
                                // Run directly - we are running on some thread 
somewhere, don't worry about it.
                                innerSuccess(result, container, context);
                        } else {
+                               boolean wasActive;
                                // We are running on the database thread.
                                // Add a tag, unpack on a separate thread, copy 
the data to a persistent bucket, then schedule on the database thread,
                                // remove the tag, and call the callback.
-                               if(persistent) {
+                               wasActive = 
container.ext().isActive(SingleFileFetcher.this);
+                               if(!wasActive)
                                        
container.activate(SingleFileFetcher.this, 1);
-                                       ah.activateForExecution(container);
-                               }
+                               ah.activateForExecution(container);
                                
ah.extractPersistentOffThread(result.asBucket(), actx, element, callback, 
container, context);
+                               if(!wasActive)
+                                       
container.deactivate(SingleFileFetcher.this, 1);
                        }
                }

                private void innerSuccess(FetchResult result, ObjectContainer 
container, ClientContext context) {
-                       if(persistent) {
-                               container.activate(SingleFileFetcher.this, 1);
-                               ah.activateForExecution(container);
-                       }
                        try {
                                ah.extractToCache(result.asBucket(), actx, 
element, callback, context.archiveManager, container, context);
                        } catch (ArchiveFailureException e) {
@@ -755,18 +779,32 @@
                }

                public void onFailure(FetchException e, ClientGetState state, 
ObjectContainer container, ClientContext context) {
-                       if(persistent)
-                               container.activate(SingleFileFetcher.this, 1);
+                       boolean wasActive = true;
+                       if(persistent) {
+                               wasActive = 
container.ext().isActive(SingleFileFetcher.this);
+                               if(!wasActive)
+                                       
container.activate(SingleFileFetcher.this, 1);
+                       }
                        // Force fatal as the fetcher is presumed to have made 
a reasonable effort.
                        SingleFileFetcher.this.onFailure(e, true, container, 
context);
+                       if(wasActive)
+                               container.deactivate(SingleFileFetcher.this, 1);
                }

                public void onBlockSetFinished(ClientGetState state, 
ObjectContainer container, ClientContext context) {
+                       boolean wasActive = true;
+                       if(persistent) {
+                               wasActive = 
container.ext().isActive(SingleFileFetcher.this);
+                               if(!wasActive)
+                                       
container.activate(SingleFileFetcher.this, 1);
+                       }
                        if(persistent)
                                container.activate(rcb, 1);
                        if(wasFetchingFinalData) {
                                rcb.onBlockSetFinished(SingleFileFetcher.this, 
container, context);
                        }
+                       if(!wasActive)
+                               container.deactivate(SingleFileFetcher.this, 1);
                }

                public void onTransition(ClientGetState oldState, 
ClientGetState newState, ObjectContainer container) {
@@ -798,8 +836,11 @@
                }

                public void onSuccess(FetchResult result, ClientGetState state, 
ObjectContainer container, ClientContext context) {
-                       if(persistent)
+                       boolean wasActive = true;
+                       if(persistent) {
+                               wasActive = 
container.ext().isActive(SingleFileFetcher.this);
                                container.activate(SingleFileFetcher.this, 1);
+                       }
                        try {
                                Metadata meta = 
Metadata.construct(result.asBucket());
                                synchronized(SingleFileFetcher.this) {
@@ -807,22 +848,27 @@
                                }
                                if(persistent)
                                        container.set(SingleFileFetcher.this);
+                               wrapHandleMetadata(true, container, context);
                        } catch (MetadataParseException e) {
                                SingleFileFetcher.this.onFailure(new 
FetchException(FetchException.INVALID_METADATA, e), false, container, context);
-                               return;
                        } catch (IOException e) {
                                // Bucket error?
                                SingleFileFetcher.this.onFailure(new 
FetchException(FetchException.BUCKET_ERROR, e), false, container, context);
-                               return;
                        }
-                       wrapHandleMetadata(true, container, context);
+                       if(!wasActive)
+                               container.deactivate(SingleFileFetcher.this, 1);
                }

                public void onFailure(FetchException e, ClientGetState state, 
ObjectContainer container, ClientContext context) {
-                       if(persistent)
+                       boolean wasActive = true;
+                       if(persistent) {
+                               wasActive = 
container.ext().isActive(SingleFileFetcher.this);
                                container.activate(SingleFileFetcher.this, 1);
+                       }
                        // Pass it on; fetcher is assumed to have retried as 
appropriate already, so this is fatal.
                        SingleFileFetcher.this.onFailure(e, true, container, 
context);
+                       if(!wasActive)
+                               container.deactivate(SingleFileFetcher.this, 1);
                }

                public void onBlockSetFinished(ClientGetState state, 
ObjectContainer container, ClientContext context) {
@@ -838,11 +884,19 @@
                }

                public void onExpectedSize(long size, ObjectContainer 
container) {
+                       boolean wasActive = true;
+                       boolean cbWasActive = true;
                        if(persistent) {
+                               wasActive = 
container.ext().isActive(SingleFileFetcher.this);
                                container.activate(SingleFileFetcher.this, 1);
+                               cbWasActive = container.ext().isActive(rcb);
                                container.activate(rcb, 1);
                        }
                        rcb.onExpectedSize(size, container);
+                       if(!wasActive)
+                               container.deactivate(SingleFileFetcher.this, 1);
+                       if(!cbWasActive)
+                               container.deactivate(rcb, 1);
                }

                public void onFinalizedMetadata(ObjectContainer container) {
@@ -982,5 +1036,9 @@
                }

        }
-
+       
+       public void objectOnActivate(ObjectContainer container) {
+               Logger.minor(this, "ACTIVATING: "+this, new Exception("debug"));
+       }
+       
 }


Reply via email to