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.
--
_______________________________________________
Devl mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/devl