Author: toad
Date: 2008-03-24 16:30:49 +0000 (Mon, 24 Mar 2008)
New Revision: 18736

Modified:
   trunk/freenet/src/freenet/support/RandomGrabArray.java
Log:
When there are very few items, avoid logging an error if they are all excluded, 
defrag them, and pick a random non-excluded item.

Modified: trunk/freenet/src/freenet/support/RandomGrabArray.java
===================================================================
--- trunk/freenet/src/freenet/support/RandomGrabArray.java      2008-03-24 
16:03:00 UTC (rev 18735)
+++ trunk/freenet/src/freenet/support/RandomGrabArray.java      2008-03-24 
16:30:49 UTC (rev 18736)
@@ -63,6 +63,66 @@
                                        if(logMINOR) Logger.minor(this, "All 
null on "+this);
                                        return null;
                                }
+                               if(index < MAX_EXCLUDED) {
+                                       // Optimise the common case of not many 
items, and avoid some spurious errors.
+                                       int random = -1;
+                                       while(true) {
+                                               int exclude = 0;
+                                               int valid = 0;
+                                               int validIndex = -1;
+                                               int target = 0;
+                                               for(int i=0;i<index;i++) {
+                                                       RandomGrabArrayItem 
item = reqs[i];
+                                                       if(item == null) {
+                                                               continue;
+                                                       } else 
if(item.isCancelled()) {
+                                                               reqs[i] = null;
+                                                               
contents.remove(item);
+                                                               continue;
+                                                       }
+                                                       if(i != target) {
+                                                               reqs[i] = null;
+                                                               reqs[target] = 
item;
+                                                       }
+                                                       target++;
+                                                       
if(excluding.exclude(item)) {
+                                                               exclude++;
+                                                       } else {
+                                                               if(valid == 
random) { // Picked on previous round
+                                                                       
if(item.canRemove()) {
+                                                                               
contents.remove(item);
+                                                                               
reqs[i] = null;
+                                                                       }
+                                                                       return 
item;
+                                                               }
+                                                               validIndex = 
target-1;
+                                                               valid++;
+                                                       }
+                                               }
+                                               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(valid == 0 && exclude == 0) {
+                                                       index = 0;
+                                                       if(logMINOR) 
Logger.minor(this, "No valid or excluded items");
+                                                       return null;
+                                               } else if(valid == 0) {
+                                                       if(logMINOR) 
Logger.minor(this, "No valid items, "+exclude+" excluded items");
+                                                       return null;
+                                               } else if(valid == 1) {
+                                                       ret = reqs[validIndex];
+                                                       if(ret.canRemove()) {
+                                                               index = 0;
+                                                               
contents.remove(ret);
+                                                               
reqs[validIndex] = null;
+                                                       }
+                                                       if(logMINOR) 
Logger.minor(this, "No valid or excluded items after removing "+ret);
+                                                       return ret;
+                                               } else {
+                                                       random = 
rand.nextInt(valid);
+                                               }
+                                       }
+                               }
                                int i = rand.nextInt(index);
                                ret = reqs[i];
                                oret = ret;
@@ -73,7 +133,7 @@
                                if(ret != null && excluding.exclude(ret)) {
                                        excluded++;
                                        if(excluded > MAX_EXCLUDED) {
-                                               Logger.error(this, "Remove 
random returning null because "+excluded+" excluded items", new 
Exception("error"));
+                                               Logger.error(this, "Remove 
random returning null because "+excluded+" excluded items, length = "+index, 
new Exception("error"));
                                                return null;
                                        }
                                        continue;


Reply via email to