Author: toad
Date: 2008-05-31 13:32:53 +0000 (Sat, 31 May 2008)
New Revision: 20156

Added:
   branches/db4o/freenet/src/freenet/client/async/PersistentChosenRequest.java
Modified:
   branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java
   
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java
Log:
When we choose a persistent request, store it to the database (in the same 
transaction as finding it).
When it's finished, remove it.
When we restart, restart any requests which weren't removed.
Hence we can remove the request from the main queue structures, and rely on 
getting the failure callback if it fails.

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-05-31 13:12:13 UTC (rev 20155)
+++ branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-05-31 13:32:53 UTC (rev 20156)
@@ -108,6 +108,8 @@
                this.selectorContainer = node.db;
                schedCore = ClientRequestSchedulerCore.create(node, forInserts, 
forSSKs, selectorContainer, COOLDOWN_PERIOD, core.clientDatabaseExecutor, this);
                schedTransient = new ClientRequestSchedulerNonPersistent(this);
+               schedCore.fillStarterQueue();
+               schedCore.start();
                persistentCooldownQueue = schedCore.persistentCooldownQueue;
                this.databaseExecutor = core.clientDatabaseExecutor;
                this.starter = starter;
@@ -280,6 +282,12 @@
                databaseExecutor.executeNoDupes(requestStarterQueueFiller, 
                                NativeThread.MAX_PRIORITY, "Fill request 
starter queue");
        }
+
+       void addToStarterQueue(PersistentChosenRequest req) {
+               synchronized(starterQueue) {
+                       starterQueue.add(req);
+               }
+       }

        private Runnable requestStarterQueueFiller = new Runnable() {
                public void run() {

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java  
    2008-05-31 13:12:13 UTC (rev 20155)
+++ 
branches/db4o/freenet/src/freenet/client/async/ClientRequestSchedulerCore.java  
    2008-05-31 13:32:53 UTC (rev 20156)
@@ -114,9 +114,28 @@
                else
                        keysFetching = null;
                this.sched = sched;
+       }
+       
+       void start() {
                databaseExecutor.execute(registerMeRunner, 
NativeThread.NORM_PRIORITY, "Register request");
        }

+       void fillStarterQueue() {
+               ObjectSet results = container.query(new Predicate() {
+                       public boolean match(PersistentChosenRequest req) {
+                               if(req.core != ClientRequestSchedulerCore.this) 
return false;
+                               return true;
+                       }
+               });
+               while(results.hasNext()) {
+                       PersistentChosenRequest req = (PersistentChosenRequest) 
results.next();
+                       sched.addToStarterQueue(req);
+                       synchronized(keysFetching) {
+                               keysFetching.add(req.key);
+                       }
+               }
+       }
+       
        // We pass in the schedTransient to the next two methods so that we can 
select between either of them.

        private int removeFirstAccordingToPriorities(boolean tryOfferedKeys, 
int fuzz, RandomSource random, OfferedKeysList[] offeredKeys, 
ClientRequestSchedulerNonPersistent schedTransient, boolean transientOnly, 
short maxPrio){
@@ -168,7 +187,9 @@
                                key = null;
                        else
                                key = ((BaseSendableGet)req).getNodeKey(token);
-                       ChosenRequest ret = new ChosenRequest(req, token, key);
+                       PersistentChosenRequest ret = new 
PersistentChosenRequest(this, req, token, key);
+                       if(req.persistent())
+                               container.set(ret);
                        if(key != null)
                                keysFetching.add(key);
                        return ret;
@@ -444,10 +465,25 @@
                }
        }

-       public void removeFetchingKey(Key key) {
+       public void removeFetchingKey(final Key key) {
                synchronized(keysFetching) {
                        keysFetching.remove(key);
                }
+               sched.databaseExecutor.execute(new Runnable() {
+                       public void run() {
+                               ObjectSet results = container.query(new 
Predicate() {
+                                       public boolean 
match(PersistentChosenRequest req) {
+                                               if(req.core != 
ClientRequestSchedulerCore.this) return false;
+                                               return req.key.equals(key);
+                                       }
+                               });
+                               if(results.hasNext()) {
+                                       PersistentChosenRequest req = 
(PersistentChosenRequest) results.next();
+                                       container.delete(req);
+                                       container.commit();
+                               }
+                       }
+               }, NativeThread.HIGH_PRIORITY, "Remove fetching key");
        }

 }

Added: 
branches/db4o/freenet/src/freenet/client/async/PersistentChosenRequest.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/PersistentChosenRequest.java 
                        (rev 0)
+++ branches/db4o/freenet/src/freenet/client/async/PersistentChosenRequest.java 
2008-05-31 13:32:53 UTC (rev 20156)
@@ -0,0 +1,28 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.client.async;
+
+import freenet.keys.Key;
+import freenet.node.SendableRequest;
+
+/**
+ * When we choose a request on the database thread, if it is persistent, we 
store it to the database.
+ * The reason for this is that we may crash before it completes, in which case 
we don't want to lose 
+ * it, and the process of choosing a request is destructive i.e. it will be 
removed from the queue
+ * structures before removeFirst() returns. If we do it this way we get the 
best of all worlds:
+ * - We remove the data from the queue, so the request won't be chosen again 
until it's done, and
+ *   choosing requests won't have to go over and ignore a lot of slots.
+ * - If we restart, we will restart the persistent requests we were running, 
and will therefore get
+ *   all the relevant callbacks.
+ * @author toad
+ */
+public class PersistentChosenRequest extends ChosenRequest {
+       
+       ClientRequestSchedulerCore core;
+       
+       PersistentChosenRequest(ClientRequestSchedulerCore core, 
SendableRequest req, Object tok, Key key) {
+               super(req, tok, key);
+               this.core = core;
+       }
+}


Reply via email to