Author: toad
Date: 2008-05-21 13:04:29 +0000 (Wed, 21 May 2008)
New Revision: 20011

Modified:
   
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/ClientRequestSchedulerNonPersistent.java
   branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArray.java
   branches/db4o/freenet/src/freenet/support/SortedVectorByNumber.java
Log:
Use the alternate queue structures to support non-persistent requests.

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerBase.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerBase.java  
    2008-05-21 12:28:00 UTC (rev 20010)
+++ 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerBase.java  
    2008-05-21 13:04:29 UTC (rev 20011)
@@ -43,6 +43,7 @@
         * an overlapping request, or it is fetched by a request from another 
node. Operations on this are synchronized on
         * itself. */
        protected final Map /* <Key, SendableGet[]> */ pendingKeys;
+       
        /**
         * Structure:
         * array (by priority) -> // one element per possible priority
@@ -304,4 +305,18 @@
                }
        }

+       protected void removeFromAllRequestsByClientRequest(SendableRequest 
req, ClientRequester cr) {
+               synchronized(this) {
+                       HashSet v = (HashSet) 
allRequestsByClientRequest.get(cr);
+                       if(v == null) {
+                               Logger.error(this, "No HashSet registered for 
"+cr);
+                       } else {
+                               boolean removed = v.remove(req);
+                               if(v.isEmpty())
+                                       allRequestsByClientRequest.remove(cr);
+                               if(logMINOR) Logger.minor(this, (removed ? "" : 
"Not ") + "Removed from HashSet for "+cr+" which now has "+v.size()+" 
elements");
+                       }
+               }
+       }
+
 }

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java  
    2008-05-21 12:28:00 UTC (rev 20010)
+++ 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java  
    2008-05-21 13:04:29 UTC (rev 20011)
@@ -4,6 +4,7 @@
 package freenet.client.async;

 import java.util.HashSet;
+import java.util.List;

 import com.db4o.ObjectContainer;
 import com.db4o.ObjectSet;
@@ -77,7 +78,9 @@
                ((Db4oList)recentSuccesses).activationDepth(1);
        }

-       private int removeFirstAccordingToPriorities(boolean tryOfferedKeys, 
int fuzz, RandomSource random, OfferedKeysList[] offeredKeys){
+       // We pass in the schedTransient to the next two methods so that we can 
select between either of them.
+       
+       private int removeFirstAccordingToPriorities(boolean tryOfferedKeys, 
int fuzz, RandomSource random, OfferedKeysList[] offeredKeys, 
ClientRequestSchedulerNonPersistent schedTransient){
                SortedVectorByNumber result = null;

                short iteration = 0, priority;
@@ -88,6 +91,8 @@
                while(iteration++ < RequestStarter.NUMBER_OF_PRIORITY_CLASSES + 
1){
                        priority = fuzz<0 ? 
tweakedPrioritySelector[random.nextInt(tweakedPrioritySelector.length)] : 
prioritySelector[Math.abs(fuzz % prioritySelector.length)];
                        result = priorities[priority];
+                       if(result == null)
+                               result = schedTransient.priorities[priority];
                        if((result != null) && 
                                        (!result.isEmpty()) || (tryOfferedKeys 
&& !offeredKeys[priority].isEmpty())) {
                                if(logMINOR) Logger.minor(this, "using priority 
: "+priority);
@@ -110,10 +115,10 @@
                // Priorities start at 0
                if(logMINOR) Logger.minor(this, "removeFirst()");
                boolean tryOfferedKeys = offeredKeys != null && 
random.nextBoolean();
-               int choosenPriorityClass = 
removeFirstAccordingToPriorities(tryOfferedKeys, fuzz, random, offeredKeys);
+               int choosenPriorityClass = 
removeFirstAccordingToPriorities(tryOfferedKeys, fuzz, random, offeredKeys, 
schedTransient);
                if(choosenPriorityClass == -1 && offeredKeys != null && 
!tryOfferedKeys) {
                        tryOfferedKeys = true;
-                       choosenPriorityClass = 
removeFirstAccordingToPriorities(tryOfferedKeys, fuzz, random, offeredKeys);
+                       choosenPriorityClass = 
removeFirstAccordingToPriorities(tryOfferedKeys, fuzz, random, offeredKeys, 
schedTransient);
                }
                if(choosenPriorityClass == -1) {
                        if(logMINOR)
@@ -126,97 +131,119 @@
                        
if(offeredKeys[choosenPriorityClass].hasValidKeys(starter))
                                return offeredKeys[choosenPriorityClass];
                }
-               SortedVectorByNumber s = priorities[choosenPriorityClass];
-               if(s != null){
-                       for(int retryIndex=0;retryIndex<s.count();retryIndex++) 
{
-                               SectoredRandomGrabArrayWithInt retryTracker = 
(SectoredRandomGrabArrayWithInt) s.getByIndex(retryIndex);
-                               if(retryTracker == null) {
-                                       if(logMINOR) Logger.minor(this, "No 
retrycount's left");
-                                       break;
+               SortedVectorByNumber perm = priorities[choosenPriorityClass];
+               SortedVectorByNumber trans = 
schedTransient.priorities[choosenPriorityClass];
+               if(perm == null && trans == null) {
+                       if(logMINOR) Logger.minor(this, "No requests to run: 
chosen priority empty");
+                       return null;
+               }
+               int permRetryIndex = 0;
+               int transRetryIndex = 0;
+               while(true) {
+                       int permRetryCount = perm == null ? -1 : 
perm.getNumberByIndex(permRetryIndex);
+                       int transRetryCount = trans == null ? -1 : 
trans.getNumberByIndex(transRetryIndex);
+                       if(permRetryCount == -1 && transRetryCount == -1) {
+                               if(logMINOR) Logger.minor(this, "No requests to 
run: ran out of retrycounts on chosen priority");
+                               return null;
+                       }
+                       SectoredRandomGrabArrayWithInt chosenTracker = null;
+                       SortedVectorByNumber trackerParent = null;
+                       if(permRetryCount == transRetryCount) {
+                               // Choose between them.
+                               SectoredRandomGrabArrayWithInt permRetryTracker 
= (SectoredRandomGrabArrayWithInt) perm.getByIndex(permRetryIndex);
+                               SectoredRandomGrabArrayWithInt 
transRetryTracker = (SectoredRandomGrabArrayWithInt) 
trans.getByIndex(transRetryIndex);
+                               int permTrackerSize = permRetryTracker.size();
+                               int transTrackerSize = transRetryTracker.size();
+                               if(permTrackerSize + transTrackerSize == 0) {
+                                       permRetryCount++;
+                                       transRetryCount++;
+                                       continue;
                                }
-                               while(true) {
-                                       if(logMINOR)
-                                               Logger.minor(this, "Got retry 
count tracker "+retryTracker);
-                                       SendableRequest req = (SendableRequest) 
retryTracker.removeRandom(starter);
-                                       if(retryTracker.isEmpty()) {
-                                               if(logMINOR) Logger.minor(this, 
"Removing retrycount "+retryTracker.getNumber()+" : "+retryTracker);
-                                               
s.remove(retryTracker.getNumber());
-                                               if(s.isEmpty()) {
-                                                       if(logMINOR) 
Logger.minor(this, "Should remove priority ");
-                                               }
+                               if(random.nextInt(permTrackerSize + 
transTrackerSize) > permTrackerSize) {
+                                       chosenTracker = permRetryTracker;
+                                       trackerParent = perm;
+                               } else {
+                                       chosenTracker = transRetryTracker;
+                                       trackerParent = trans;
+                               }
+                       } else if(permRetryCount < transRetryCount) {
+                               chosenTracker = 
(SectoredRandomGrabArrayWithInt) perm.getByIndex(permRetryIndex);
+                               trackerParent = perm;
+                       } else {
+                               chosenTracker = 
(SectoredRandomGrabArrayWithInt) trans.getByIndex(transRetryIndex);
+                               trackerParent = trans;
+                       }
+                       if(logMINOR)
+                               Logger.minor(this, "Got retry count tracker 
"+chosenTracker);
+                       SendableRequest req = (SendableRequest) 
chosenTracker.removeRandom(starter);
+                       if(chosenTracker.isEmpty()) {
+                               trackerParent.remove(chosenTracker.getNumber());
+                               if(trackerParent.isEmpty()) {
+                                       if(logMINOR) Logger.minor(this, "Should 
remove priority");
+                               }
+                       }
+                       if(req == null) {
+                               if(logMINOR) Logger.minor(this, "No requests, 
adjusted retrycount "+chosenTracker.getNumber()+" ("+chosenTracker+") of 
priority "+choosenPriorityClass);
+                               continue; // Try next retry count.
+                       } else if(req.getPriorityClass() != 
choosenPriorityClass) {
+                               // Reinsert it : shouldn't happen if we are 
calling reregisterAll,
+                               // maybe we should ask people to report that 
error if seen
+                               Logger.normal(this, "In wrong priority class: 
"+req+" (req.prio="+req.getPriorityClass()+" but chosen="+choosenPriorityClass+ 
')');
+                               // Remove it.
+                               SectoredRandomGrabArrayWithObject clientGrabber 
= (SectoredRandomGrabArrayWithObject) chosenTracker.getGrabber(req.getClient());
+                               if(clientGrabber != null) {
+                                       RandomGrabArray baseRGA = 
(RandomGrabArray) clientGrabber.getGrabber(req.getClientRequest());
+                                       if(baseRGA != null) {
+                                               baseRGA.remove(req);
+                                       } else {
+                                               Logger.error(this, "Could not 
find base RGA for requestor "+req.getClientRequest()+" from "+clientGrabber);
                                        }
-                                       if(req == null) {
-                                               if(logMINOR) Logger.minor(this, 
"No requests, adjusted retrycount "+retryTracker.getNumber()+" ("+retryTracker+ 
')');
-                                               break; // Try next retry count.
-                                       } else if(req.getPriorityClass() != 
choosenPriorityClass) {
-                                               // Reinsert it : shouldn't 
happen if we are calling reregisterAll,
-                                               // maybe we should ask people 
to report that error if seen
-                                               Logger.normal(this, "In wrong 
priority class: "+req+" (req.prio="+req.getPriorityClass()+" but 
chosen="+choosenPriorityClass+ ')');
-                                               // Remove it.
-                                               
SectoredRandomGrabArrayWithObject clientGrabber = 
(SectoredRandomGrabArrayWithObject) retryTracker.getGrabber(req.getClient());
-                                               if(clientGrabber != null) {
-                                                       RandomGrabArray baseRGA 
= (RandomGrabArray) clientGrabber.getGrabber(req.getClientRequest());
-                                                       if(baseRGA != null) {
-                                                               
baseRGA.remove(req);
-                                                       } else {
-                                                               
Logger.error(this, "Could not find base RGA for requestor 
"+req.getClientRequest()+" from "+clientGrabber);
-                                                       }
-                                               } else {
-                                                       Logger.error(this, 
"Could not find client grabber for client "+req.getClient()+" from 
"+retryTracker);
-                                               }
-                                               innerRegister(req, random);
-                                               continue; // Try the next one 
on this retry count.
-                                       }
-                                       
-                                       SendableRequest altReq = null;
-                                       synchronized(this) {
-                                               if(!recentSuccesses.isEmpty()) {
-                                                       
if(random.nextBoolean()) {
-                                                               altReq = 
(BaseSendableGet) recentSuccesses.remove(recentSuccesses.size()-1);
-                                                       }
-                                               }
-                                       }
-                                               if(altReq != null && 
altReq.getPriorityClass() <= choosenPriorityClass && 
-                                                               
fixRetryCount(altReq.getRetryCount()) <= retryTracker.getNumber()) {
-                                                       // Use the recent one 
instead
-                                                       if(logMINOR)
-                                                               
Logger.minor(this, "Recently succeeded req "+altReq+" is better, using that, 
reregistering chosen "+req);
-                                                       innerRegister(req, 
random);
-                                                       req = altReq;
-                                               } else {
-                                                       if(altReq != null) {
-                                                               
synchronized(this) {
-                                                                       
recentSuccesses.add(altReq);
-                                                               }
-                                                               if(logMINOR)
-                                                                       
Logger.minor(this, "Chosen req "+req+" is better, reregistering recently 
succeeded "+altReq);
-                                                               
innerRegister(altReq, random);
-                                                       }
-                                               }
-                                       
-                                       if(logMINOR) Logger.debug(this, 
"removeFirst() returning "+req+" ("+retryTracker.getNumber()+", prio "+
-                                                       
req.getPriorityClass()+", retries "+req.getRetryCount()+", client 
"+req.getClient()+", client-req "+req.getClientRequest()+ ')');
-                                       ClientRequester cr = 
req.getClientRequest();
-                                       if(req.canRemove()) {
-                                               synchronized(this) {
-                                                       HashSet v = (HashSet) 
allRequestsByClientRequest.get(cr);
-                                                       if(v == null) {
-                                                               
Logger.error(this, "No HashSet registered for "+cr);
-                                                       } else {
-                                                               boolean removed 
= v.remove(req);
-                                                               if(v.isEmpty())
-                                                                       
allRequestsByClientRequest.remove(cr);
-                                                               if(logMINOR) 
Logger.minor(this, (removed ? "" : "Not ") + "Removed from HashSet for "+cr+" 
which now has "+v.size()+" elements");
-                                                       }
-                                               }
-                                               // Do not remove from the 
pendingKeys list.
-                                               // Whether it is running a 
request, waiting to execute, or waiting on the
-                                               // cooldown queue, ULPRs and 
backdoor coalescing should still be active.
-                                       }
-                                       if(logMINOR) Logger.minor(this, 
"removeFirst() returning "+req+" of "+req.getClientRequest());
-                                       return req;
+                               } else {
+                                       Logger.error(this, "Could not find 
client grabber for client "+req.getClient()+" from "+chosenTracker);
                                }
+                               innerRegister(req, random);
+                               continue; // Try the next one on this retry 
count.
                        }
+                       // Check recentSuccesses
+                       List recent = req.persistent() ? recentSuccesses : 
schedTransient.recentSuccesses;
+                       SendableRequest altReq = null;
+                       if(recent.isEmpty()) {
+                               if(random.nextBoolean()) {
+                                       altReq = (BaseSendableGet) 
recentSuccesses.remove(recentSuccesses.size()-1);
+                               }
+                       }
+                       if(altReq != null && altReq.getPriorityClass() <= 
choosenPriorityClass && 
+                                       fixRetryCount(altReq.getRetryCount()) 
<= chosenTracker.getNumber()) {
+                               // Use the recent one instead
+                               if(logMINOR)
+                                       Logger.minor(this, "Recently succeeded 
req "+altReq+" is better, using that, reregistering chosen "+req);
+                               if(req.persistent())
+                                       innerRegister(req, random);
+                               else
+                                       schedTransient.innerRegister(req, 
random);
+                               req = altReq;
+                       } else {
+                               // Don't use the recent one
+                               if(logMINOR)
+                                       Logger.minor(this, "Chosen req "+req+" 
is better, reregistering recently succeeded "+altReq);
+                               recent.add(altReq);
+                       }
+                       // Now we have chosen a request.
+                       if(logMINOR) Logger.debug(this, "removeFirst() 
returning "+req+" ("+chosenTracker.getNumber()+", prio "+
+                                       req.getPriorityClass()+", retries 
"+req.getRetryCount()+", client "+req.getClient()+", client-req 
"+req.getClientRequest()+ ')');
+                       ClientRequester cr = req.getClientRequest();
+                       if(req.canRemove()) {
+                               if(req.persistent())
+                                       
removeFromAllRequestsByClientRequest(req, cr);
+                               else
+                                       
schedTransient.removeFromAllRequestsByClientRequest(req, cr);
+                               // Do not remove from the pendingKeys list.
+                               // Whether it is running a request, waiting to 
execute, or waiting on the
+                               // cooldown queue, ULPRs and backdoor 
coalescing should still be active.
+                       }
+                       if(logMINOR) Logger.minor(this, "removeFirst() 
returning "+req+" of "+req.getClientRequest());
+                       return req;
+                       
                }
                }
                if(logMINOR) Logger.minor(this, "No requests to run");

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerNonPersistent.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerNonPersistent.java
     2008-05-21 12:28:00 UTC (rev 20010)
+++ 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerNonPersistent.java
     2008-05-21 13:04:29 UTC (rev 20011)
@@ -15,10 +15,6 @@
  */
 class ClientRequestSchedulerNonPersistent extends ClientRequestSchedulerBase {

-       // These are package-visible so that ClientRequestSchedulerCore can 
conveniently access them.
-       // THEY SHOULD NOT BE ACCESSED DIRECTLY BY ANY OTHER CLASS!
-       
-       final HashMap allRequestsByClientRequest;
        /**
         * Structure:
         * array (by priority) -> // one element per possible priority
@@ -32,7 +28,6 @@

        ClientRequestSchedulerNonPersistent(ClientRequestScheduler sched) {
                super(sched.isInsertScheduler, sched.isSSKScheduler, 
sched.isInsertScheduler ? null : new HashMap(), new HashMap(), new 
LinkedList());
-               allRequestsByClientRequest = new HashMap();
                priorities = new 
SortedVectorByNumber[RequestStarter.NUMBER_OF_PRIORITY_CLASSES];
                recentSuccesses = new LinkedList();
        }

Modified: branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArray.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArray.java      
2008-05-21 12:28:00 UTC (rev 20010)
+++ branches/db4o/freenet/src/freenet/support/SectoredRandomGrabArray.java      
2008-05-21 13:04:29 UTC (rev 20011)
@@ -164,4 +164,8 @@
                return persistent;
        }

+       public int size() {
+               return grabArrays.length;
+       }
+
 }

Modified: branches/db4o/freenet/src/freenet/support/SortedVectorByNumber.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/SortedVectorByNumber.java 
2008-05-21 12:28:00 UTC (rev 20010)
+++ branches/db4o/freenet/src/freenet/support/SortedVectorByNumber.java 
2008-05-21 13:04:29 UTC (rev 20011)
@@ -116,4 +116,9 @@
                return data[index];
        }

+       public int getNumberByIndex(int idx) {
+               if(idx >= length) return -1;
+               return data[idx].getNumber();
+       }
+
 }


Reply via email to