Author: toad
Date: 2008-03-21 23:04:59 +0000 (Fri, 21 Mar 2008)
New Revision: 18706
Modified:
trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
trunk/freenet/src/freenet/client/async/OfferedKeysList.java
trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
trunk/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
trunk/freenet/src/freenet/node/RequestStarter.java
trunk/freenet/src/freenet/node/SendableRequest.java
trunk/freenet/src/freenet/node/SimpleSendableInsert.java
Log:
Pass KeysFetchingLocally into chooseKey(). Use this to not fetch offered keys
which we are already fetching.
Modified: trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
2008-03-21 22:58:07 UTC (rev 18705)
+++ trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
2008-03-21 23:04:59 UTC (rev 18706)
@@ -9,6 +9,7 @@
import freenet.keys.Key;
import freenet.keys.KeyBlock;
import freenet.keys.KeyVerifyException;
+import freenet.node.KeysFetchingLocally;
import freenet.node.RequestScheduler;
import freenet.node.SendableGet;
import freenet.support.Logger;
@@ -42,7 +43,8 @@
return keys;
}
- public Object chooseKey() {
+ public Object chooseKey(KeysFetchingLocally fetching) {
+ if(fetching.hasKey(key.getNodeKey())) return null;
return keys[0];
}
Modified: trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
2008-03-21 22:58:07 UTC (rev 18705)
+++ trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
2008-03-21 23:04:59 UTC (rev 18706)
@@ -398,7 +398,7 @@
return null;
}
if(tryOfferedKeys) {
- if(!offeredKeys[choosenPriorityClass].isEmpty())
+
if(offeredKeys[choosenPriorityClass].hasValidKeys(starter))
return offeredKeys[choosenPriorityClass];
}
SortedVectorByNumber s = priorities[choosenPriorityClass];
Modified: trunk/freenet/src/freenet/client/async/OfferedKeysList.java
===================================================================
--- trunk/freenet/src/freenet/client/async/OfferedKeysList.java 2008-03-21
22:58:07 UTC (rev 18705)
+++ trunk/freenet/src/freenet/client/async/OfferedKeysList.java 2008-03-21
23:04:59 UTC (rev 18706)
@@ -8,8 +8,10 @@
import freenet.crypt.RandomSource;
import freenet.keys.Key;
+import freenet.node.KeysFetchingLocally;
import freenet.node.NodeClientCore;
import freenet.node.RequestScheduler;
+import freenet.node.RequestStarter;
import freenet.node.SendableRequest;
import freenet.node.NodeClientCore.SimpleRequestSenderCompletionListener;
import freenet.support.Logger;
@@ -71,20 +73,35 @@
throw new UnsupportedOperationException();
}
- public synchronized Object chooseKey() {
+ public synchronized Object chooseKey(KeysFetchingLocally fetching) {
assert(keysList.size() == keys.size());
+ for(int i=0;i<10;i++) {
// Pick a random key
if(keysList.isEmpty()) return null;
int ptr = random.nextInt(keysList.size());
// Avoid shuffling penalty by swapping the chosen element with
the end.
Key k = (Key) keysList.get(ptr);
+ if(fetching.hasKey(k)) continue;
keysList.set(ptr, keysList.get(keysList.size()-1));
keysList.setSize(keysList.size()-1);
keys.remove(k);
assert(keysList.size() == keys.size());
return k;
+ }
+ return null;
}
+ public synchronized boolean hasValidKeys(RequestStarter starter) {
+ assert(keysList.size() == keys.size());
+ for(int i=0;i<10;i++) {
+ // Pick a random key
+ if(keysList.isEmpty()) return false;
+ int ptr = random.nextInt(keysList.size());
+ return true;
+ }
+ return false;
+ }
+
public Object getClient() {
return this;
}
Modified: trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
2008-03-21 22:58:07 UTC (rev 18705)
+++ trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
2008-03-21 23:04:59 UTC (rev 18706)
@@ -16,6 +16,7 @@
import freenet.keys.FreenetURI;
import freenet.keys.InsertableClientSSK;
import freenet.keys.SSKEncodeException;
+import freenet.node.KeysFetchingLocally;
import freenet.node.LowLevelPutException;
import freenet.node.NodeClientCore;
import freenet.node.RequestScheduler;
@@ -357,7 +358,7 @@
return sendableKeys();
}
- public synchronized Object chooseKey() {
+ public synchronized Object chooseKey(KeysFetchingLocally ignored) {
if(finished) return null;
else return new Integer(0);
}
Modified: trunk/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
2008-03-21 22:58:07 UTC (rev 18705)
+++ trunk/freenet/src/freenet/client/async/SplitFileFetcherSubSegment.java
2008-03-21 23:04:59 UTC (rev 18706)
@@ -15,6 +15,7 @@
import freenet.keys.KeyBlock;
import freenet.keys.KeyDecodeException;
import freenet.keys.TooBigException;
+import freenet.node.KeysFetchingLocally;
import freenet.node.LowLevelGetException;
import freenet.node.RequestScheduler;
import freenet.node.SendableGet;
@@ -59,9 +60,9 @@
return ctx;
}
- public Object chooseKey() {
+ public Object chooseKey(KeysFetchingLocally keys) {
if(cancelled) return null;
- return removeRandomBlockNum();
+ return removeRandomBlockNum(keys);
}
public ClientKey getKey(Object token) {
@@ -98,18 +99,35 @@
return blockNums.toArray();
}
- private synchronized Object removeRandomBlockNum() {
+ private Object removeRandomBlockNum(KeysFetchingLocally keys) {
logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ synchronized(this) {
if(blockNums.isEmpty()) {
if(logMINOR)
Logger.minor(this, "No blocks to remove");
return null;
}
- int x = ctx.random.nextInt(blockNums.size());
- Object ret = (Integer) blockNums.remove(x);
+ }
+ for(int i=0;i<10;i++) {
+ Object ret;
+ int x;
+ synchronized(this) {
+ x = ctx.random.nextInt(blockNums.size());
+ ret = (Integer) blockNums.remove(x);
+ }
+ // LOCKING: keys is safe to check, but segment isn't.
+ Key key = segment.getBlockNodeKey(((Integer)ret).intValue());
+ if(keys.hasKey(key)) {
+ synchronized(this) {
+ blockNums.add(ret);
+ }
+ continue;
+ }
if(logMINOR)
Logger.minor(this, "Removing block "+x+" of
"+(blockNums.size()+1)+ " : "+ret+ " on "+this);
return ret;
+ }
+ return null;
}
public boolean ignoreStore() {
Modified: trunk/freenet/src/freenet/node/RequestStarter.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestStarter.java 2008-03-21 22:58:07 UTC
(rev 18705)
+++ trunk/freenet/src/freenet/node/RequestStarter.java 2008-03-21 23:04:59 UTC
(rev 18706)
@@ -162,7 +162,7 @@
if(req == null) continue;
if(!startRequest(req, logMINOR)) {
if(!req.isCancelled())
- Logger.error(this, "No requests to
start on "+req);
+ Logger.normal(this, "No requests to
start on "+req);
}
req = null;
cycleTime = sentRequestTime =
System.currentTimeMillis();
@@ -186,7 +186,7 @@
Key key = null;
while(true) {
try {
- keyNum = req.chooseKey();
+ keyNum = req.chooseKey(isInsert ? null : this);
if(keyNum == null) return false;
if(!isInsert) {
key =
((SendableGet)req).getKey(keyNum).getNodeKey();
@@ -252,7 +252,7 @@
try {
freenet.support.Logger.OSThread.logPID(this);
if(!req.send(core, sched, keyNum))
- Logger.normal(this, "run() not able to send a
request");
+ Logger.error(this, "run() not able to send a
request on "+req);
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Finished "+req);
} finally {
Modified: trunk/freenet/src/freenet/node/SendableRequest.java
===================================================================
--- trunk/freenet/src/freenet/node/SendableRequest.java 2008-03-21 22:58:07 UTC
(rev 18705)
+++ trunk/freenet/src/freenet/node/SendableRequest.java 2008-03-21 23:04:59 UTC
(rev 18706)
@@ -22,7 +22,7 @@
* (but not the key itself, implementors must have a separate queue of
block
* numbers and mapping of block numbers to keys).
* @return An object identifying a specific key. -1 indicates no keys
available. */
- public abstract Object chooseKey();
+ public abstract Object chooseKey(KeysFetchingLocally keys);
/** All key identifiers. Including those not currently eligible to be
sent because
* they are on a cooldown queue, requests for them are in progress,
etc. */
Modified: trunk/freenet/src/freenet/node/SimpleSendableInsert.java
===================================================================
--- trunk/freenet/src/freenet/node/SimpleSendableInsert.java 2008-03-21
22:58:07 UTC (rev 18705)
+++ trunk/freenet/src/freenet/node/SimpleSendableInsert.java 2008-03-21
23:04:59 UTC (rev 18706)
@@ -124,7 +124,7 @@
return new Object[] { new Integer(0) };
}
- public synchronized Object chooseKey() {
+ public synchronized Object chooseKey(KeysFetchingLocally keys) {
if(finished) return null;
else return new Integer(0);
}