On Monday 16 March 2009 09:11:03 Daniel Cheng wrote: > On Mon, Mar 16, 2009 at 2:51 PM, xor <[email protected]> wrote: > > > > > >> -----Original Message----- > >> From: [email protected] > >> [mailto:[email protected]] On Behalf Of Daniel Cheng > >> Sent: Monday, March 16, 2009 1:19 AM > >> To: [email protected] > >> Subject: Re: [freenet-dev] [freenet-cvs] r26044 > >> -trunk/freenet/src/freenet/pluginmanager > >> > >> On Sun, Mar 15, 2009 at 11:35 PM, <[email protected]> wrote: > >> > Author: xor > >> > Date: 2009-03-15 15:35:03 +0000 (Sun, 15 Mar 2009) New > >> Revision: 26044 > >> > > >> > Added: > >> > trunk/freenet/src/freenet/pluginmanager/PluginTalkerBlocking.java > >> > Modified: > >> > trunk/freenet/src/freenet/pluginmanager/PluginTalker.java > >> > Log: > >> > Implement a blocking PluginTalker. This is to be used if > >> the result of a FCP call is needed by the caller directly, > >> i.e. in UI functions. For example, when creating an identity > >> using the Freetalk web interface, we need to show the user > >> directly whether the attempt to create it was successful. > >> > > >> > Modified: trunk/freenet/src/freenet/pluginmanager/PluginTalker.java > >> > =================================================================== > >> > --- trunk/freenet/src/freenet/pluginmanager/PluginTalker.java > >> > 2009-03-14 16:03:52 UTC (rev 26043) > >> > +++ trunk/freenet/src/freenet/pluginmanager/PluginTalker.java > >> > +++ 2009-03-15 15:35:03 UTC (rev 26044) > >> > @@ -15,15 +15,19 @@ > >> > */ > >> > public class PluginTalker { > >> > > >> > - Node node; > >> > - private PluginReplySender replysender; > >> > + protected Node node; > >> > + protected PluginReplySender replysender; > >> > > >> > - private int access; > >> > + protected int access; > >> > > >> > - FredPluginFCP plugin; > >> > + protected FredPluginFCP plugin; > >> > + protected String pluginName; > >> > + protected String connectionIdentifier; > >> > > >> > - PluginTalker(FredPluginTalker fpt, Node node2, String > >> > pluginname2, String identifier2) throws PluginNotFoundException { > >> > + public PluginTalker(FredPluginTalker fpt, Node > >> node2, String > >> > + pluginname2, String identifier2) throws PluginNotFoundException { > >> > node = node2; > >> > + pluginName = pluginname2; > >> > + connectionIdentifier = identifier2; > >> > plugin = findPlugin(pluginname2); > >> > access = FredPluginFCP.ACCESS_DIRECT; > >> > replysender = new > >> PluginReplySenderDirect(node2, fpt, > >> > pluginname2, identifier2); @@ -31,12 +35,14 @@ > >> > > >> > public PluginTalker(Node node2, FCPConnectionHandler > >> handler, > >> > String pluginname2, String identifier2, boolean access2) throws > >> > PluginNotFoundException { > >> > node = node2; > >> > + pluginName = pluginname2; > >> > + connectionIdentifier = identifier2; > >> > plugin = findPlugin(pluginname2); > >> > access = access2 ? FredPluginFCP.ACCESS_FCP_FULL : > >> > FredPluginFCP.ACCESS_FCP_RESTRICTED; > >> > replysender = new PluginReplySenderFCP(handler, > >> > pluginname2, identifier2); > >> > } > >> > > >> > - private FredPluginFCP findPlugin(String pluginname2) throws > >> > PluginNotFoundException { > >> > + protected FredPluginFCP findPlugin(String > >> pluginname2) throws > >> > + PluginNotFoundException { > >> > > >> > Logger.normal(this, "Searching fcp plugin: " + > >> > pluginname2); > >> > FredPluginFCP plug = > >> > node.pluginManager.getFCPPlugin(pluginname2); > >> > > >> > Added: > >> > trunk/freenet/src/freenet/pluginmanager/PluginTalkerBlocking.java > >> > =================================================================== > >> > --- > >> trunk/freenet/src/freenet/pluginmanager/PluginTalkerBlocking.j > >> ava > >> > (rev 0) > >> > +++ > >> trunk/freenet/src/freenet/pluginmanager/PluginTalkerBlocking.java > >> > +++ 2009-03-15 15:35:03 UTC (rev 26044) > >> > @@ -0,0 +1,93 @@ > >> > +/* 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.pluginmanager; > >> > + > >> > +import freenet.node.Node; > >> > +import freenet.support.Logger; > >> > +import freenet.support.SimpleFieldSet; import > >> > +freenet.support.api.Bucket; > >> > + > >> > +/** > >> > + * A PluginTalker which has a sendBlocking() function > >> which directly returns the result of the FCP call to the caller. > >> > + * This can be used to simplify code which uses FCP very > >> much, especially UI code which needs the result of FCP calls directly. > >> > + * > >> > + * @author xor > >> > + */ > >> > +public class PluginTalkerBlocking extends PluginTalker { > >> > + > >> > + public PluginTalkerBlocking(FredPluginTalker > >> myPluginTalker, > >> > + Node myNode, String myPluginName, String myConnectionIdentifier) > >> > + throws PluginNotFoundException { > >> > + super(myPluginTalker, myNode, myPluginName, > >> > + myConnectionIdentifier); > >> > + // TODO Auto-generated constructor stub > >> > + } > >> > + > >> > + public static class Result { > >> > + public SimpleFieldSet params; > >> > + public Bucket data; > >> > + > >> > + public Result(SimpleFieldSet myParams, > >> Bucket myData) > >> > + { > >> > + params = myParams; > >> > + data = myData; > >> > + } > >> > + } > >> > + > >> > + protected class PluginReplySenderBlocking extends > >> > + PluginReplySender { > >> > + > >> > + protected final PluginReplySender > >> > + nonBlockingReplySender; > >> > + protected volatile Result mResult; > >> > + > >> > + public PluginReplySenderBlocking() { > >> > + super(pluginName, connectionIdentifier); > >> > + nonBlockingReplySender = replysender; > >> > + } > >> > + > >> > + @Override > >> > + public synchronized void > >> send(SimpleFieldSet params, > >> > + Bucket bucket) { > >> > + if(mResult == null) { > >> > + mResult = new > >> Result(params, bucket); > >> > + notifyAll(); > >> > + } else { > >> > + Logger.error(this, > >> > + "PluginTalkerBlocking is being used with a FCP call which > >> results in > >> > + more than 1 reply"); > >> > + nonBlockingReplySender.send(params, > >> > + bucket); > >> > + } > >> > >> If the user ask for blocking, throw a exception if it can't. > >> Don't fallback to async -- the client asked for blocking for a reason. > > > > The exception unfortunately could not be thrown to the caller of > > sendBlocking() because it is the plugin which receives the message which > > calls send() twice or more and after the first send(), the "Result"-object > > is returned to the caller of sendBlocking(), so when the plugin calls send() > > a second time, sendBlocking() will already have returned. > > > > Would it be useful to throw the exception at the plugin? I do not think so. > > It is legal in FCP to call send() more than once when handling a FCP > > message, isn't it? > > The real question is : Who need blocking send, and why? > > If we *really* have to do it synchronously, we should have notify the > the caller. > If not, why bother to write this at all? > > >> > >> > + } > >> > + > >> > + public Result getResult() { > >> > + while(mResult == null) { > >> > + try { > >> > + wait(); > >> > >> this would throw Illegal Monitor State Exception make it synchronized, > >> > >> > + } catch (InterruptedException e) { > >> > + } > >> > + } > >> > + > >> > + return mResult; > >> > + } > >> > + > >> > + } > >> > + > >> > + /** > >> > + * When using sendBlocking(), please make sure that > >> you only ever call it for FCP functions which only send() a > >> single result! > >> > + * Results which are sent by the plugin after the > >> first result > >> > + are dispatched to the asynchronous onReply() function of your > >> > + * FredPluginTalker, however this behavior is > >> deprecated and not guranteed to work. > >> > + */ > >> > + public Result sendBlocking(final SimpleFieldSet plugparams, > >> > + final Bucket data2) { > >> > + final PluginReplySenderBlocking replySender = new > >> > + PluginReplySenderBlocking(); > >> > + > >> > + node.executor.execute(new Runnable() { > >> > + > >> > >> Why spawn a thread, if all you want is blocking behaviour? > > > > Hmmmm yea this is right, it doesn't really make sense. The code was > > copy-pasted from the non-blocking version, thats the reason. > > I am just wondering right now whether it still might make sense to execute > > it in a separate thread... well, it would allow us to give the caller of > > sendBlocking() a timeout value. Further, we wouldn't be mixing the execution > > of plugins into single threads, each thread would clearly belong to one > > plugin - I don't know whether this has any more advantages than feeling more > > clean? > > With this addition, > our executor things have grow to (almost) the same complexity of > java.until.concurrent.ExecutorService ... > > The Future / Callable interface may look strange at the first look, > but it is designed by the Doug Lea (*THE* java thread and memory model > guy) with maximum performance and least need or manual > synchronization.. > > The blocking + timeout in java.util.concurrent.ExecurorService is: > > Future<Result> ft = executor.submit( callable ); > Result r = ft.get( timeout , TimeUnit.SECOND ); > if (r != null ) > .... > > Please have a look at it. > If you can live with that interface, I will port > freenet.support.Executor to use them.
Being able to set thread priorities is critical, please make sure that we retain this ability...
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Devl mailing list [email protected] http://emu.freenetproject.org/cgi-bin/mailman/listinfo/devl
