Author: toad
Date: 2008-06-26 13:18:47 +0000 (Thu, 26 Jun 2008)
New Revision: 20738

Modified:
   branches/db4o/freenet/src/freenet/support/RandomGrabArray.java
Log:
More queue structures deactivation to reduce required memory usage (db4o will 
keep stuff in weak refs if there is plenty of memory).
Database updating.
Activating *after* checking isEmpty() in one place, this is bad!
setParentGrabArray to null when removing an empty item in compaction.
Remove double activations.
Don't set changedMe (hence set to database) if we don't change the index.
Pass the chosen/valid item as a variable, and don't deactivate it, and assert 
that it's what it should be - partly a minor optimisation.
Removal loop: Check for nulls, but don't check for cancelled, since we'd have 
to activate.
Don't double check for cancelled request.
Comments.

Modified: branches/db4o/freenet/src/freenet/support/RandomGrabArray.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/RandomGrabArray.java      
2008-06-26 13:08:09 UTC (rev 20737)
+++ branches/db4o/freenet/src/freenet/support/RandomGrabArray.java      
2008-06-26 13:18:47 UTC (rev 20738)
@@ -55,7 +55,10 @@
                        }
                        reqs[index++] = req;
                        if(logMINOR) Logger.minor(this, "Added: "+req+" to 
"+this+" size now "+index);
-                       if(persistent) container.set(this);
+                       if(persistent) {
+                               container.set(contents);
+                               container.set(this);
+                       }
                }
        }

@@ -80,43 +83,58 @@
                                                int validIndex = -1;
                                                int target = 0;
                                                int chosenIndex = -1;
+                                               RandomGrabArrayItem chosenItem 
= null;
+                                               RandomGrabArrayItem validItem = 
null;
                                                for(int i=0;i<index;i++) {
+                                                       // Compact the array.
                                                        RandomGrabArrayItem 
item = reqs[i];
+                                                       if(persistent)
+                                                               
container.activate(item, 1);
                                                        if(item == null) {
                                                                continue;
                                                        } else 
if(item.isEmpty(container)) {
                                                                changedMe = 
true;
+                                                               // We are doing 
compaction here. We don't need to swap with the end; we write valid ones to the 
target location.
                                                                reqs[i] = null;
                                                                
contents.remove(item);
+                                                               
item.setParentGrabArray(null, container);
                                                                continue;
                                                        }
                                                        if(i != target) {
                                                                changedMe = 
true;
                                                                reqs[i] = null;
                                                                reqs[target] = 
item;
-                                                       }
+                                                       } // else the request 
can happily stay where it is
                                                        target++;
-                                                       if(persistent)
-                                                               
container.activate(item, 1);
                                                        
if(excluding.exclude(item, container, context)) {
                                                                exclude++;
                                                        } else {
                                                                if(valid == 
random) { // Picked on previous round
                                                                        
chosenIndex = target-1;
+                                                                       
chosenItem = item;
                                                                }
-                                                               validIndex = 
target-1;
+                                                               if(validIndex 
!= -1) {
+                                                                       // Take 
the first valid item
+                                                                       
validIndex = target-1;
+                                                                       
validItem = item;
+                                                               }
                                                                valid++;
                                                        }
+                                                       if(persistent && item 
!= chosenItem && item != validItem)
+                                                               
container.deactivate(item, 1);
                                                }
-                                               changedMe = true;
-                                               index = target;
+                                               if(index != target) {
+                                                       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) {
+                                               if(chosenItem != null) {
+                                                       if(persistent && 
validItem != null && validItem != chosenItem)
+                                                               
container.deactivate(validItem, 1);
                                                        changedMe = true;
-                                                       ret = reqs[chosenIndex];
-                                                       if(persistent)
-                                                               
container.activate(ret, 1);
+                                                       ret = chosenItem;
+                                                       assert(ret == 
reqs[chosenIndex]);
                                                        
if(ret.canRemove(container)) {
                                                                
contents.remove(ret);
                                                                if(chosenIndex 
!= index-1) {
@@ -141,9 +159,8 @@
                                                        if(logMINOR) 
Logger.minor(this, "No valid items, "+exclude+" excluded items");
                                                        return null;
                                                } else if(valid == 1) {
-                                                       ret = reqs[validIndex];
-                                                       if(persistent)
-                                                               
container.activate(ret, 1);
+                                                       ret = validItem;
+                                                       assert(ret == 
reqs[validIndex]);
                                                        
if(ret.canRemove(container)) {
                                                                changedMe = 
true;
                                                                
contents.remove(ret);
@@ -182,9 +199,11 @@
                                if(ret.isEmpty(container)) {
                                        if(logMINOR) Logger.minor(this, "Not 
returning because cancelled: "+ret);
                                        ret = null;
+                                       // Will be removed in the do{} loop
                                }
                                if(ret != null && excluding.exclude(ret, 
container, context)) {
                                        excluded++;
+                                       container.deactivate(ret, 1);
                                        if(excluded > MAX_EXCLUDED) {
                                                Logger.error(this, "Remove 
random returning null because "+excluded+" excluded items, length = "+index, 
new Exception("error"));
                                                if(persistent && changedMe)
@@ -199,15 +218,18 @@
                                                container.set(this);
                                        return ret;
                                }
+                               // Remove an element.
                                do {
                                        changedMe = true;
                                        reqs[i] = reqs[--index];
                                        reqs[index] = null;
                                        if(oret != null)
                                                contents.remove(oret);
+                                       if(persistent && oret != null && ret == 
null) // if ret != null we will return it
+                                               container.deactivate(oret, 1);
                                        oret = reqs[i];
-                                       // May as well check whether that is 
cancelled too.
-                               } while (index > i && (oret == null || 
oret.isEmpty(container)));
+                                       // Check for nulls, but don't check for 
cancelled, since we'd have to activate.
+                               } while (index > i && oret == null);
                                // Shrink array
                                if((index < reqs.length / 4) && (reqs.length > 
MIN_SIZE)) {
                                        changedMe = true;
@@ -217,7 +239,7 @@
                                        System.arraycopy(reqs, 0, r, 0, 
r.length);
                                        reqs = r;
                                }
-                               if((ret != null) && !ret.isEmpty(container)) 
break;
+                               if(ret != null) break;
                        }
                }
                if(logMINOR) Logger.minor(this, "Returning "+ret+" of "+index);
@@ -241,8 +263,10 @@
                        }
                }
                it.setParentGrabArray(null, container);
-               if(persistent)
+               if(persistent) {
+                       container.set(contents);
                        container.set(this);
+               }
        }

        public synchronized boolean isEmpty() {


Reply via email to