Author: toad
Date: 2008-06-27 12:18:15 +0000 (Fri, 27 Jun 2008)
New Revision: 20817
Modified:
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
Log:
Don't allow the same block number in blockNums twice.
Most callers want us to scream if we averted this, some don't.
Related to same bug as previous, but imho we should keep this.
Modified:
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
2008-06-27 12:16:42 UTC (rev 20816)
+++ branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
2008-06-27 12:18:15 UTC (rev 20817)
@@ -512,7 +512,7 @@
seg.unregisterKey(key.getNodeKey(), context, container);
if(logMINOR)
Logger.minor(this, "Retrying block "+blockNo+"
on "+this+" : tries="+tries+"/"+maxTries+" : "+sub);
- sub.add(blockNo, false, container, context);
+ sub.add(blockNo, false, container, context, false);
}
}
@@ -576,7 +576,7 @@
if(persistent)
container.activate(seg, 1);
for(int
i=0;i<dataRetries.length+checkRetries.length;i++)
- seg.add(i, true, container, context);
+ seg.add(i, true, container, context, false);
seg.schedule(container, context);
synchronized(this) {
@@ -678,13 +678,16 @@
return checkCooldownTimes[blockNum - dataKeys.length];
}
- public void requeueAfterCooldown(Key key, long time, ObjectContainer
container, ClientContext context) {
+ /**
+ * @return True if the key was wanted and the scheduled segment was the
one that called, false otherwise.
+ */
+ public boolean requeueAfterCooldown(Key key, long time, ObjectContainer
container, ClientContext context, SplitFileFetcherSubSegment segment) {
if(persistent)
container.activate(this, 1);
Vector v = null;
boolean notFound = true;
synchronized(this) {
- if(isFinishing(container)) return;
+ if(isFinishing(container)) return false;
int maxTries = blockFetchContext.maxNonSplitfileRetries;
for(int i=0;i<dataKeys.length;i++) {
if(dataKeys[i] == null) continue;
@@ -695,14 +698,14 @@
if(dataCooldownTimes[i] > time) {
if(logMINOR)
Logger.minor(this, "Not
retrying after cooldown for data block "+i+"as deadline has not passed yet on
"+this);
- return;
+ return false;
}
int tries = dataRetries[i];
SplitFileFetcherSubSegment sub =
getSubSegment(tries);
if(logMINOR)
Logger.minor(this, "Retrying after
cooldown on "+this+": data block "+i+" on "+this+" :
tries="+tries+"/"+maxTries+" : "+sub);
if(v == null) v = new Vector();
- sub.add(i, true, container, context);
+ sub.add(i, true, container, context, true);
if(!v.contains(sub)) v.add(sub);
notFound = false;
}
@@ -716,14 +719,14 @@
if(checkCooldownTimes[i] > time) {
if(logMINOR)
Logger.minor(this, "Not
retrying after cooldown for data block "+i+" as deadline has not passed yet on
"+this);
- return;
+ return false;
}
int tries = checkRetries[i];
SplitFileFetcherSubSegment sub =
getSubSegment(tries);
if(logMINOR)
Logger.minor(this, "Retrying after
cooldown on "+this+": check block "+i+" on "+this+" :
tries="+tries+"/"+maxTries+" : "+sub);
if(v == null) v = new Vector();
- sub.add(i+dataKeys.length, true, container,
context);
+ sub.add(i+dataKeys.length, true, container,
context, true);
if(!v.contains(sub)) v.add(sub);
notFound = false;
}
@@ -732,11 +735,14 @@
if(notFound) {
Logger.error(this, "requeueAfterCooldown: Key not
found!: "+key+" on "+this);
}
+ boolean foundCaller = false;
if(v != null) {
for(int i=0;i<v.size();i++) {
+ if(v.get(i) == segment) foundCaller = true;
((SplitFileFetcherSubSegment)
v.get(i)).schedule(container, context);
}
}
+ return foundCaller;
}
public synchronized long getCooldownWakeupByKey(Key key,
ObjectContainer container) {
Modified:
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
===================================================================
---
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
2008-06-27 12:16:42 UTC (rev 20816)
+++
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
2008-06-27 12:18:15 UTC (rev 20817)
@@ -118,9 +118,27 @@
container.activate(this, 1);
container.activate(blockNums, 1);
}
+ cleanBlockNums();
return blockNums.toArray();
}
+ private void cleanBlockNums() {
+ synchronized(segment) {
+ int initSize = blockNums.size();
+ Integer prev = null;
+ for(int i=0;i<blockNums.size();i++) {
+ Integer x = (Integer) blockNums.get(i);
+ if(x == prev || x.equals(prev)) {
+ blockNums.remove(i);
+ i--;
+ }
+ }
+ if(blockNums.size() < initSize) {
+ Logger.error(this, "Cleaned block number list
duplicates: was "+initSize+" now "+blockNums.size());
+ }
+ }
+ }
+
private Object removeRandomBlockNum(KeysFetchingLocally keys,
ClientContext context, ObjectContainer container) {
if(persistent) {
container.activate(this, 1);
@@ -394,7 +412,7 @@
return false;
}
- public void add(int blockNo, boolean dontSchedule, ObjectContainer
container, ClientContext context) {
+ public void add(int blockNo, boolean dontSchedule, ObjectContainer
container, ClientContext context, boolean dontComplainOnDupes) {
if(persistent) {
container.activate(this, 1);
container.activate(segment, 1);
@@ -409,7 +427,12 @@
synchronized(segment) {
if(cancelled)
throw new IllegalStateException("Adding block
"+blockNo+" to already cancelled "+this);
- blockNums.add(i);
+ if(blockNums.contains(i)) {
+ if(!dontComplainOnDupes)
+ Logger.error(this, "Block numbers
already contain block "+blockNo);
+ } else {
+ blockNums.add(i);
+ }
if(dontSchedule) schedule = false;
/**
* Race condition:
@@ -538,7 +561,10 @@
}
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Requeueing after cooldown "+key+"
for "+this);
- segment.requeueAfterCooldown(key, time, container, context);
+ if(!segment.requeueAfterCooldown(key, time, container, context,
this)) {
+ Logger.error(this, "Removing key "+key+" for "+this+"
in requeueAfterCooldown as is now registered to a different subsegment");
+ unregisterKey(key, context, container);
+ }
}
public long getCooldownWakeupByKey(Key key, ObjectContainer container) {