Package plugins.Freetalk

Source Code of plugins.Freetalk.PluginTalkerBlocking

/* 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 plugins.Freetalk;

import freenet.pluginmanager.FredPluginTalker;
import freenet.pluginmanager.PluginNotFoundException;
import freenet.pluginmanager.PluginRespirator;
import freenet.pluginmanager.PluginTalker;
import freenet.support.Logger;
import freenet.support.SimpleFieldSet;
import freenet.support.api.Bucket;

public class PluginTalkerBlocking implements FredPluginTalker {
 
  /**
   * Timeout when waiting for FCP replies from WoT. This is set to a very high value because nodes which are under very heavy load sometimes cause
   * the FCP thread to stall for very long times...
   */
  public static final long TIMEOUT = 10 * 60 * 1000;
 
  private PluginTalker mTalker;
 
  private final Object mLock = new Object();
 
  private volatile boolean mWaitingForResult = false;
       
  private volatile Result mResult = null;

  public static class Result {
    final public SimpleFieldSet params;
    final public Bucket data;

    Result(SimpleFieldSet myParams, Bucket myData) {
      params = myParams;
      data = myData;
    }
  };

  public PluginTalkerBlocking(PluginRespirator myPR) throws PluginNotFoundException {
    mTalker = myPR.getPluginTalker(this, Freetalk.WOT_PLUGIN_NAME, Freetalk.PLUGIN_TITLE);
  }

  /**
   * Sends a FCP message and blocks execution until the answer was received and then returns the answer.
   * This can be used to simplify code which uses FCP very much, especially UI code which needs the result of FCP calls directly.
   *
   * When using sendBlocking(), please make sure that you only ever call it for FCP functions which only send() a single result!
   */
  public synchronized Result sendBlocking(SimpleFieldSet params, Bucket data) throws PluginNotFoundException {
    assert(mResult == null);
    assert(mWaitingForResult == false);
   
    // The "synchronized" prefix of sendBlocking ensures that only 1 send is running at once. This is necessary because the onReply will not receive
    // any information which could be used to tell to WHICH request the reply belongs.
   
    // We must synchronize on a different lock here: If we used the same lock which locks the entrance of sendBlocking(), onReply would call notifyAll()
    // which would NOT wake up threads which are in wait() first, it might as well wake up another thread which is waiting to enter sendBlocking.
    // This would cause another request to be sent while the sendBlocking() of the first request was not finished, the resulting call to onReply() could
    // overwrite the result of the first request with the result of the second one. Therefore, sendBlocking would return the wrong result.
    // So we must use two different locks: One for enforcing "one request at once" and one for wait/notifyAll.
   
    synchronized(mLock) {
      mResult = null;
      mWaitingForResult = true;
      mTalker.send(params, data);

      long startTime = System.currentTimeMillis();

      while (mResult == null) {
        try {
          mLock.wait(TIMEOUT);
        } catch (InterruptedException e) {
        }

        if(mResult == null && (System.currentTimeMillis() - startTime) >= TIMEOUT) {
          mWaitingForResult = false;
          throw new PluginNotFoundException("Timeout while waiting for reply from target plugin, message was: " + params);
        }
      }

      Result result = mResult;
      mWaitingForResult = false;
      mResult = null;
      return result;
    }
  }

 
  public void onReply(String pluginname, String indentifier, SimpleFieldSet params, Bucket data) {
   
    // TODO: This has one more synchronization issue: If an old request times out and it's sendBlocking throws an exception therefore,
    // the next call to sendBlocking might receive the late answer to the previous call as reply - that is the wrong reply!
    // What is lacking in the FCP design is a unique ID for each request.
    // I'm marking this as TO-DO and not as FIX-ME because timeouts should only happen when something is wrong anyway.
   
    synchronized(mLock) { // Synchronized for notifyAll()
      if(!mWaitingForResult) {
        Logger.error(this, "sendBlocking() received onReply too late: " + params);
        return;
      }

      if(mResult != null) {
        Logger.error(this, "sendBlocking() called for a FCP function which sends more than 1 reply, second reply was: " + params);
        return;
      }

      mResult = new Result(params, data);
      mLock.notifyAll();
    }
  }
}
TOP

Related Classes of plugins.Freetalk.PluginTalkerBlocking

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
y/mvc/web/support/ParamMetaInfo.html" title="Examples of com.firefly.mvc.web.support.ParamMetaInfo">com.firefly.mvc.web.support.ParamMetaInfo
  • com.foundationdb.server.types.InputSetFlags
  • com.google.checkout.sample.protocol.MerchantCalculationResultBuilder
  • com.google.gwt.dev.jjs.ast.JDeclaredType
  • com.google.gwt.dev.jjs.ast.JField
  • TOP
    Copyright © 2018 www.massapi.com. All rights reserved.
    All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.