Author: toad
Date: 2008-06-17 18:01:05 +0000 (Tue, 17 Jun 2008)
New Revision: 20408

Modified:
   branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java
   branches/db4o/freenet/src/freenet/node/fcp/ClientPut.java
   branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java
Log:
Almost fixed QueueToadlet

Modified: branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java    
2008-06-17 17:30:09 UTC (rev 20407)
+++ branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java    
2008-06-17 18:01:05 UTC (rev 20408)
@@ -26,8 +26,13 @@
 import java.util.LinkedList;
 import java.util.List;

+import com.db4o.ObjectContainer;
+
 import freenet.client.DefaultMIMETypes;
 import freenet.client.HighLevelSimpleClient;
+import freenet.client.MetadataUnresolvedException;
+import freenet.client.async.ClientContext;
+import freenet.client.async.DBJob;
 import freenet.keys.FreenetURI;
 import freenet.l10n.L10n;
 import freenet.node.NodeClientCore;
@@ -54,6 +59,7 @@
 import freenet.support.io.BucketTools;
 import freenet.support.io.Closer;
 import freenet.support.io.FileBucket;
+import freenet.support.io.NativeThread;

 public class QueueToadlet extends Toadlet implements RequestCompletionCallback 
{

@@ -202,7 +208,7 @@
                                String persistence = 
request.getPartAsString("persistence", 32);
                                String returnType = 
request.getPartAsString("return-type", 32);
                                try {
-                                       
fcp.makePersistentGlobalRequest(fetchURI, expectedMIMEType, persistence, 
returnType);
+                                       
fcp.makePersistentGlobalRequestBlocking(fetchURI, expectedMIMEType, 
persistence, returnType);
                                } catch (NotAllowedException e) {
                                        
this.writeError(L10n.getString("QueueToadlet.errorDToDisk"), 
L10n.getString("QueueToadlet.errorDToDiskConfig"), ctx);
                                        return;
@@ -212,14 +218,7 @@
                        } else if (request.isPartSet("change_priority")) {
                                String identifier = 
request.getPartAsString("identifier", MAX_IDENTIFIER_LENGTH);
                                short newPriority = 
Short.parseShort(request.getPartAsString("priority", 32));
-                               ClientRequest[] clientRequests = 
fcp.getGlobalRequests();
-loop:                          for (int requestIndex = 0, requestCount = 
clientRequests.length; requestIndex < requestCount; requestIndex++) {
-                                       ClientRequest clientRequest = 
clientRequests[requestIndex];
-                                       if 
(clientRequest.getIdentifier().equals(identifier)) {
-                                               
clientRequest.modifyRequest(null, newPriority); // no new ClientToken
-                                               break loop;
-                                       }
-                               }
+                               fcp.modifyGlobalRequestBlocking(identifier, 
null, newPriority);
                                writePermanentRedirect(ctx, "Done", "/queue/");
                                return;
                        } else if (request.getPartAsString("insert", 
128).length() > 0) {
@@ -253,11 +252,13 @@
                                /* copy bucket data */
                                Bucket copiedBucket = 
core.persistentEncryptedTempBucketFactory.makeBucket(file.getData().size());
                                BucketTools.copy(file.getData(), copiedBucket);
+                               final ClientPut clientPut;
                                try {
-                                       ClientPut clientPut = new 
ClientPut(fcp.getGlobalForeverClient(), insertURI, identifier, 
Integer.MAX_VALUE, RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS, 
ClientRequest.PERSIST_FOREVER, null, false, !compress, -1, 
ClientPutMessage.UPLOAD_FROM_DIRECT, null, file.getContentType(), copiedBucket, 
null, fnam, false);
-                                       clientPut.start();
+                                       clientPut = new 
ClientPut(fcp.getGlobalForeverClient(), insertURI, identifier, 
Integer.MAX_VALUE, RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS, 
ClientRequest.PERSIST_FOREVER, null, false, !compress, -1, 
ClientPutMessage.UPLOAD_FROM_DIRECT, null, file.getContentType(), copiedBucket, 
null, fnam, false, fcp);
                                } catch (IdentifierCollisionException e) {
-                                       e.printStackTrace();
+                                       Logger.error(this, "Cannot put same 
file twice in same millisecond");
+                                       writePermanentRedirect(ctx, "Done", 
"/queue/");
+                                       return;
                                } catch (NotAllowedException e) {
                                        
this.writeError(L10n.getString("QueueToadlet.errorAccessDenied"), 
L10n.getString("QueueToadlet.errorAccessDeniedFile", new String[]{ "file" }, 
new String[]{ file.getFilename() }), ctx);
                                        return;
@@ -267,7 +268,14 @@
                                } catch (MalformedURLException mue1) {
                                        
writeError(L10n.getString("QueueToadlet.errorInvalidURI"), 
L10n.getString("QueueToadlet.errorInvalidURIToU"), ctx);
                                        return;
+                               } catch (MetadataUnresolvedException e) {
+                                       Logger.error(this, "Unresolved metadata 
in starting insert from data uploaded from browser: "+e, e);
+                                       writePermanentRedirect(ctx, "Done", 
"/queue/");
+                                       return;
+                                       // FIXME should this be a proper 
localised message? It shouldn't happen... but we'd like to get reports if it 
does.
                                }
+                               if(clientPut != null)
+                                       fcp.startBlocking(clientPut);
                                writePermanentRedirect(ctx, "Done", "/queue/");
                                return;
                        } else if (request.isPartSet("insert-local-file")) {
@@ -289,12 +297,14 @@
                                String target = file.getName();
                                if(!furi.getKeyType().equals("CHK"))
                                        target = null;
+                               final ClientPut clientPut;
                                try {
-                                       ClientPut clientPut = new 
ClientPut(fcp.getGlobalClient(), furi, identifier, Integer.MAX_VALUE, 
RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS, ClientRequest.PERSIST_FOREVER, 
null, false, false, -1, ClientPutMessage.UPLOAD_FROM_DISK, file, contentType, 
new FileBucket(file, true, false, false, false, false), null, target, false);
+                                       clientPut = new 
ClientPut(fcp.getGlobalForeverClient(), furi, identifier, Integer.MAX_VALUE, 
RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS, ClientRequest.PERSIST_FOREVER, 
null, false, false, -1, ClientPutMessage.UPLOAD_FROM_DISK, file, contentType, 
new FileBucket(file, true, false, false, false, false), null, target, false, 
fcp);
                                        if(logMINOR) Logger.minor(this, 
"Started global request to insert "+file+" to CHK@ as "+identifier);
-                                       clientPut.start();
                                } catch (IdentifierCollisionException e) {
-                                       e.printStackTrace();
+                                       Logger.error(this, "Cannot put same 
file twice in same millisecond");
+                                       writePermanentRedirect(ctx, "Done", 
"/queue/");
+                                       return;
                                } catch (MalformedURLException e) {
                                        
writeError(L10n.getString("QueueToadlet.errorInvalidURI"), 
L10n.getString("QueueToadlet.errorInvalidURIToU"), ctx);
                                        return;
@@ -304,7 +314,13 @@
                                } catch (NotAllowedException e) {
                                        
this.writeError(L10n.getString("QueueToadlet.errorAccessDenied"), 
L10n.getString("QueueToadlet.errorAccessDeniedFile", new String[]{ "file" }, 
new String[]{ file.getName() }), ctx);
                                        return;
+                               } catch (MetadataUnresolvedException e) {
+                                       Logger.error(this, "Unresolved metadata 
in starting insert from data from file: "+e, e);
+                                       writePermanentRedirect(ctx, "Done", 
"/queue/");
+                                       return;
+                                       // FIXME should this be a proper 
localised message? It shouldn't happen... but we'd like to get reports if it 
does.
                                }
+                               fcp.startBlocking(clientPut);
                                writePermanentRedirect(ctx, "Done", "/queue/");
                                return;
                        } else if (request.isPartSet("insert-local-dir")) {
@@ -322,12 +338,14 @@
                                                return;
                                        }
                                }
+                               ClientPutDir clientPutDir;
                                try {
-                                       ClientPutDir clientPutDir = new 
ClientPutDir(fcp.getGlobalClient(), furi, identifier, Integer.MAX_VALUE, 
RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS, ClientRequest.PERSIST_FOREVER, 
null, false, false, -1, file, null, false, true, false);
+                                       clientPutDir = new 
ClientPutDir(fcp.getGlobalForeverClient(), furi, identifier, Integer.MAX_VALUE, 
RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS, ClientRequest.PERSIST_FOREVER, 
null, false, false, -1, file, null, false, true, false, fcp);
                                        if(logMINOR) Logger.minor(this, 
"Started global request to insert dir "+file+" to "+furi+" as "+identifier);
-                                       clientPutDir.start();
                                } catch (IdentifierCollisionException e) {
-                                       e.printStackTrace();
+                                       Logger.error(this, "Cannot put same 
directory twice in same millisecond");
+                                       writePermanentRedirect(ctx, "Done", 
"/queue/");
+                                       return;
                                } catch (MalformedURLException e) {
                                        
writeError(L10n.getString("QueueToadlet.errorInvalidURI"), 
L10n.getString("QueueToadlet.errorInvalidURIToU"), ctx);
                                        return;
@@ -335,6 +353,7 @@
                                        
this.writeError(L10n.getString("QueueToadlet.errorNoFileOrCannotRead"), 
L10n.getString("QueueToadlet.errorAccessDeniedFile", new String[]{ "file" }, 
new String[]{ file.toString() }), ctx);
                                        return;
                                }
+                               fcp.startBlocking(clientPutDir);
                                writePermanentRedirect(ctx, "Done", "/queue/");
                                return;
                        } else if (request.isPartSet("get")) {

Modified: branches/db4o/freenet/src/freenet/node/fcp/ClientPut.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/ClientPut.java   2008-06-17 
17:30:09 UTC (rev 20407)
+++ branches/db4o/freenet/src/freenet/node/fcp/ClientPut.java   2008-06-17 
18:01:05 UTC (rev 20408)
@@ -97,12 +97,13 @@
         * @throws NotAllowedException 
         * @throws FileNotFoundException 
         * @throws MalformedURLException 
+        * @throws MetadataUnresolvedException 
         * @throws InsertException 
         */
        public ClientPut(FCPClient globalClient, FreenetURI uri, String 
identifier, int verbosity, 
                        short priorityClass, short persistenceType, String 
clientToken, boolean getCHKOnly,
                        boolean dontCompress, int maxRetries, short 
uploadFromType, File origFilename, String contentType,
-                       Bucket data, FreenetURI redirectTarget, String 
targetFilename, boolean earlyEncode, FCPServer server) throws 
IdentifierCollisionException, NotAllowedException, FileNotFoundException, 
MalformedURLException, InsertException {
+                       Bucket data, FreenetURI redirectTarget, String 
targetFilename, boolean earlyEncode, FCPServer server) throws 
IdentifierCollisionException, NotAllowedException, FileNotFoundException, 
MalformedURLException, MetadataUnresolvedException {
                super(uri, identifier, verbosity, null, globalClient, 
priorityClass, persistenceType, null, true, getCHKOnly, dontCompress, 
maxRetries, earlyEncode, server);
                if(uploadFromType == ClientPutMessage.UPLOAD_FROM_DISK) {
                        if(!server.core.allowUploadFrom(origFilename))
@@ -128,16 +129,7 @@
                        this.targetURI = redirectTarget;
                        Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
targetURI, cm);
                        byte[] d;
-                       try {
-                               d = m.writeToByteArray();
-                       } catch (MetadataUnresolvedException e) {
-                               // Impossible
-                               Logger.error(this, "Impossible: "+e, e);
-                               this.data = null;
-                               clientMetadata = cm;
-                               putter = null;
-                               throw new 
InsertException(InsertException.INTERNAL_ERROR, "Impossible: "+e+" in 
ClientPut", null);
-                       }
+                       d = m.writeToByteArray();
                        tempData = new SimpleReadOnlyArrayBucket(d);
                        isMetadata = true;
                } else

Modified: branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java   2008-06-17 
17:30:09 UTC (rev 20407)
+++ branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java   2008-06-17 
18:01:05 UTC (rev 20408)
@@ -644,6 +644,103 @@
                }
        }

+       public void makePersistentGlobalRequestBlocking(final FreenetURI 
fetchURI, final String expectedMimeType, final String persistenceTypeString, 
final String returnTypeString) throws NotAllowedException, IOException {
+               class OutputWrapper {
+                       NotAllowedException ne;
+                       IOException ioe;
+                       boolean done;
+               }
+               
+               final OutputWrapper ow = new OutputWrapper();
+               core.clientContext.jobRunner.queue(new DBJob() {
+
+                       public void run(ObjectContainer container, 
ClientContext context) {
+                               NotAllowedException ne = null;
+                               IOException ioe = null;
+                               try {
+                                       makePersistentGlobalRequest(fetchURI, 
expectedMimeType, persistenceTypeString, returnTypeString, container);
+                               } catch (NotAllowedException e) {
+                                       ne = e;
+                               } catch (IOException e) {
+                                       ioe = e;
+                               } catch (Throwable t) {
+                                       // Unexpected and severe, might even be 
OOM, just log it.
+                                       Logger.error(this, "Failed to make 
persistent request: "+t, t);
+                               } finally {
+                                       synchronized(ow) {
+                                               ow.ne = ne;
+                                               ow.ioe = ioe;
+                                               ow.done = true;
+                                               ow.notifyAll();
+                                       }
+                               }
+                       }
+                       
+               }, NativeThread.HIGH_PRIORITY, false);
+               
+               synchronized(ow) {
+                       while(true) {
+                               if(!ow.done) {
+                                       try {
+                                               ow.wait();
+                                       } catch (InterruptedException e) {
+                                               // Ignore
+                                       }
+                                       continue;
+                               }
+                               if(ow.ioe != null) throw ow.ioe;
+                               if(ow.ne != null) throw ow.ne;
+                               return;
+                       }
+               }
+       }
+       
+       public boolean modifyGlobalRequestBlocking(final String identifier, 
final String newToken, final short newPriority) {
+               ClientRequest req = 
this.globalRebootClient.getRequest(identifier, null);
+               if(req != null) {
+                       req.modifyRequest(newToken, newPriority, this, null);
+                       return true;
+               } else {
+                       class OutputWrapper {
+                               boolean success;
+                               boolean done;
+                       }
+                       final OutputWrapper ow = new OutputWrapper();
+                       core.clientContext.jobRunner.queue(new DBJob() {
+
+                               public void run(ObjectContainer container, 
ClientContext context) {
+                                       boolean success = false;
+                                       try {
+                                               ClientRequest req = 
globalForeverClient.getRequest(identifier, container);
+                                               if(req != null)
+                                                       
req.modifyRequest(newToken, newPriority, FCPServer.this, container);
+                                       } finally {
+                                               synchronized(ow) {
+                                                       ow.success = success;
+                                                       ow.done = true;
+                                                       ow.notifyAll();
+                                               }
+                                       }
+                               }
+                               
+                       }, NativeThread.HIGH_PRIORITY, false);
+                       
+                       synchronized(ow) {
+                               while(true) {
+                                       if(!ow.done) {
+                                               try {
+                                                       ow.wait();
+                                               } catch (InterruptedException 
e) {
+                                                       // Ignore
+                                               }
+                                               continue;
+                                       }
+                                       return ow.success;
+                               }
+                       }
+               }
+       }
+       
        /**
         * Create a persistent globally-queued request for a file.
         * @param fetchURI The file to fetch.
@@ -794,5 +891,44 @@
                if(globalRebootClient.setRequestCompletionCallback(cb) != null)
                        Logger.error(this, "Replacing request completion 
callback "+cb, new Exception("error"));
        }
-       
+
+       public void startBlocking(final ClientRequest req) {
+               if(req.persistenceType == ClientRequest.PERSIST_REBOOT) {
+                       req.start(null, core.clientContext);
+               } else {
+                       class OutputWrapper {
+                               boolean done;
+                       }
+                       final OutputWrapper ow = new OutputWrapper();
+                       core.clientContext.jobRunner.queue(new DBJob() {
+                               
+                               public void run(ObjectContainer container, 
ClientContext context) {
+                                       try {
+                                               req.start(container, context);
+                                       } finally {
+                                               synchronized(ow) {
+                                                       ow.done = true;
+                                                       ow.notifyAll();
+                                               }
+                                       }
+                               }
+                               
+                       }, NativeThread.HIGH_PRIORITY, false);
+                       
+                       synchronized(ow) {
+                               while(true) {
+                                       if(!ow.done) {
+                                               try {
+                                                       ow.wait();
+                                               } catch (InterruptedException 
e) {
+                                                       // Ignore
+                                               }
+                                       } else {
+                                               return;
+                                       }
+                               }
+                       }
+               }
+       }
+
 }


Reply via email to