Package freenet.node

Source Code of freenet.node.RequestStarterGroup$PrioritySchedulerCallback

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

import static java.util.concurrent.TimeUnit.MINUTES;

import freenet.client.async.ClientContext;
import freenet.client.async.ClientRequestScheduler;
import freenet.config.Config;
import freenet.config.EnumerableOptionCallback;
import freenet.config.InvalidConfigValueException;
import freenet.config.SubConfig;
import freenet.crypt.RandomSource;
import freenet.keys.Key;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.SimpleFieldSet;
import freenet.support.TimeUtil;
import freenet.support.Logger.LogLevel;
import freenet.support.api.StringCallback;
import freenet.support.math.BootstrappingDecayingRunningAverage;

public class RequestStarterGroup {
  private static volatile boolean logMINOR;

  static {
    Logger.registerLogThresholdCallback(new LogThresholdCallback(){
      @Override
      public void shouldUpdate(){
        logMINOR = Logger.shouldLog(LogLevel.MINOR, this);
      }
    });
  }

  private final ThrottleWindowManager throttleWindowBulk;
  private final ThrottleWindowManager throttleWindowRT;
  // These are for diagnostic purposes
  private final ThrottleWindowManager throttleWindowCHK;
  private final ThrottleWindowManager throttleWindowSSK;
  private final ThrottleWindowManager throttleWindowInsert;
  private final ThrottleWindowManager throttleWindowRequest;
  final MyRequestThrottle chkRequestThrottleBulk;
  final RequestStarter chkRequestStarterBulk;
  final MyRequestThrottle chkInsertThrottleBulk;
  final RequestStarter chkInsertStarterBulk;
  final MyRequestThrottle sskRequestThrottleBulk;
  final RequestStarter sskRequestStarterBulk;
  final MyRequestThrottle sskInsertThrottleBulk;
  final RequestStarter sskInsertStarterBulk;
 
  final MyRequestThrottle chkRequestThrottleRT;
  final RequestStarter chkRequestStarterRT;
  final MyRequestThrottle chkInsertThrottleRT;
  final RequestStarter chkInsertStarterRT;
  final MyRequestThrottle sskRequestThrottleRT;
  final RequestStarter sskRequestStarterRT;
  final MyRequestThrottle sskInsertThrottleRT;
  final RequestStarter sskInsertStarterRT;

  public final ClientRequestScheduler chkFetchSchedulerBulk;
  public final ClientRequestScheduler chkPutSchedulerBulk;
  public final ClientRequestScheduler sskFetchSchedulerBulk;
  public final ClientRequestScheduler sskPutSchedulerBulk;
  public final ClientRequestScheduler chkFetchSchedulerRT;
  public final ClientRequestScheduler chkPutSchedulerRT;
  public final ClientRequestScheduler sskFetchSchedulerRT;
  public final ClientRequestScheduler sskPutSchedulerRT;

  private final NodeStats stats;
  RequestStarterGroup(Node node, NodeClientCore core, int portNumber, RandomSource random, Config config, SimpleFieldSet fs, ClientContext ctx, long dbHandle) throws InvalidConfigValueException {
    SubConfig schedulerConfig = new SubConfig("node.scheduler", config);
    this.stats = core.nodeStats;
   
    throttleWindowBulk = new ThrottleWindowManager(2.0, fs == null ? null : fs.subset("ThrottleWindow"), node);
    throttleWindowRT = new ThrottleWindowManager(2.0, fs == null ? null : fs.subset("ThrottleWindowRT"), node);
   
    throttleWindowCHK = new ThrottleWindowManager(2.0, fs == null ? null : fs.subset("ThrottleWindowCHK"), node);
    throttleWindowSSK = new ThrottleWindowManager(2.0, fs == null ? null : fs.subset("ThrottleWindowSSK"), node);
    throttleWindowInsert = new ThrottleWindowManager(2.0, fs == null ? null : fs.subset("ThrottleWindowInsert"), node);
    throttleWindowRequest = new ThrottleWindowManager(2.0, fs == null ? null : fs.subset("ThrottleWindowRequest"), node);
    chkRequestThrottleBulk = new MyRequestThrottle(5000, "CHK Request", fs == null ? null : fs.subset("CHKRequestThrottle"), 32768, false);
    chkRequestThrottleRT = new MyRequestThrottle(5000, "CHK Request (RT)", fs == null ? null : fs.subset("CHKRequestThrottleRT"), 32768, true);
    chkRequestStarterBulk = new RequestStarter(core, chkRequestThrottleBulk, "CHK Request starter ("+portNumber+ ')', stats.requestOutputThrottle, stats.requestInputThrottle, stats.localChkFetchBytesSentAverage, stats.localChkFetchBytesReceivedAverage, false, false, false);
    chkRequestStarterRT = new RequestStarter(core, chkRequestThrottleRT, "CHK Request starter ("+portNumber+ ')', stats.requestOutputThrottle, stats.requestInputThrottle, stats.localChkFetchBytesSentAverage, stats.localChkFetchBytesReceivedAverage, false, false, true);
    chkFetchSchedulerBulk = new ClientRequestScheduler(false, false, false, random, chkRequestStarterBulk, node, core, "CHKrequester", ctx);
    chkFetchSchedulerRT = new ClientRequestScheduler(false, false, true, random, chkRequestStarterRT, node, core, "CHKrequester", ctx);
    chkRequestStarterBulk.setScheduler(chkFetchSchedulerBulk);
    chkRequestStarterRT.setScheduler(chkFetchSchedulerRT);
   
    registerSchedulerConfig(schedulerConfig, "CHKrequester", chkFetchSchedulerBulk, chkFetchSchedulerRT, false, false);
   
    //insertThrottle = new ChainedRequestThrottle(10000, 2.0F, requestThrottle);
    // FIXME reenable the above
    chkInsertThrottleBulk = new MyRequestThrottle(20000, "CHK Insert", fs == null ? null : fs.subset("CHKInsertThrottle"), 32768, false);
    chkInsertThrottleRT = new MyRequestThrottle(20000, "CHK Insert (RT)", fs == null ? null : fs.subset("CHKInsertThrottleRT"), 32768, true);
    chkInsertStarterBulk = new RequestStarter(core, chkInsertThrottleBulk, "CHK Insert starter ("+portNumber+ ')', stats.requestOutputThrottle, stats.requestInputThrottle, stats.localChkInsertBytesSentAverage, stats.localChkInsertBytesReceivedAverage, true, false, false);
    chkInsertStarterRT = new RequestStarter(core, chkInsertThrottleRT, "CHK Insert starter ("+portNumber+ ')', stats.requestOutputThrottle, stats.requestInputThrottle, stats.localChkInsertBytesSentAverage, stats.localChkInsertBytesReceivedAverage, true, false, true);
    chkPutSchedulerBulk = new ClientRequestScheduler(true, false, false, random, chkInsertStarterBulk, node, core, "CHKinserter", ctx);
    chkPutSchedulerRT = new ClientRequestScheduler(true, false, true, random, chkInsertStarterRT, node, core, "CHKinserter", ctx);
    chkInsertStarterBulk.setScheduler(chkPutSchedulerBulk);
    chkInsertStarterRT.setScheduler(chkPutSchedulerRT);
   
    registerSchedulerConfig(schedulerConfig, "CHKinserter", chkPutSchedulerBulk, chkPutSchedulerRT, false, true);
   
    sskRequestThrottleBulk = new MyRequestThrottle(5000, "SSK Request", fs == null ? null : fs.subset("SSKRequestThrottle"), 1024, false);
    sskRequestThrottleRT = new MyRequestThrottle(5000, "SSK Request (RT)", fs == null ? null : fs.subset("SSKRequestThrottleRT"), 1024, true);
    sskRequestStarterBulk = new RequestStarter(core, sskRequestThrottleBulk, "SSK Request starter ("+portNumber+ ')', stats.requestOutputThrottle, stats.requestInputThrottle, stats.localSskFetchBytesSentAverage, stats.localSskFetchBytesReceivedAverage, false, true, false);
    sskRequestStarterRT = new RequestStarter(core, sskRequestThrottleRT, "SSK Request starter ("+portNumber+ ')', stats.requestOutputThrottle, stats.requestInputThrottle, stats.localSskFetchBytesSentAverage, stats.localSskFetchBytesReceivedAverage, false, true, true);
    sskFetchSchedulerBulk = new ClientRequestScheduler(false, true, false, random, sskRequestStarterBulk, node, core, "SSKrequester", ctx);
    sskFetchSchedulerRT = new ClientRequestScheduler(false, true, true, random, sskRequestStarterRT, node, core, "SSKrequester", ctx);
    sskRequestStarterBulk.setScheduler(sskFetchSchedulerBulk);
    sskRequestStarterRT.setScheduler(sskFetchSchedulerRT);
   
    registerSchedulerConfig(schedulerConfig, "SSKrequester", sskFetchSchedulerBulk, sskFetchSchedulerRT, true, false);
   
    //insertThrottle = new ChainedRequestThrottle(10000, 2.0F, requestThrottle);
    // FIXME reenable the above
    sskInsertThrottleBulk = new MyRequestThrottle(20000, "SSK Insert", fs == null ? null : fs.subset("SSKInsertThrottle"), 1024, false);
    sskInsertThrottleRT = new MyRequestThrottle(20000, "SSK Insert", fs == null ? null : fs.subset("SSKInsertThrottleRT"), 1024, true);
    sskInsertStarterBulk = new RequestStarter(core, sskInsertThrottleBulk, "SSK Insert starter ("+portNumber+ ')', stats.requestOutputThrottle, stats.requestInputThrottle, stats.localSskInsertBytesSentAverage, stats.localSskFetchBytesReceivedAverage, true, true, false);
    sskInsertStarterRT = new RequestStarter(core, sskInsertThrottleRT, "SSK Insert starter ("+portNumber+ ')', stats.requestOutputThrottle, stats.requestInputThrottle, stats.localSskInsertBytesSentAverage, stats.localSskFetchBytesReceivedAverage, true, true, true);
    sskPutSchedulerBulk = new ClientRequestScheduler(true, true, false, random, sskInsertStarterBulk, node, core, "SSKinserter", ctx);
    sskPutSchedulerRT = new ClientRequestScheduler(true, true, true, random, sskInsertStarterRT, node, core, "SSKinserter", ctx);
    sskInsertStarterBulk.setScheduler(sskPutSchedulerBulk);
    sskInsertStarterRT.setScheduler(sskPutSchedulerRT);
   
    registerSchedulerConfig(schedulerConfig, "SSKinserter", sskPutSchedulerBulk, sskPutSchedulerRT, true, true);
   
    schedulerConfig.finishedInitialization();
  }
 
  private void registerSchedulerConfig(SubConfig schedulerConfig,
      String name, ClientRequestScheduler csBulk,
      ClientRequestScheduler csRT, boolean forSSKs, boolean forInserts) throws InvalidConfigValueException {
    PrioritySchedulerCallback callback = new PrioritySchedulerCallback();
    schedulerConfig.register(name+"_priority_policy", ClientRequestScheduler.PRIORITY_SOFT, name.hashCode(), true, false,
        "RequestStarterGroup.scheduler"+(forSSKs?"SSK" : "CHK")+(forInserts?"Inserts":"Requests"),
        "RequestStarterGroup.schedulerLong",
        callback);
    callback.init(csRT, csBulk, schedulerConfig.getString(name+"_priority_policy"));
  }

  public void start() {
    chkRequestStarterRT.start();
    chkInsertStarterRT.start();
    sskRequestStarterRT.start();
    sskInsertStarterRT.start();
    chkRequestStarterBulk.start();
    chkInsertStarterBulk.start();
    sskRequestStarterBulk.start();
    sskInsertStarterBulk.start();
  }
 
  public class MyRequestThrottle implements BaseRequestThrottle {
    private final BootstrappingDecayingRunningAverage roundTripTime;
    /** Data size for purposes of getRate() */
    private final int size;
    private final boolean realTime;

    public MyRequestThrottle(int rtt, String string, SimpleFieldSet fs, int size, boolean realTime) {
      roundTripTime = new BootstrappingDecayingRunningAverage(rtt, 10, MINUTES.toMillis(5), 10, fs == null ? null : fs.subset("RoundTripTime"));
      this.size = size;
      this.realTime = realTime;
    }

    @Override
    public synchronized long getDelay() {
      double rtt = roundTripTime.currentValue();
      double winSizeForMinPacketDelay = rtt / MIN_DELAY;
      double _simulatedWindowSize = getThrottleWindow().currentValue(realTime);
      if (_simulatedWindowSize > winSizeForMinPacketDelay) {
        _simulatedWindowSize = winSizeForMinPacketDelay;
      }
      if (_simulatedWindowSize < 1.0) {
        _simulatedWindowSize = 1.0F;
      }
      // return (long) (_roundTripTime / _simulatedWindowSize);
      return Math.max(MIN_DELAY, Math.min((long) (rtt / _simulatedWindowSize), MAX_DELAY));
    }

    private ThrottleWindowManager getThrottleWindow() {
      return RequestStarterGroup.this.getThrottleWindow(realTime);
    }

    public synchronized void successfulCompletion(long rtt) {
      roundTripTime.report(Math.max(rtt, 10));
      if(logMINOR)
        Logger.minor(this, "Reported successful completion: "+rtt+" on "+this+" avg "+roundTripTime.currentValue());
    }
   
    @Override
    public String toString() {
      return "rtt: "+roundTripTime.currentValue()+" _s="+getThrottleWindow().currentValue(realTime)+" RT="+realTime;
    }

    public SimpleFieldSet exportFieldSet() {
      SimpleFieldSet fs = new SimpleFieldSet(false);
      fs.put("RoundTripTime", roundTripTime.exportFieldSet(false));
      return fs;
    }

    public double getRTT() {
      return roundTripTime.currentValue();
    }

    public long getRate() {
      return (long) ((1000.0 / getDelay()) * size);
    }
  }

  public static class PrioritySchedulerCallback extends StringCallback implements EnumerableOptionCallback {
    ClientRequestScheduler csRT;
    ClientRequestScheduler csBulk;
    private final String[] possibleValues = new String[]{ ClientRequestScheduler.PRIORITY_HARD, ClientRequestScheduler.PRIORITY_SOFT };
   
    public void init(ClientRequestScheduler csRT, ClientRequestScheduler csBulk, String config) throws InvalidConfigValueException{
      this.csRT = csRT;
      this.csBulk = csBulk;
      set(config);
    }
   
    @Override
    public String get(){
      if(csBulk != null)
        return csBulk.getChoosenPriorityScheduler();
      else
        return ClientRequestScheduler.PRIORITY_SOFT;
    }
   
    @Override
    public void set(String val) throws InvalidConfigValueException{
      String value;
      if(val == null || val.equalsIgnoreCase(get())) return;
      if(val.equalsIgnoreCase(ClientRequestScheduler.PRIORITY_HARD)){
        value = ClientRequestScheduler.PRIORITY_HARD;
      }else if(val.equalsIgnoreCase(ClientRequestScheduler.PRIORITY_SOFT)){
        value = ClientRequestScheduler.PRIORITY_SOFT;
      }else{
        throw new InvalidConfigValueException("Invalid priority scheme");
      }
      csBulk.setPriorityScheduler(value);
      csRT.setPriorityScheduler(value);
    }
   
    @Override
    public String[] getPossibleValues() {
      return possibleValues;
    }
  }

  public ThrottleWindowManager getThrottleWindow(boolean realTime) {
    if(realTime) return throttleWindowRT;
    else return throttleWindowBulk;
  }

  public void requestCompleted(boolean isSSK, boolean isInsert, Key key, boolean realTime) {
    getThrottleWindow(realTime).requestCompleted();
    (isSSK ? throttleWindowSSK : throttleWindowCHK).requestCompleted();
    (isInsert ? throttleWindowInsert : throttleWindowRequest).requestCompleted();
    stats.reportOutgoingRequestLocation(key.toNormalizedDouble());
  }
 
  public void rejectedOverload(boolean isSSK, boolean isInsert, boolean realTime) {
    getThrottleWindow(realTime).rejectedOverload();
    (isSSK ? throttleWindowSSK : throttleWindowCHK).rejectedOverload();
    (isInsert ? throttleWindowInsert : throttleWindowRequest).rejectedOverload();
  }
 
  /**
   * Persist the throttle data to a SimpleFieldSet.
   */
  SimpleFieldSet persistToFieldSet() {
    SimpleFieldSet fs = new SimpleFieldSet(false);
    fs.put("ThrottleWindow", throttleWindowBulk.exportFieldSet(false));
    fs.put("ThrottleWindowRT", throttleWindowRT.exportFieldSet(false));
    fs.put("ThrottleWindowCHK", throttleWindowCHK.exportFieldSet(false));
    fs.put("ThrottleWindowSSK", throttleWindowCHK.exportFieldSet(false));
    fs.put("CHKRequestThrottle", chkRequestThrottleBulk.exportFieldSet());
    fs.put("SSKRequestThrottle", sskRequestThrottleBulk.exportFieldSet());
    fs.put("CHKInsertThrottle", chkInsertThrottleBulk.exportFieldSet());
    fs.put("SSKInsertThrottle", sskInsertThrottleBulk.exportFieldSet());
    fs.put("CHKRequestThrottleRT", chkRequestThrottleRT.exportFieldSet());
    fs.put("SSKRequestThrottleRT", sskRequestThrottleRT.exportFieldSet());
    fs.put("CHKInsertThrottleRT", chkInsertThrottleRT.exportFieldSet());
    fs.put("SSKInsertThrottleRT", sskInsertThrottleRT.exportFieldSet());
    return fs;
  }
 
  public double getWindow(boolean realTime) {
    return getThrottleWindow(realTime).currentValue(realTime);
  }

  public double getRTT(boolean isSSK, boolean isInsert, boolean realTime) {
    return getThrottle(isSSK, isInsert, realTime).getRTT();
  }

  public double getDelay(boolean isSSK, boolean isInsert, boolean realTime) {
    return getThrottle(isSSK, isInsert, realTime).getDelay();
  }
 
  MyRequestThrottle getThrottle(boolean isSSK, boolean isInsert, boolean realTime) {
    if(realTime) {
      if(isSSK) {
        if(isInsert) return sskInsertThrottleRT;
        else return sskRequestThrottleRT;
      } else {
        if(isInsert) return chkInsertThrottleRT;
        else return chkRequestThrottleRT;
      }
    } else {
      if(isSSK) {
        if(isInsert) return sskInsertThrottleBulk;
        else return sskRequestThrottleBulk;
      } else {
        if(isInsert) return chkInsertThrottleBulk;
        else return chkRequestThrottleBulk;
      }
    }
  }

  public String statsPageLine(boolean isSSK, boolean isInsert, boolean realTime) {
    StringBuilder sb = new StringBuilder(100);
    sb.append(isSSK ? "SSK" : "CHK");
    sb.append(' ');
    sb.append(isInsert ? "Insert" : "Request");
    sb.append(' ');
    sb.append(realTime ? "RealTime" : "Bulk");
    sb.append(" RTT=");
    MyRequestThrottle throttle = getThrottle(isSSK, isInsert, realTime);
    sb.append(TimeUtil.formatTime((long)throttle.getRTT(), 2, true));
    sb.append(" delay=");
    sb.append(TimeUtil.formatTime(throttle.getDelay(), 2, true));
    sb.append(" bw=");
    sb.append(throttle.getRate());
    sb.append("B/sec");
    return sb.toString();
  }

  public String diagnosticThrottlesLine(boolean mode) {
    StringBuilder sb = new StringBuilder();
    if(mode) {
      sb.append("Request window: ");
      sb.append(throttleWindowRequest.toString());
      sb.append(", Insert window: ");
      sb.append(throttleWindowInsert.toString());
    } else {
      sb.append("CHK window: ");
      sb.append(throttleWindowCHK.toString());
      sb.append(", SSK window: ");
      sb.append(throttleWindowSSK.toString());
    }
    return sb.toString();
  }

  public double getRealWindow(boolean realTime) {
    return getThrottleWindow(realTime).realCurrentValue();
  }

  public long countQueuedRequests() {
    return chkFetchSchedulerBulk.countQueuedRequests() +
      sskFetchSchedulerBulk.countQueuedRequests() +
      chkPutSchedulerBulk.countQueuedRequests() +
      sskPutSchedulerBulk.countQueuedRequests() +
      chkFetchSchedulerRT.countQueuedRequests() +
      sskFetchSchedulerRT.countQueuedRequests() +
      chkPutSchedulerRT.countQueuedRequests() +
      sskPutSchedulerRT.countQueuedRequests();
  }

  public ClientRequestScheduler getScheduler(boolean ssk, boolean insert,
      boolean realTime) {
    if(realTime) {
      if(insert) {
        return ssk ? sskPutSchedulerRT : chkPutSchedulerRT;
      } else {
        return ssk ? sskFetchSchedulerRT : chkFetchSchedulerRT;
      }
    } else {
      if(insert) {
        return ssk ? sskPutSchedulerBulk : chkPutSchedulerBulk;
      } else {
        return ssk ? sskFetchSchedulerBulk : chkFetchSchedulerBulk;
      }
    }
  }

    public void setGlobalSalt(byte[] salt) {
        chkFetchSchedulerBulk.startCore(salt);
        sskFetchSchedulerBulk.startCore(salt);
        chkPutSchedulerBulk.startCore(salt);
        sskPutSchedulerBulk.startCore(salt);
        chkFetchSchedulerRT.startCore(salt);
        sskFetchSchedulerRT.startCore(salt);
        chkPutSchedulerRT.startCore(salt);
        sskPutSchedulerRT.startCore(salt);
    }

}
TOP

Related Classes of freenet.node.RequestStarterGroup$PrioritySchedulerCallback

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.