Author: toad
Date: 2008-05-31 15:25:30 +0000 (Sat, 31 May 2008)
New Revision: 20165

Modified:
   branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java
   
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java
   branches/db4o/freenet/src/freenet/node/RequestScheduler.java
   branches/db4o/freenet/src/freenet/node/SendableGet.java
Log:
Run onFailure() on the databaseExecutor thread.
Make sure it runs before the remove-the-job-from-running-requests logic.

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-05-31 15:15:56 UTC (rev 20164)
+++ branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-05-31 15:25:30 UTC (rev 20165)
@@ -190,7 +190,17 @@
                                                // verifies at low-level, but 
not at decode.
                                                if(logMINOR)
                                                        Logger.minor(this, 
"Decode failed: "+e, e);
-                                               getter.onFailure(new 
LowLevelGetException(LowLevelGetException.DECODE_FAILED), tok, this);
+                                               if(onDatabaseThread)
+                                                       getter.onFailure(new 
LowLevelGetException(LowLevelGetException.DECODE_FAILED), tok, this);
+                                               else {
+                                                       final SendableGet g = 
getter;
+                                                       final Object token = 
tok;
+                                                       
databaseExecutor.execute(new Runnable() {
+                                                               public void 
run() {
+                                                                       
g.onFailure(new LowLevelGetException(LowLevelGetException.DECODE_FAILED), 
token, ClientRequestScheduler.this);
+                                                               }
+                                                       }, 
NativeThread.NORM_PRIORITY, "Block decode failed");
+                                               }
                                                continue; // other keys might 
be valid
                                        }
                                        if(block != null) {
@@ -556,4 +566,18 @@
        public void removeFetchingKey(Key key) {
                schedCore.removeFetchingKey(key);
        }
+
+       public PrioritizedSerialExecutor getDatabaseExecutor() {
+               return databaseExecutor;
+       }
+
+       public void callFailure(final SendableGet get, final 
LowLevelGetException e, final Object keyNum, int prio, String name) {
+               databaseExecutor.execute(new Runnable() {
+                       public void run() {
+                               get.onFailure(e, keyNum, 
ClientRequestScheduler.this);
+                               selectorContainer.commit();
+                       }
+               }, prio, name);
+       }
+
 }

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java  
    2008-05-31 15:15:56 UTC (rev 20164)
+++ 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java  
    2008-05-31 15:25:30 UTC (rev 20165)
@@ -483,7 +483,7 @@
                                        container.commit();
                                }
                        }
-               }, NativeThread.HIGH_PRIORITY, "Remove fetching key");
+               }, NativeThread.NORM_PRIORITY, "Remove fetching key");
        }

 }

Modified: branches/db4o/freenet/src/freenet/node/RequestScheduler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/RequestScheduler.java        
2008-05-31 15:15:56 UTC (rev 20164)
+++ branches/db4o/freenet/src/freenet/node/RequestScheduler.java        
2008-05-31 15:25:30 UTC (rev 20165)
@@ -8,6 +8,7 @@
 import freenet.client.async.ChosenRequest;
 import freenet.keys.ClientKey;
 import freenet.keys.Key;
+import freenet.support.PrioritizedSerialExecutor;

 public interface RequestScheduler {

@@ -52,5 +53,9 @@
        public KeysFetchingLocally fetchingKeys();

        public void removeFetchingKey(Key key);
+
+       public PrioritizedSerialExecutor getDatabaseExecutor();
+
+       public void callFailure(final SendableGet get, final 
LowLevelGetException e, final Object keyNum, int prio, String name);

 }

Modified: branches/db4o/freenet/src/freenet/node/SendableGet.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/SendableGet.java     2008-05-31 
15:15:56 UTC (rev 20164)
+++ branches/db4o/freenet/src/freenet/node/SendableGet.java     2008-05-31 
15:25:30 UTC (rev 20165)
@@ -11,6 +11,7 @@
 import freenet.keys.Key;
 import freenet.keys.KeyBlock;
 import freenet.support.Logger;
+import freenet.support.io.NativeThread;

 /**
  * A low-level key fetch which can be sent immediately. @see SendableRequest
@@ -56,7 +57,7 @@
        /** Do the request, blocking. Called by RequestStarter. 
         * @return True if a request was executed. False if caller should try 
to find another request, and remove
         * this one from the queue. */
-       public boolean send(NodeClientCore core, RequestScheduler sched, Object 
keyNum) {
+       public boolean send(NodeClientCore core, final RequestScheduler sched, 
final Object keyNum) {
                ClientKey key = getKey(keyNum);
                if(key == null) {
                        Logger.error(this, "Key is null in send(): keyNum = 
"+keyNum+" for "+this);
@@ -73,25 +74,26 @@
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
                if(isCancelled()) {
                        if(logMINOR) Logger.minor(this, "Cancelled: "+this);
-                       onFailure(new 
LowLevelGetException(LowLevelGetException.CANCELLED), null, sched);
+                       // callbacks must initially run at HIGH_PRIORITY so 
they are executed before we remove the key from the currently running list
+                       sched.callFailure(this, new 
LowLevelGetException(LowLevelGetException.CANCELLED), null, 
NativeThread.HIGH_PRIORITY, "onFailure(cancelled)");
                        return false;
                }
                try {
                        try {
                                core.realGetKey(key, ctx.localRequestOnly, 
ctx.cacheLocalRequests, ctx.ignoreStore);
-                       } catch (LowLevelGetException e) {
-                               onFailure(e, keyNum, sched);
+                       } catch (final LowLevelGetException e) {
+                               sched.callFailure(this, e, keyNum, 
NativeThread.HIGH_PRIORITY, "onFailure");
                                return true;
                        } catch (Throwable t) {
                                Logger.error(this, "Caught "+t, t);
-                               onFailure(new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR), keyNum, sched);
+                               sched.callFailure(this, new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR), keyNum, 
NativeThread.HIGH_PRIORITY, "onFailure(caught throwable)");
                                return true;
                        }
                        // Don't call onSuccess(), it will be called for us by 
backdoor coalescing.
                        sched.succeeded(this);
                } catch (Throwable t) {
                        Logger.error(this, "Caught "+t, t);
-                       onFailure(new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR), keyNum, sched);
+                       sched.callFailure(this, new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR), keyNum, 
NativeThread.HIGH_PRIORITY, "onFailure(caught throwable)");
                        return true;
                }
                return true;
@@ -141,8 +143,13 @@
                getScheduler().removePendingKey(this, false, key);
        }

-       public void internalError(Object keyNum, Throwable t, RequestScheduler 
sched) {
-               onFailure(new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR, t.getMessage(), t), 
keyNum, sched);
+       public void internalError(final Object keyNum, final Throwable t, final 
RequestScheduler sched) {
+               sched.getDatabaseExecutor().execute(new Runnable() {
+                       public void run() {
+                               onFailure(new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR, t.getMessage(), t), 
keyNum, sched);
+                       }
+               }, NativeThread.MAX_PRIORITY, // ensure this is run before the 
callback to remove the request from the running requests list 
+               "Internal error");
        }

        /**


Reply via email to