Author: xor
Date: 2008-11-16 15:53:42 +0000 (Sun, 16 Nov 2008)
New Revision: 23645

Modified:
   trunk/plugins/WoT/IdentityInserter.java
   trunk/plugins/WoT/WoT.java
   trunk/plugins/WoT/introduction/IntroductionClient.java
   trunk/plugins/WoT/introduction/IntroductionPuzzle.java
   trunk/plugins/WoT/introduction/IntroductionServer.java
Log:
Finally fix plugin unloading: Make all inserts & requests non-blocking. 
Blocking inserts/requests do not care about Thread.interrupt().

Modified: trunk/plugins/WoT/IdentityInserter.java
===================================================================
--- trunk/plugins/WoT/IdentityInserter.java     2008-11-16 14:34:36 UTC (rev 
23644)
+++ trunk/plugins/WoT/IdentityInserter.java     2008-11-16 15:53:42 UTC (rev 
23645)
@@ -9,13 +9,16 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.Iterator;
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.TransformerConfigurationException;
 import javax.xml.transform.TransformerException;
 
 import plugins.WoT.exceptions.InvalidParameterException;
+import plugins.WoT.introduction.IntroductionPuzzle;
 
 import com.db4o.ObjectContainer;
 import com.db4o.ObjectSet;
@@ -23,10 +26,18 @@
 import com.db4o.ext.Db4oIOException;
 
 import freenet.client.ClientMetadata;
+import freenet.client.FetchException;
+import freenet.client.FetchResult;
 import freenet.client.HighLevelSimpleClient;
 import freenet.client.InsertBlock;
+import freenet.client.InsertContext;
 import freenet.client.InsertException;
+import freenet.client.async.BaseClientPutter;
+import freenet.client.async.ClientCallback;
+import freenet.client.async.ClientGetter;
+import freenet.client.async.ClientPutter;
 import freenet.keys.FreenetURI;
+import freenet.node.RequestStarter;
 import freenet.support.Logger;
 import freenet.support.api.Bucket;
 import freenet.support.io.TempBucketFactory;
@@ -37,7 +48,7 @@
  * @author Julien Cornuwel ([EMAIL PROTECTED])
  *
  */
-public class IdentityInserter implements Runnable {
+public class IdentityInserter implements Runnable, ClientCallback {
        
        private static final int THREAD_PERIOD = 30 * 60 * 1000;
        
@@ -51,6 +62,8 @@
        private volatile boolean isRunning;
        private Thread mThread;
        
+       private final ArrayList<ClientPutter> mInserts = new 
ArrayList<ClientPutter>(10); /* Just assume that there are 10 identities */
+       
        /**
         * Creates an IdentityInserter.
         * 
@@ -71,6 +84,7 @@
         */
        public void run() {
                mThread = Thread.currentThread();
+               Logger.debug(this, "Identity inserter thread started.");
                
                try {
                        Thread.sleep((long) (3*60*1000 * (0.5f + 
Math.random()))); // Let the node start up
@@ -89,9 +103,6 @@
                                        try {
                                                Logger.debug(this, "Starting 
insert of "+identity.getNickName() + " (" + identity.getInsertURI().toString() 
+ ")");
                                                insert(identity);
-                                               // We set the date now, so if 
the identity is modified during the insert, we'll insert it again next time
-                                               identity.setLastInsert(new 
Date()); 
-                                               db.store(identity);
                                        } catch (Exception e) {
                                                Logger.error(this, "Identity 
insert failed: "+e.getMessage(), e);
                                        }
@@ -105,10 +116,22 @@
                        catch (InterruptedException e)
                        {
                                mThread.interrupt();
+                               Logger.debug(this, "Identity inserter thread 
interrupted.");
                        }
                }
+               
+               cancelInserts();
+               Logger.debug(this, "Identity inserter thread finished.");
        }
        
+       private synchronized void cancelInserts() {
+               Iterator<ClientPutter> i = mInserts.iterator();
+               int icounter = 0;
+               Logger.debug(this, "Trying to stop all inserts"); 
+               while (i.hasNext()) { i.next().cancel(); ++icounter; }
+               Logger.debug(this, "Stopped " + icounter + " current inserts");
+       }
+       
        /**
         * Stops the IdentityInserter thread.
         */
@@ -145,44 +168,98 @@
         * @throws InvalidParameterException
         * @throws InsertException
         */
-       private void insert(OwnIdentity identity) throws 
TransformerConfigurationException, FileNotFoundException, 
ParserConfigurationException, TransformerException, IOException, 
Db4oIOException, DatabaseClosedException, InvalidParameterException, 
InsertException {
+       private synchronized void insert(OwnIdentity identity) throws 
TransformerConfigurationException, FileNotFoundException, 
ParserConfigurationException, TransformerException, IOException, 
Db4oIOException, DatabaseClosedException, InvalidParameterException, 
InsertException {
                /* FIXME: Where is the synchronization? */
                /* TODO: after the WoT has become large enough, calculate the 
average size of identity.xml and either modify the constant or even calculate 
dynamically */
                Bucket tempB = tBF.makeBucket(8 * 1024);  
                OutputStream os = tempB.getOutputStream();
-               FreenetURI iURI;
+
                try {
                        // Create XML file to insert
                        identity.exportToXML(db, os);
                
-                       os.close();
+                       os.close(); os = null;
                        tempB.setReadOnly();
                
                        // Prepare the insert
                        ClientMetadata cmd = new ClientMetadata("text/xml");
                        InsertBlock ib = new 
InsertBlock(tempB,cmd,identity.getInsertURI());
+                       InsertContext ictx = client.getInsertContext(true);
+                       
+                       /* FIXME: are these parameters correct? */
+                       ClientPutter pu = client.insert(ib, false, 
"identity.xml", false, ictx, this);
+                       
pu.setPriorityClass(RequestStarter.UPDATE_PRIORITY_CLASS);
+                       mInserts.add(pu);
+                       tempB = null;
 
-                       // Logging
-                       Logger.debug(this, "Started insert of identity '" + 
identity.getNickName() + "'");
-
-                       /* FIXME: use nonblocking insert */
-                       // Blocking Insert
-                       iURI = client.insert(ib, false, "identity.xml");
-                       
-                       identity.setEdition(iURI.getSuggestedEdition());
+                       // We set the date now, so if the identity is modified 
during the insert, we'll insert it again next time
                        identity.setLastInsert(new Date());
                        
-                       db.store(identity);
-                       db.commit();
-                       
-                       // Logging
-                       Logger.debug(this, "Successful insert of identity '" + 
identity.getNickName() + "'");
+                       Logger.debug(this, "Started insert of identity '" + 
identity.getNickName() + "'");
                }
                catch(Exception e) {
                        Logger.error(this,"Error during insert of identity '" + 
identity.getNickName() + "'", e);
                }
                finally {
-                       tempB.free();           
+                       if(tempB != null)
+                               tempB.free();
+                       if(os != null)
+                               os.close();
                }
        }
+
+       // Only called by inserts
+       public synchronized void onSuccess(BaseClientPutter state)
+       {
+               try {
+                       OwnIdentity identity = OwnIdentity.getByURI(db, 
state.getURI());
+                       
identity.setEdition(state.getURI().getSuggestedEdition());
+                        
+                       db.store(identity);
+                       db.commit();
+                       Logger.debug(this, "Successful insert of identity '" + 
identity.getNickName() + "'");
+               } catch(Exception e) { Logger.error(this, "Error", e); }
+               state.cancel(); /* FIXME: is this necessary */
+               mInserts.remove(state);
+       }
+       
+       // Only called by inserts
+       public synchronized void onFailure(InsertException e, BaseClientPutter 
state) 
+       {
+               try {
+                       OwnIdentity identity = OwnIdentity.getByURI(db, 
state.getURI());
+
+                       Logger.error(this, "Error during insert of identity '" 
+ identity.getNickName() + "'", e);
+               } catch(Exception ex) { Logger.error(this, "Error", e); }
+               state.cancel(); /* FIXME: is this necessary */
+               mInserts.remove(state);
+       }
+       
+       /* Not needed functions from the ClientCallback inteface */
+       
+       public void onFailure(FetchException e, ClientGetter state) {
+               // TODO Auto-generated method stub
+               
+       }
+
+       public void onFetchable(BaseClientPutter state) {
+               // TODO Auto-generated method stub
+               
+       }
+
+       public void onGeneratedURI(FreenetURI uri, BaseClientPutter state) {
+               // TODO Auto-generated method stub
+               
+       }
+
+       public void onMajorProgress() {
+               // TODO Auto-generated method stub
+               
+       }
+
+       public void onSuccess(FetchResult result, ClientGetter state) {
+               // TODO Auto-generated method stub
+               
+       }
 }
+

Modified: trunk/plugins/WoT/WoT.java
===================================================================
--- trunk/plugins/WoT/WoT.java  2008-11-16 14:34:36 UTC (rev 23644)
+++ trunk/plugins/WoT/WoT.java  2008-11-16 15:53:42 UTC (rev 23645)
@@ -164,6 +164,7 @@
        }
        
        public void terminate() {
+               Logger.debug(this, "WoT plugin terminating ...");
                if(inserter != null) inserter.stop();
                if(introductionServer != null) introductionServer.terminate();
                if(introductionClient != null) introductionClient.terminate();
@@ -172,6 +173,7 @@
                        db.commit();
                        db.close();
                }
+               Logger.debug(this, "WoT plugin terminated.");
        }
 
        public String handleHTTPGet(HTTPRequest request) throws 
PluginHTTPException {   

Modified: trunk/plugins/WoT/introduction/IntroductionClient.java
===================================================================
--- trunk/plugins/WoT/introduction/IntroductionClient.java      2008-11-16 
14:34:36 UTC (rev 23644)
+++ trunk/plugins/WoT/introduction/IntroductionClient.java      2008-11-16 
15:53:42 UTC (rev 23645)
@@ -127,6 +127,8 @@
                        IntroductionPuzzle.deleteExpiredPuzzles(db);
                        downloadPuzzles();
                        
+                       Logger.debug(this, "Introduction client loop 
finished.");
+                       
                        try {
                                Thread.sleep((long) (THREAD_PERIOD * (0.5f + 
Math.random())));
                        }
@@ -135,14 +137,13 @@
                                mThread.interrupt();
                                Logger.debug(this, "Introduction client loop 
interrupted.");
                        }
-                       Logger.debug(this, "Introduction client loop 
finished.");
                }
                
                cancelRequests();
                Logger.debug(this, "Introduction client thread finished.");
        }
        
-       public synchronized void terminate() {
+       public void terminate() {
                Logger.debug(this, "Stopping the introduction client...");
                isRunning = false;
                mThread.interrupt();
@@ -201,6 +202,7 @@
                        ClientPutter pu = mClient.insert(ib, false, null, 
false, ictx, this);
                        
pu.setPriorityClass(RequestStarter.UPDATE_PRIORITY_CLASS);
                        mInserts.add(pu);
+                       tempB = null;
                        
                        Logger.debug(this, "Started to insert puzzle solution 
of " + solver.getNickName() + " at " + solutionURI);
 
@@ -209,7 +211,8 @@
                        db.commit();
                }
                finally {
-                       tempB.free();
+                       if(tempB != null)
+                               tempB.free();
                        if(os != null)
                                os.close();
                }
@@ -326,11 +329,9 @@
                        Logger.error(this, "Parsing failed for "+ 
state.getURI(), e);
                }
        }
-       
-       /* Not needed functions from the ClientCallback inteface */
-       
+
        // Only called by inserts
-       public void onSuccess(BaseClientPutter state)
+       public synchronized void onSuccess(BaseClientPutter state)
        {
                Logger.debug(this, "Successful insert of puzzle solution at " + 
state.getURI());
                state.cancel(); /* FIXME: is this necessary */
@@ -338,7 +339,14 @@
        }
        
        // Only called by inserts
-       public void onFailure(InsertException e, BaseClientPutter state) {}
+       public synchronized void onFailure(InsertException e, BaseClientPutter 
state)
+       {
+               Logger.debug(this, "Insert of puzzle solution failed for " + 
state.getURI(), e);
+               state.cancel(); /* FIXME: is this necessary */
+               mInserts.remove(state);
+       }
+       
+       /* Not needed functions from the ClientCallback inteface */
 
        // Only called by inserts
        public void onFetchable(BaseClientPutter state) {}

Modified: trunk/plugins/WoT/introduction/IntroductionPuzzle.java
===================================================================
--- trunk/plugins/WoT/introduction/IntroductionPuzzle.java      2008-11-16 
14:34:36 UTC (rev 23644)
+++ trunk/plugins/WoT/introduction/IntroductionPuzzle.java      2008-11-16 
15:53:42 UTC (rev 23645)
@@ -161,7 +161,7 @@
          * @return
          * @throws ParseException
          */
-       public static IntroductionPuzzle getBySolutionURI(ObjectContainer db, 
FreenetURI uri) throws ParseException {
+       public static IntroductionPuzzle getByURI(ObjectContainer db, 
FreenetURI uri) throws ParseException {
                UUID id = UUID.fromString(uri.getDocName().split("|")[3]);
                
                Query q = db.query();

Modified: trunk/plugins/WoT/introduction/IntroductionServer.java
===================================================================
--- trunk/plugins/WoT/introduction/IntroductionServer.java      2008-11-16 
14:34:36 UTC (rev 23644)
+++ trunk/plugins/WoT/introduction/IntroductionServer.java      2008-11-16 
15:53:42 UTC (rev 23645)
@@ -29,10 +29,12 @@
 import freenet.client.FetchResult;
 import freenet.client.HighLevelSimpleClient;
 import freenet.client.InsertBlock;
+import freenet.client.InsertContext;
 import freenet.client.InsertException;
 import freenet.client.async.BaseClientPutter;
 import freenet.client.async.ClientCallback;
 import freenet.client.async.ClientGetter;
+import freenet.client.async.ClientPutter;
 import freenet.keys.FreenetURI;
 import freenet.node.RequestStarter;
 import freenet.support.Logger;
@@ -70,6 +72,9 @@
        private final IntroductionPuzzleFactory[] mPuzzleFactories = new 
IntroductionPuzzleFactory[] { new CaptchaFactory1() };
        
        private final ArrayList<ClientGetter> mRequests = new 
ArrayList<ClientGetter>(PUZZLE_COUNT * 5); /* Just assume that there are 5 
identities */
+       
+       private final ArrayList<ClientPutter> mInserts = new 
ArrayList<ClientPutter>(PUZZLE_COUNT * 5); /* Just assume that there are 5 
identities */
+       
 
        /**
         * Creates an IntroductionServer
@@ -122,6 +127,7 @@
                                }
                        }
                        db.commit();
+                       Logger.debug(this, "Introduction server loop 
finished.");
                        
                        try {
                                Thread.sleep((long) (THREAD_PERIOD * (0.5f + 
Math.random())));
@@ -131,14 +137,13 @@
                                mThread.interrupt();
                                Logger.debug(this, "Introduction server loop 
interrupted.");
                        }
-                       Logger.debug(this, "Introduction server loop 
finished.");
                }
                
                cancelRequests();
                Logger.debug(this, "Introduction server thread finished.");
        }
        
-       public synchronized void terminate() {
+       public void terminate() {
                Logger.debug(this, "Stopping the introduction server...");
                isRunning = false;
                mThread.interrupt();
@@ -153,11 +158,15 @@
        }
        
        private synchronized void cancelRequests() {
-               Iterator<ClientGetter> i = mRequests.iterator();
-               int counter = 0;
-               Logger.debug(this, "Trying to stop all requests"); 
-               while (i.hasNext()) { i.next().cancel(); ++counter; }
-               Logger.debug(this, "Stopped " + counter + " current requests");
+               Iterator<ClientGetter> r = mRequests.iterator();
+               Iterator<ClientPutter> i = mInserts.iterator();
+               int rcounter = 0;
+               int icounter = 0;
+               Logger.debug(this, "Trying to stop all requests & inserts"); 
+               while (r.hasNext()) { r.next().cancel(); ++rcounter; }
+               while (i.hasNext()) { i.next().cancel(); ++icounter; }
+               Logger.debug(this, "Stopped " + rcounter + " current requests");
+               Logger.debug(this, "Stopped " + icounter + " current inserts");
        }
                
        private synchronized void downloadSolutions(OwnIdentity identity) 
throws FetchException {
@@ -219,15 +228,17 @@
                                
                                        ClientMetadata cmd = new 
ClientMetadata("text/xml");
                                        InsertBlock ib = new InsertBlock(tempB, 
cmd, p.getInsertURI());
+                                       InsertContext ictx = 
mClient.getInsertContext(true);
+                                       
+                                       /* FIXME: are these parameters correct? 
*/
+                                       ClientPutter pu = mClient.insert(ib, 
false, null, false, ictx, this);
+                                       
pu.setPriorityClass(RequestStarter.UPDATE_PRIORITY_CLASS);
+                                       mInserts.add(pu);
+                                       tempB = null;
                
-                                       Logger.debug(this, "Started insert 
puzzle from " + identity.getNickName());
-               
-                                       /* FIXME: use nonblocking insert maybe 
*/
-                                       mClient.insert(ib, false, null);
-               
                                        db.store(p);
                                        db.commit();
-                                       Logger.debug(this, "Successful insert 
of puzzle from " + identity.getNickName() + ": " + p.getRequestURI());
+                                       Logger.debug(this, "Started insert of 
puzzle from " + identity.getNickName());
                                }
                                catch(InsertException e) {
                                        if(e.errorCodes.getFirstCode() == 
InsertException.COLLISION)
@@ -241,7 +252,8 @@
                        while(retryWithNewIndex);
                }
                finally {
-                       tempB.free();
+                       if(tempB != null)
+                               tempB.free();
                        if(os != null)
                                os.close();
                }
@@ -266,7 +278,7 @@
 
                try {
                        db.commit();
-                       IntroductionPuzzle p = 
IntroductionPuzzle.getBySolutionURI(db, state.getURI());
+                       IntroductionPuzzle p = IntroductionPuzzle.getByURI(db, 
state.getURI());
                        OwnIdentity puzzleOwner = (OwnIdentity)p.getInserter();
                        Identity newIdentity = 
Identity.importIntroductionFromXML(db, mIdentityFetcher, 
result.asBucket().getInputStream());
                        puzzleOwner.setTrust(db, newIdentity, (byte)0, null); 
/* FIXME: is 0 the proper trust for newly imported identities? */
@@ -281,14 +293,30 @@
                }
        }
        
-       /* Not needed functions from the ClientCallback inteface */
-       
        // Only called by inserts
-       public void onSuccess(BaseClientPutter state) {}
+       public synchronized void onSuccess(BaseClientPutter state)
+       {
+               try {
+                       IntroductionPuzzle p = IntroductionPuzzle.getByURI(db, 
state.getURI());
+                       Logger.debug(this, "Successful insert of puzzle from " 
+ p.getInserter().getNickName() + ": " + p.getRequestURI());
+               } catch(Exception e) { Logger.error(this, "Error", e); }
+               state.cancel(); /* FIXME: is this necessary */
+               mInserts.remove(state);
+       }
        
        // Only called by inserts
-       public void onFailure(InsertException e, BaseClientPutter state) {}
+       public synchronized void onFailure(InsertException e, BaseClientPutter 
state) 
+       {
+               try {
+                       IntroductionPuzzle p = IntroductionPuzzle.getByURI(db, 
state.getURI());
+                       Logger.debug(this, "Insert of puzzle failed from " + 
p.getInserter().getNickName() + ": " + p.getRequestURI(), e);
+               } catch(Exception ex) { Logger.error(this, "Error", e); }
+               state.cancel(); /* FIXME: is this necessary */
+               mInserts.remove(state);
+       }
 
+       /* Not needed functions from the ClientCallback inteface */
+       
        // Only called by inserts
        public void onFetchable(BaseClientPutter state) {}
 

_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to