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() {
