Author: toad
Date: 2008-06-20 15:21:59 +0000 (Fri, 20 Jun 2008)
New Revision: 20526

Modified:
   branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
   branches/db4o/freenet/src/freenet/client/async/BinaryBlobInserter.java
   branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java
   
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerBase.java
   
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java
   branches/db4o/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java
   branches/db4o/freenet/src/freenet/client/async/SingleBlockInserter.java
   branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java
   branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
   
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
   branches/db4o/freenet/src/freenet/client/async/USKChecker.java
   branches/db4o/freenet/src/freenet/node/SendableGet.java
   branches/db4o/freenet/src/freenet/node/SendableRequest.java
   branches/db4o/freenet/src/freenet/node/SimpleSendableInsert.java
   branches/db4o/freenet/src/freenet/support/RandomGrabArray.java
   branches/db4o/freenet/src/freenet/support/RandomGrabArrayWithClient.java
   branches/db4o/freenet/src/freenet/support/RandomGrabArrayWithInt.java
   branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArray.java
   branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArrayWithInt.java
   
branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArrayWithObject.java
Log:
Persist the queue (RGA's).
Use a Db4oMap or Db4oSet (new class) where needed.

Modified: 
branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java   
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java   
2008-06-20 15:21:59 UTC (rev 20526)
@@ -111,7 +111,7 @@
                synchronized(this) {
                        cancelled = true;
                }
-               super.unregister(false);
+               super.unregister(false, container);
        }

        public synchronized boolean isCancelled() {

Modified: branches/db4o/freenet/src/freenet/client/async/BinaryBlobInserter.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/BinaryBlobInserter.java      
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/client/async/BinaryBlobInserter.java      
2008-06-20 15:21:59 UTC (rev 20526)
@@ -80,7 +80,7 @@
        public void cancel(ObjectContainer container, ClientContext context) {
                for(int i=0;i<inserters.length;i++) {
                        if(inserters[i] != null)
-                               inserters[i].cancel();
+                               inserters[i].cancel(container, context);
                }
                parent.onFailure(new 
InsertException(InsertException.CANCELLED), this, container, context);
        }

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-06-20 15:21:59 UTC (rev 20526)
@@ -306,14 +306,14 @@
                                        throw new IllegalStateException("Not on 
database thread!");
                                }
                                if(anyValid)
-                                       schedCore.innerRegister(req, random);
+                                       schedCore.innerRegister(req, random, 
selectorContainer);
                                schedCore.deleteRegisterMe(req);
                                starter.wakeUp();
                        } else {
                                databaseExecutor.execute(new Runnable() {
                                        public void run() {
                                                if(anyValid)
-                                                       
schedCore.innerRegister(req, random);
+                                                       
schedCore.innerRegister(req, random, selectorContainer);
                                                schedCore.deleteRegisterMe(req);
                                                selectorContainer.commit();
                                        }
@@ -321,7 +321,7 @@
                        }
                } else {
                        // Register immediately.
-                       schedTransient.innerRegister(req, random);
+                       schedTransient.innerRegister(req, random, null);
                        starter.wakeUp();
                }
        }
@@ -456,7 +456,7 @@
        }

        public void reregisterAll(final ClientRequester request, 
ObjectContainer container) {
-               schedTransient.reregisterAll(request, random, this);
+               schedTransient.reregisterAll(request, random, this, container);
                starter.wakeUp();
        }


Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerBase.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerBase.java  
    2008-06-20 14:53:36 UTC (rev 20525)
+++ 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerBase.java  
    2008-06-20 15:21:59 UTC (rev 20526)
@@ -233,10 +233,10 @@
                else return 0;
        }

-       void innerRegister(SendableRequest req, RandomSource random) {
+       void innerRegister(SendableRequest req, RandomSource random, 
ObjectContainer container) {
                if(logMINOR) Logger.minor(this, "Still registering "+req+" at 
prio "+req.getPriorityClass()+" retry "+req.getRetryCount()+" for 
"+req.getClientRequest());
                int retryCount = req.getRetryCount();
-               addToGrabArray(req.getPriorityClass(), retryCount, 
fixRetryCount(retryCount), req.getClient(), req.getClientRequest(), req, 
random);
+               addToGrabArray(req.getPriorityClass(), retryCount, 
fixRetryCount(retryCount), req.getClient(), req.getClientRequest(), req, 
random, container);
                HashSet v = (HashSet) 
allRequestsByClientRequest.get(req.getClientRequest());
                if(v == null) {
                        v = new HashSet();
@@ -246,7 +246,7 @@
                if(logMINOR) Logger.minor(this, "Registered "+req+" on 
prioclass="+req.getPriorityClass()+", retrycount="+req.getRetryCount()+" 
v.size()="+v.size());
        }

-       void addToGrabArray(short priorityClass, int retryCount, int rc, Object 
client, ClientRequester cr, SendableRequest req, RandomSource random) {
+       void addToGrabArray(short priorityClass, int retryCount, int rc, Object 
client, ClientRequester cr, SendableRequest req, RandomSource random, 
ObjectContainer container) {
                if((priorityClass > RequestStarter.MINIMUM_PRIORITY_CLASS) || 
(priorityClass < RequestStarter.MAXIMUM_PRIORITY_CLASS))
                        throw new IllegalStateException("Invalid priority: 
"+priorityClass+" - range is "+RequestStarter.MAXIMUM_PRIORITY_CLASS+" (most 
important) to "+RequestStarter.MINIMUM_PRIORITY_CLASS+" (least important)");
                // Priority
@@ -258,7 +258,7 @@
                // Client
                SectoredRandomGrabArrayWithInt clientGrabber = 
(SectoredRandomGrabArrayWithInt) prio.get(rc);
                if(clientGrabber == null) {
-                       clientGrabber = new 
SectoredRandomGrabArrayWithInt(random, rc, persistent());
+                       clientGrabber = new 
SectoredRandomGrabArrayWithInt(random, rc, persistent(), container);
                        prio.add(clientGrabber);
                        if(logMINOR) Logger.minor(this, "Registering retry 
count "+rc+" with prioclass "+priorityClass+" on "+clientGrabber+" for "+prio);
                }
@@ -268,12 +268,12 @@
                        // Request
                        SectoredRandomGrabArrayWithObject requestGrabber = 
(SectoredRandomGrabArrayWithObject) clientGrabber.getGrabber(client);
                        if(requestGrabber == null) {
-                               requestGrabber = new 
SectoredRandomGrabArrayWithObject(client, random, persistent());
+                               requestGrabber = new 
SectoredRandomGrabArrayWithObject(client, random, persistent(), container);
                                if(logMINOR)
                                        Logger.minor(this, "Creating new 
grabber: "+requestGrabber+" for "+client+" from "+clientGrabber+" : "+prio+" : 
prio="+priorityClass+", rc="+rc);
-                               clientGrabber.addGrabber(client, 
requestGrabber);
+                               clientGrabber.addGrabber(client, 
requestGrabber, container);
                        }
-                       requestGrabber.add(cr, req);
+                       requestGrabber.add(cr, req, container);
                }
        }

@@ -289,7 +289,7 @@
                return Math.max(0, retryCount-MIN_RETRY_COUNT);
        }

-       public void reregisterAll(ClientRequester request, RandomSource random, 
ClientRequestScheduler lock) {
+       public void reregisterAll(ClientRequester request, RandomSource random, 
ClientRequestScheduler lock, ObjectContainer container) {
                SendableRequest[] reqs;
                synchronized(lock) {
                        HashSet h = (HashSet) 
allRequestsByClientRequest.get(request);
@@ -300,9 +300,9 @@
                for(int i=0;i<reqs.length;i++) {
                        SendableRequest req = reqs[i];
                        // Unregister from the RGA's, but keep the pendingKeys 
and cooldown queue data.
-                       req.unregister(true);
+                       req.unregister(true, container);
                        // Then can do innerRegister() (not register()).
-                       innerRegister(req, random);
+                       innerRegister(req, random, container);
                }
        }


Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java  
    2008-06-20 14:53:36 UTC (rev 20525)
+++ 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java  
    2008-06-20 15:21:59 UTC (rev 20526)
@@ -307,7 +307,7 @@
                                if(clientGrabber != null) {
                                        RandomGrabArray baseRGA = 
(RandomGrabArray) clientGrabber.getGrabber(req.getClientRequest());
                                        if(baseRGA != null) {
-                                               baseRGA.remove(req);
+                                               baseRGA.remove(req, container);
                                        } else {
                                                Logger.error(this, "Could not 
find base RGA for requestor "+req.getClientRequest()+" from "+clientGrabber);
                                        }
@@ -315,9 +315,9 @@
                                        Logger.error(this, "Could not find 
client grabber for client "+req.getClient()+" from "+chosenTracker);
                                }
                                if(req.persistent())
-                                       innerRegister(req, random);
+                                       innerRegister(req, random, container);
                                else
-                                       schedTransient.innerRegister(req, 
random);
+                                       schedTransient.innerRegister(req, 
random, container);
                                continue; // Try the next one on this retry 
count.
                        }
                        // Check recentSuccesses
@@ -334,9 +334,9 @@
                                if(logMINOR)
                                        Logger.minor(this, "Recently succeeded 
req "+altReq+" is better, using that, reregistering chosen "+req);
                                if(req.persistent())
-                                       innerRegister(req, random);
+                                       innerRegister(req, random, container);
                                else
-                                       schedTransient.innerRegister(req, 
random);
+                                       schedTransient.innerRegister(req, 
random, container);
                                req = altReq;
                        } else {
                                // Don't use the recent one

Modified: 
branches/db4o/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java 
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java 
2008-06-20 15:21:59 UTC (rev 20526)
@@ -98,7 +98,7 @@
                        }
                }
                // :(
-               unregister(false);
+               unregister(false, container);
                if(e.isFatal() || forceFatal)
                        parent.fatallyFailedBlock(container, context);
                else
@@ -108,7 +108,7 @@

        /** Will be overridden by SingleFileFetcher */
        protected void onSuccess(FetchResult data, RequestScheduler sched, 
ObjectContainer container, ClientContext context) {
-               unregister(false);
+               unregister(false, container);
                if(parent.isCancelled()) {
                        data.asBucket().free();
                        onFailure(new FetchException(FetchException.CANCELLED), 
false, sched, container, context);

Modified: 
branches/db4o/freenet/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SingleBlockInserter.java     
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/client/async/SingleBlockInserter.java     
2008-06-20 15:21:59 UTC (rev 20526)
@@ -300,7 +300,7 @@
                }
                if(parent.persistent())
                        container.set(this);
-               super.unregister(false);
+               super.unregister(false, container);
                cb.onFailure(new InsertException(InsertException.CANCELLED), 
this, container, context);
        }


Modified: branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java       
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/client/async/SingleFileFetcher.java       
2008-06-20 15:21:59 UTC (rev 20526)
@@ -175,7 +175,7 @@

        protected void onSuccess(FetchResult result, RequestScheduler sched, 
ObjectContainer container, ClientContext context) {
                this.sched = sched;
-               unregister(false);
+               unregister(false, container);
                if(parent.isCancelled()) {
                        if(logMINOR)
                                Logger.minor(this, "Parent is cancelled");

Modified: 
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 
2008-06-20 15:21:59 UTC (rev 20526)
@@ -198,9 +198,9 @@
                        dontNotify = !scheduled;
                }
                parentFetcher.parent.completedBlock(dontNotify, container, 
sched.getContext());
-               seg.possiblyRemoveFromParent();
+               seg.possiblyRemoveFromParent(container);
                if(decodeNow) {
-                       removeSubSegments();
+                       removeSubSegments(container);
                        decode(container, sched.getContext(), sched);
                }
        }
@@ -382,7 +382,7 @@
                if(allFailed)
                        fail(new FetchException(FetchException.SPLITFILE_ERROR, 
errors), container, context);
                else
-                       seg.possiblyRemoveFromParent();
+                       seg.possiblyRemoveFromParent(container);
        }

        /** A request has failed non-fatally, so the block may be retried 
@@ -489,7 +489,7 @@
                                checkBuckets[i] = null;
                        }
                }
-               removeSubSegments();
+               removeSubSegments(container);
                parentFetcher.segmentFinished(this, container, context);
        }

@@ -573,14 +573,14 @@
                return true;
        }

-       private void removeSubSegments() {
+       private void removeSubSegments(ObjectContainer container) {
                SplitFileFetcherSubSegment[] deadSegs;
                synchronized(this) {
                        deadSegs = (SplitFileFetcherSubSegment[]) 
subSegments.toArray(new SplitFileFetcherSubSegment[subSegments.size()]);
                        subSegments.clear();
                }
                for(int i=0;i<deadSegs.length;i++) {
-                       deadSegs[i].kill();
+                       deadSegs[i].kill(container);
                }
        }


Modified: 
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java  
    2008-06-20 14:53:36 UTC (rev 20525)
+++ 
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java  
    2008-06-20 15:21:59 UTC (rev 20526)
@@ -370,7 +370,7 @@
                return 
super.toString()+":"+retryCount+"/"+segment+'('+blockNums.size()+')'; 
        }

-       public void possiblyRemoveFromParent() {
+       public void possiblyRemoveFromParent(ObjectContainer container) {
                if(logMINOR)
                        Logger.minor(this, "Possibly removing from parent: 
"+this);
                synchronized(segment) {
@@ -380,7 +380,7 @@
                        if(!segment.maybeRemoveSeg(this)) return;
                        cancelled = true;
                }
-               unregister(false);
+               unregister(false, container);
        }

        public void onGotKey(Key key, KeyBlock block, RequestScheduler sched, 
ObjectContainer container, ClientContext context) {
@@ -427,11 +427,11 @@
         * Terminate a subsegment. Called by the segment, which will have 
already removed the
         * subsegment from the list.
         */
-       public void kill() {
+       public void kill(ObjectContainer container) {
                if(logMINOR)
                        Logger.minor(this, "Killing "+this);
                // Do unregister() first so can get and unregister each key and 
avoid a memory leak
-               unregister(false);
+               unregister(false, container);
                synchronized(segment) {
                        blockNums.clear();
                        cancelled = true;

Modified: branches/db4o/freenet/src/freenet/client/async/USKChecker.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/USKChecker.java      
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/client/async/USKChecker.java      
2008-06-20 15:21:59 UTC (rev 20526)
@@ -29,7 +29,7 @@
        }

        public void onSuccess(ClientKeyBlock block, boolean fromStore, Object 
token, RequestScheduler sched, ObjectContainer container, ClientContext 
context) {
-               unregister(false);
+               unregister(false, container);
                cb.onSuccess((ClientSSKBlock)block, context);
        }

@@ -66,7 +66,7 @@
                if(canRetry && retry(sched, container, context)) return;

                // Ran out of retries.
-               unregister(false);
+               unregister(false, container);
                if(e.code == LowLevelGetException.CANCELLED){
                        cb.onCancelled(context);
                        return;

Modified: branches/db4o/freenet/src/freenet/node/SendableGet.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/SendableGet.java     2008-06-20 
14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/node/SendableGet.java     2008-06-20 
15:21:59 UTC (rev 20526)
@@ -133,10 +133,10 @@
        /** Reset the cooldown times when the request is reregistered. */
        public abstract void resetCooldownTimes(ObjectContainer container);

-       public final void unregister(boolean staySubscribed, ClientContext 
context) {
+       public final void unregister(boolean staySubscribed, ObjectContainer 
container, ClientContext context) {
                if(!staySubscribed)
                        getScheduler(context).removePendingKeys(this, false);
-               super.unregister(staySubscribed);
+               super.unregister(staySubscribed, container);
        }

        public final void unregisterKey(Key key, ClientContext context) {

Modified: branches/db4o/freenet/src/freenet/node/SendableRequest.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/SendableRequest.java 2008-06-20 
14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/node/SendableRequest.java 2008-06-20 
15:21:59 UTC (rev 20526)
@@ -5,7 +5,6 @@
 import freenet.client.async.ChosenRequest;
 import freenet.client.async.ClientContext;
 import freenet.client.async.ClientRequester;
-import freenet.keys.ClientKey;
 import freenet.support.Logger;
 import freenet.support.RandomGrabArray;
 import freenet.support.RandomGrabArrayItem;
@@ -81,10 +80,10 @@
                parentGrabArray = parent;
        }

-       public void unregister(boolean staySubscribed) {
+       public void unregister(boolean staySubscribed, ObjectContainer 
container) {
                RandomGrabArray arr = getParentGrabArray();
                if(arr != null) {
-                       arr.remove(this);
+                       arr.remove(this, container);
                } else {
                        // Should this be a higher priority?
                        if(Logger.shouldLog(Logger.MINOR, this))

Modified: branches/db4o/freenet/src/freenet/node/SimpleSendableInsert.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/SimpleSendableInsert.java    
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/node/SimpleSendableInsert.java    
2008-06-20 15:21:59 UTC (rev 20526)
@@ -111,12 +111,12 @@
                scheduler.register(this);
        }

-       public void cancel() {
+       public void cancel(ObjectContainer container, ClientContext context) {
                synchronized(this) {
                        if(finished) return;
                        finished = true;
                }
-               super.unregister(false);
+               super.unregister(false, container);
        }

        public boolean shouldCache() {

Modified: branches/db4o/freenet/src/freenet/support/RandomGrabArray.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/RandomGrabArray.java      
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/support/RandomGrabArray.java      
2008-06-20 15:21:59 UTC (rev 20526)
@@ -1,6 +1,7 @@
 package freenet.support;

 import java.util.HashSet;
+import java.util.Set;

 import com.db4o.ObjectContainer;

@@ -22,19 +23,22 @@
         * RAM), or rewrite the whole class as a custom hashset maybe based on 
the classpath 
         * HashSet. Note that removeRandom() is *the* common operation, so MUST 
BE FAST.
         */
-       private HashSet contents;
+       private Set contents;
        private final static int MIN_SIZE = 32;
        private final boolean persistent;

-       public RandomGrabArray(RandomSource rand, boolean persistent) {
+       public RandomGrabArray(RandomSource rand, boolean persistent, 
ObjectContainer container) {
                this.reqs = new RandomGrabArrayItem[MIN_SIZE];
                this.persistent = persistent;
                index = 0;
                this.rand = rand;
-               contents = new HashSet();
+               if(persistent)
+                       contents = new Db4oSet(container, 10);
+               else
+                       contents = new HashSet();
        }

-       public void add(RandomGrabArrayItem req) {
+       public void add(RandomGrabArrayItem req, ObjectContainer container) {
                if(req.persistent() != persistent) throw new 
IllegalArgumentException("req.persistent()="+req.persistent()+" but 
array.persistent="+persistent+" item="+req+" array="+this);
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
                if(req.isEmpty()) {
@@ -55,6 +59,7 @@
                        }
                        reqs[index++] = req;
                        if(logMINOR) Logger.minor(this, "Added: "+req+" to 
"+this+" size now "+index);
+                       if(persistent) container.set(this);
                }
        }

@@ -64,6 +69,7 @@
                synchronized(this) {
                        final int MAX_EXCLUDED = 10;
                        int excluded = 0;
+                       boolean changedMe = false;
                        while(true) {
                                if(index == 0) {
                                        if(logMINOR) Logger.minor(this, "All 
null on "+this);
@@ -83,11 +89,13 @@
                                                        if(item == null) {
                                                                continue;
                                                        } else 
if(item.isEmpty()) {
+                                                               changedMe = 
true;
                                                                reqs[i] = null;
                                                                
contents.remove(item);
                                                                continue;
                                                        }
                                                        if(i != target) {
+                                                               changedMe = 
true;
                                                                reqs[i] = null;
                                                                reqs[target] = 
item;
                                                        }
@@ -102,10 +110,12 @@
                                                                valid++;
                                                        }
                                                }
+                                               changedMe = true;
                                                index = target;
                                                // We reach this point if 1) 
the random number we picked last round is invalid because an item became 
cancelled or excluded
                                                // or 2) we are on the first 
round anyway.
                                                if(chosenIndex >= 0) {
+                                                       changedMe = true;
                                                        ret = reqs[chosenIndex];
                                                        if(ret.canRemove()) {
                                                                
contents.remove(ret);
@@ -116,18 +126,24 @@
                                                                
ret.setParentGrabArray(null);
                                                        }
                                                        if(logMINOR) 
Logger.minor(this, "Chosen random item "+ret+" out of "+valid);
+                                                       if(persistent && 
changedMe)
+                                                               
container.set(this);
                                                        return ret;
                                                }
                                                if(valid == 0 && exclude == 0) {
                                                        index = 0;
+                                                       container.set(this);
                                                        if(logMINOR) 
Logger.minor(this, "No valid or excluded items");
                                                        return null;
                                                } else if(valid == 0) {
+                                                       if(persistent && 
changedMe)
+                                                               
container.set(this);
                                                        if(logMINOR) 
Logger.minor(this, "No valid items, "+exclude+" excluded items");
                                                        return null;
                                                } else if(valid == 1) {
                                                        ret = reqs[validIndex];
                                                        if(ret.canRemove()) {
+                                                               changedMe = 
true;
                                                                
contents.remove(ret);
                                                                if(validIndex 
!= index-1) {
                                                                        
reqs[validIndex] = reqs[index-1];
@@ -138,6 +154,8 @@
                                                        } else {
                                                                if(logMINOR) 
Logger.minor(this, "No valid or excluded items apart from "+ret);
                                                        }
+                                                       if(persistent && 
changedMe)
+                                                               
container.set(this);
                                                        return ret;
                                                } else {
                                                        random = 
rand.nextInt(valid);
@@ -153,6 +171,7 @@
                                                reqs[i] = reqs[index];
                                                reqs[index] = null;
                                        }
+                                       changedMe = true;
                                        continue;
                                }
                                oret = ret;
@@ -164,15 +183,20 @@
                                        excluded++;
                                        if(excluded > MAX_EXCLUDED) {
                                                Logger.error(this, "Remove 
random returning null because "+excluded+" excluded items, length = "+index, 
new Exception("error"));
+                                               if(persistent && changedMe)
+                                                       container.set(this);
                                                return null;
                                        }
                                        continue;
                                }
                                if(ret != null && !ret.canRemove()) {
                                        if(logMINOR) Logger.minor(this, 
"Returning (cannot remove): "+ret+" of "+index);
+                                       if(persistent && changedMe)
+                                               container.set(this);
                                        return ret;
                                }
                                do {
+                                       changedMe = true;
                                        reqs[i] = reqs[--index];
                                        reqs[index] = null;
                                        if(oret != null)
@@ -182,6 +206,7 @@
                                } while (index > i && (oret == null || 
oret.isEmpty()));
                                // Shrink array
                                if((index < reqs.length / 4) && (reqs.length > 
MIN_SIZE)) {
+                                       changedMe = true;
                                        // Shrink array
                                        int newSize = Math.max(index * 2, 
MIN_SIZE);
                                        RandomGrabArrayItem[] r = new 
RandomGrabArrayItem[newSize];
@@ -193,10 +218,12 @@
                }
                if(logMINOR) Logger.minor(this, "Returning "+ret+" of "+index);
                ret.setParentGrabArray(null);
+               if(persistent)
+                       container.set(this);
                return ret;
        }

-       public void remove(RandomGrabArrayItem it) {
+       public void remove(RandomGrabArrayItem it, ObjectContainer container) {
                synchronized(this) {
                        if(!contents.contains(it)) return;
                        contents.remove(it);
@@ -210,6 +237,8 @@
                        }
                }
                it.setParentGrabArray(null);
+               if(persistent)
+                       container.set(this);
        }

        public synchronized boolean isEmpty() {

Modified: 
branches/db4o/freenet/src/freenet/support/RandomGrabArrayWithClient.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/RandomGrabArrayWithClient.java    
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/support/RandomGrabArrayWithClient.java    
2008-06-20 15:21:59 UTC (rev 20526)
@@ -1,13 +1,15 @@
 package freenet.support;

+import com.db4o.ObjectContainer;
+
 import freenet.crypt.RandomSource;

 public class RandomGrabArrayWithClient extends RandomGrabArray implements 
RemoveRandomWithObject {

        final Object client;

-       public RandomGrabArrayWithClient(Object client, RandomSource rand, 
boolean persistent) {
-               super(rand, persistent);
+       public RandomGrabArrayWithClient(Object client, RandomSource rand, 
boolean persistent, ObjectContainer container) {
+               super(rand, persistent, container);
                this.client = client;
        }


Modified: branches/db4o/freenet/src/freenet/support/RandomGrabArrayWithInt.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/RandomGrabArrayWithInt.java       
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/support/RandomGrabArrayWithInt.java       
2008-06-20 15:21:59 UTC (rev 20526)
@@ -1,13 +1,15 @@
 package freenet.support;

+import com.db4o.ObjectContainer;
+
 import freenet.crypt.RandomSource;

 public class RandomGrabArrayWithInt extends RandomGrabArray implements 
IntNumberedItem {

        private final int number;

-       public RandomGrabArrayWithInt(RandomSource rand, int no, boolean 
persistent) {
-               super(rand, persistent);
+       public RandomGrabArrayWithInt(RandomSource rand, int no, boolean 
persistent, ObjectContainer container) {
+               super(rand, persistent, container);
                number = no;
        }


Modified: branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArray.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArray.java      
2008-06-20 14:53:36 UTC (rev 20525)
+++ branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArray.java      
2008-06-20 15:21:59 UTC (rev 20526)
@@ -1,6 +1,7 @@
 package freenet.support;

 import java.util.HashMap;
+import java.util.Map;

 import com.db4o.ObjectContainer;

@@ -13,39 +14,46 @@
  */
 public class SectoredRandomGrabArray implements RemoveRandom {

-       private final HashMap grabArraysByClient;
+       private final Map grabArraysByClient;
        private RemoveRandomWithObject[] grabArrays;
        private final RandomSource rand;
        private final boolean persistent;

-       public SectoredRandomGrabArray(RandomSource rand, boolean persistent) {
+       public SectoredRandomGrabArray(RandomSource rand, boolean persistent, 
ObjectContainer container) {
                this.rand = rand;
                this.persistent = persistent;
-               this.grabArraysByClient = new HashMap();
+               if(persistent)
+                       // FIXME is this too heavyweight? Maybe we should 
iterate the array or something?
+                       grabArraysByClient = 
container.ext().collections().newHashMap(10);
+               else
+                       grabArraysByClient = new HashMap();
                grabArrays = new RemoveRandomWithObject[0];
        }

        /**
         * Add directly to a RandomGrabArrayWithClient under us. */
-       public synchronized void add(Object client, RandomGrabArrayItem item) {
+       public synchronized void add(Object client, RandomGrabArrayItem item, 
ObjectContainer container) {
                if(item.persistent() != persistent) throw new 
IllegalArgumentException("item.persistent()="+item.persistent()+" but 
array.persistent="+persistent+" item="+item+" array="+this);
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
                RandomGrabArrayWithClient rga;
                if(!grabArraysByClient.containsKey(client)) {
                        if(logMINOR)
                                Logger.minor(this, "Adding new RGAWithClient 
for "+client+" on "+this+" for "+item);
-                       rga = new RandomGrabArrayWithClient(client, rand, 
persistent);
+                       rga = new RandomGrabArrayWithClient(client, rand, 
persistent, container);
                        RemoveRandomWithObject[] newArrays = new 
RemoveRandomWithObject[grabArrays.length+1];
                        System.arraycopy(grabArrays, 0, newArrays, 0, 
grabArrays.length);
                        newArrays[grabArrays.length] = rga;
                        grabArrays = newArrays;
                        grabArraysByClient.put(client, rga);
+                       if(persistent) {
+                               container.set(this);
+                       }
                } else {
                        rga = (RandomGrabArrayWithClient) 
grabArraysByClient.get(client);
                }
                if(logMINOR)
                        Logger.minor(this, "Adding "+item+" to RGA "+rga+" for 
"+client);
-               rga.add(item);
+               rga.add(item, container);
                if(logMINOR)
                        Logger.minor(this, "Size now "+grabArrays.length+" on 
"+this);
        }
@@ -62,12 +70,15 @@
         * Put a grabber. This lets us use things other than 
RandomGrabArrayWithClient's, so don't mix calls
         * to add() with calls to getGrabber/addGrabber!
         */
-       public synchronized void addGrabber(Object client, 
RemoveRandomWithObject requestGrabber) {
+       public synchronized void addGrabber(Object client, 
RemoveRandomWithObject requestGrabber, ObjectContainer container) {
                grabArraysByClient.put(client, requestGrabber);
                RemoveRandomWithObject[] newArrays = new 
RemoveRandomWithObject[grabArrays.length+1];
                System.arraycopy(grabArrays, 0, newArrays, 0, 
grabArrays.length);
                newArrays[grabArrays.length] = requestGrabber;
                grabArrays = newArrays;
+               if(persistent) {
+                       container.set(this);
+               }
        }

        public synchronized RandomGrabArrayItem 
removeRandom(RandomGrabArrayItemExclusionList excluding, ObjectContainer 
container, ClientContext context) {
@@ -87,6 +98,8 @@
                                        Object client = rga.getObject();
                                        grabArraysByClient.remove(client);
                                        grabArrays = new 
RemoveRandomWithObject[0];
+                                       if(persistent)
+                                               container.set(this);
                                }
                                if(logMINOR)
                                        Logger.minor(this, "Returning (one item 
only) "+item+" for "+rga+" for "+rga.getObject());
@@ -106,9 +119,13 @@
                                                
grabArraysByClient.remove(rga.getObject());
                                                
grabArraysByClient.remove(firstRGA.getObject());
                                                grabArrays = new 
RemoveRandomWithObject[0];
+                                               if(persistent)
+                                                       container.set(this);
                                        } else if(firstRGA.isEmpty()) {
                                                
grabArraysByClient.remove(firstRGA.getObject());
                                                grabArrays = new 
RemoveRandomWithObject[] { rga };
+                                               if(persistent)
+                                                       container.set(this);
                                        }
                                        if(logMINOR)
                                                Logger.minor(this, "Returning 
(two items only) "+item+" for "+rga+" for "+rga.getObject());
@@ -142,6 +159,8 @@
                                if(x < grabArraysLength-1)
                                        System.arraycopy(grabArrays, x+1, 
newArray, x, grabArraysLength - (x+1));
                                grabArrays = newArray;
+                               if(persistent)
+                                       container.set(this);
                        }
                        if(item == null) {
                                if(!rga.isEmpty()) {

Modified: 
branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArrayWithInt.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArrayWithInt.java   
    2008-06-20 14:53:36 UTC (rev 20525)
+++ 
branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArrayWithInt.java   
    2008-06-20 15:21:59 UTC (rev 20526)
@@ -1,13 +1,15 @@
 package freenet.support;

+import com.db4o.ObjectContainer;
+
 import freenet.crypt.RandomSource;

 public class SectoredRandomGrabArrayWithInt extends SectoredRandomGrabArray 
implements IntNumberedItem {

        private final int number;

-       public SectoredRandomGrabArrayWithInt(RandomSource rand, int number, 
boolean persistent) {
-               super(rand, persistent);
+       public SectoredRandomGrabArrayWithInt(RandomSource rand, int number, 
boolean persistent, ObjectContainer container) {
+               super(rand, persistent, container);
                this.number = number;
        }


Modified: 
branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArrayWithObject.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArrayWithObject.java
    2008-06-20 14:53:36 UTC (rev 20525)
+++ 
branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArrayWithObject.java
    2008-06-20 15:21:59 UTC (rev 20526)
@@ -1,13 +1,15 @@
 package freenet.support;

+import com.db4o.ObjectContainer;
+
 import freenet.crypt.RandomSource;

 public class SectoredRandomGrabArrayWithObject extends SectoredRandomGrabArray 
implements RemoveRandomWithObject {

        private final Object object;

-       public SectoredRandomGrabArrayWithObject(Object object, RandomSource 
rand, boolean persistent) {
-               super(rand, persistent);
+       public SectoredRandomGrabArrayWithObject(Object object, RandomSource 
rand, boolean persistent, ObjectContainer container) {
+               super(rand, persistent, container);
                this.object = object;
        }



Reply via email to