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


Reply via email to