Author: toad
Date: 2008-03-24 23:31:11 +0000 (Mon, 24 Mar 2008)
New Revision: 18756
Modified:
trunk/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
Log:
SubSegment: synchronize on the parent Segment.
Modified: trunk/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
2008-03-24 23:30:10 UTC (rev 18755)
+++ trunk/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
2008-03-24 23:31:11 UTC (rev 18756)
@@ -27,6 +27,8 @@
* Collects together all requests within that segment at a given retry level.
* Registered on the ClientRequestScheduler instead of
SimpleSingleFileFetcher's.
* When CRS asks it to run a request, returns one, and only unregisters if no
more requests in this category.
+ *
+ * LOCKING: Synchronize on the parent segment. Nothing else makes sense w.r.t.
nested locking.
*/
public class SplitFileFetcherSubSegment extends SendableGet {
@@ -101,7 +103,7 @@
private Object removeRandomBlockNum(KeysFetchingLocally keys) {
logMINOR = Logger.shouldLog(Logger.MINOR, this);
- synchronized(this) {
+ synchronized(segment) {
if(blockNums.isEmpty()) {
if(logMINOR)
Logger.minor(this, "No blocks to
remove");
@@ -111,7 +113,7 @@
for(int i=0;i<10;i++) {
Object ret;
int x;
- synchronized(this) {
+ synchronized(segment) {
x = ctx.random.nextInt(blockNums.size());
ret = (Integer) blockNums.remove(x);
}
@@ -123,14 +125,14 @@
continue;
}
if(keys.hasKey(key)) {
- synchronized(this) {
+ synchronized(segment) {
blockNums.add(ret);
}
// Double check that it hasn't been found.
key =
segment.getBlockNodeKey(((Integer)ret).intValue());
if(key == null) {
// A race condition is possible but
should only rarely cause a Key is null for block <block>.
- synchronized(this) {
+ synchronized(segment) {
blockNums.add(ret);
}
}
@@ -147,7 +149,7 @@
for(int i=0;i<10;i++) {
Object ret;
int x;
- synchronized(this) {
+ synchronized(segment) {
if(blockNums.isEmpty()) return false;
x = ctx.random.nextInt(blockNums.size());
ret = (Integer) blockNums.get(x);
@@ -156,7 +158,7 @@
Key key =
segment.getBlockNodeKey(((Integer)ret).intValue());
if(key == null) {
Logger.error(this, "Key is null for block
"+ret+" for "+this+" in hasValidKeys()");
- synchronized(this) {
+ synchronized(segment) {
blockNums.remove(x);
}
continue;
@@ -239,7 +241,7 @@
// Normally when this method is called the block number
has already
// been removed. However if fromStore=true, it won't
have been, so
// we have to do it. (Check the call trace for why)
- synchronized(this) {
+ synchronized(segment) {
for(int i=0;i<blockNums.size();i++) {
Integer x = (Integer) blockNums.get(i);
// Compare by value as sometimes we
will do new Integer(num) in requeueing after cooldown code.
@@ -308,7 +310,8 @@
return retryCount;
}
- public synchronized boolean canRemove() {
+ public boolean canRemove() {
+ synchronized(segment) {
if(blockNums.size() < 2) {
// Can be removed, if the one key is processed.
// Once it has been processed, we may need to be
reinstated.
@@ -316,10 +319,13 @@
Logger.minor(this, "Can remove "+this+" in
canRemove()");
return true;
} else return false;
+ }
}
- public synchronized boolean isCancelled() {
+ public boolean isCancelled() {
+ synchronized(segment) {
return cancelled;
+ }
}
public boolean isSSK() {
@@ -334,7 +340,7 @@
Integer i = new Integer(blockNo);
boolean schedule = true;
- synchronized(this) {
+ synchronized(segment) {
if(cancelled)
throw new IllegalStateException("Adding block
"+blockNo+" to already cancelled "+this);
blockNums.add(i);
@@ -370,13 +376,13 @@
public void possiblyRemoveFromParent() {
if(logMINOR)
Logger.minor(this, "Possibly removing from parent:
"+this);
- synchronized(this) {
+ synchronized(segment) {
if(!blockNums.isEmpty()) return;
if(logMINOR)
Logger.minor(this, "Definitely removing from
parent: "+this);
}
if(!segment.maybeRemoveSeg(this)) return;
- synchronized(this) {
+ synchronized(segment) {
cancelled = true;
}
unregister();
@@ -386,7 +392,7 @@
if(logMINOR) Logger.minor(this, "onGotKey("+key+")");
// Find and remove block if it is on this subsegment. However
it may have been
// removed already.
- synchronized(this) {
+ synchronized(segment) {
for(int i=0;i<blockNums.size();i++) {
Integer token = (Integer) blockNums.get(i);
int num = ((Integer)token).intValue();
@@ -430,7 +436,7 @@
Logger.minor(this, "Killing "+this);
// Do unregister() first so can get and unregister each key and
avoid a memory leak
unregister();
- synchronized(this) {
+ synchronized(segment) {
blockNums.clear();
cancelled = true;
}