Package freenet.node

Source Code of freenet.node.SendableRequest

package freenet.node;

import java.io.Serializable;

import freenet.client.async.ClientContext;
import freenet.client.async.ClientRequestScheduler;
import freenet.client.async.ClientRequestSchedulerGroup;
import freenet.client.async.ClientRequester;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.RandomGrabArray;
import freenet.support.RandomGrabArrayItem;
import freenet.support.Logger.LogLevel;

/**
* A low-level request which can be sent immediately. These are registered
* on the ClientRequestScheduler.
* LOCKING: Because some subclasses may do wierd things like locking on an external object
* (see e.g. SplitFileFetcherSubSegment), if we do take the lock we need to do it last i.e.
* not call any subclass methods inside it.
*
* WARNING: Changing non-transient members on classes that are Serializable can result in
* restarting downloads or losing uploads. Not all subclasses of this class are actually persisted.
*/
public abstract class SendableRequest implements RandomGrabArrayItem, Serializable {
 
    private static final long serialVersionUID = 1L;

    /** Since we put these into Set's etc, hashCode must be persistent.
   * Guaranteed not to be 0 unless this is a persistent object that is deactivated. */
  private final int hashCode;
 
  protected final boolean realTimeFlag;

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

  SendableRequest(boolean persistent, boolean realTimeFlag) {
    this.persistent = persistent;
    this.realTimeFlag = realTimeFlag;
    int oid = super.hashCode();
    if(oid == 0) oid = 1;
    this.hashCode = oid;
  }
 
  @Override
  public final int hashCode() {
    return hashCode;
  }
 
  protected transient RandomGrabArray parentGrabArray;
  /** Member because must be accessible when only marginally activated */
  protected final boolean persistent;
 
  /** Get the priority class of the request. */
  public abstract short getPriorityClass();
 
  /** Choose a key to fetch. Must not modify any persisted structures, but will update cooldowns
   * etc to avoid it being chosen again soon. There is a separate callback for when a fetch
   * fails, succeeds, etc. Hence it is safe to call these outside of the PersistentJobRunner.
   * @return An object identifying a specific key. null indicates no keys available. */
  public abstract SendableRequestItem chooseKey(KeysFetchingLocally keys, ClientContext context);
 
  /** All key identifiers. Including those not currently eligible to be sent because
   * they are on a cooldown queue, requests for them are in progress, etc. */
  public abstract long countAllKeys(ClientContext context);

  /** All key identifiers currently eligible to be sent. Does not include those
   * currently running, on the cooldown queue etc. */
  public abstract long countSendableKeys(ClientContext context);

  /**
   * Get or create a SendableRequestSender for this object. This is a non-persistent
   * object used to send the requests. @see SendableGet.getSender().
   * @param container A database handle may be necessary for creating it.
   * @param context A client context may also be necessary.
   * @return
   */
  public abstract SendableRequestSender getSender(ClientContext context);
 
  /** If true, the request has been cancelled, or has completed, either way it need not
   * be registered any more. isEmpty() on the other hand means there are no queued blocks.
   */
  public abstract boolean isCancelled();
 
  /** Get client context object. This isn't called as frequently as you might expect
   * - once on registration, and then when there is an error. So it doesn't need to be
   * stored on the request itself, hence we pass in a container. */
  public abstract RequestClient getClient();
 
  /** Is this request persistent? MUST NOT CHANGE. */
  public final boolean persistent() {
    return persistent;
  }
 
  /** Get the ClientRequest. This DOES need to be cached on the request itself. */
  public abstract ClientRequester getClientRequest();
 
  @Override
  public synchronized RandomGrabArray getParentGrabArray() {
    return parentGrabArray;
  }
 
  /** Grab it to avoid race condition when unregistering twice in parallel. */
  private synchronized RandomGrabArray grabParentGrabArray() {
    RandomGrabArray ret = parentGrabArray;
    parentGrabArray = null;
    return ret;
  }
 
  @Override
  public boolean knowsParentGrabArray() {
    return true;
  }
 
  @Override
  public synchronized void setParentGrabArray(RandomGrabArray parent) {
    parentGrabArray = parent;
  }
 
  /** Unregister the request.
   * @param container
   * @param context
   * @param oldPrio If we are changing priorities it can matter what the old priority is.
   * However the parent method, SendableRequest, ignores this. In any case,
   * (short)-1 means not specified (look it up).
   */
  public void unregister(ClientContext context, short oldPrio) {
    RandomGrabArray arr = grabParentGrabArray();
    if(arr != null) {
      synchronized(getScheduler(context)) {
        arr.remove(this, context);
      }
    } else {
      // Should this be a higher priority?
      if(logMINOR)
        Logger.minor(this, "Cannot unregister "+this+" : not registered", new Exception("debug"));
    }
  }
 
  public abstract ClientRequestScheduler getScheduler(ClientContext context);

  /** Is this an SSK? For purposes of determining which scheduler to use. */
  public abstract boolean isSSK();
 
  /** Is this an insert? For purposes of determining which scheduler to use. */
  public abstract boolean isInsert();
 
  /** Requeue after an internal error */
  public abstract void internalError(Throwable t, RequestScheduler sched, ClientContext context, boolean persistent);

  public boolean realTimeFlag() {
    return realTimeFlag;
  }

  protected final String objectToString() {
    return super.toString();
  }
 
    @Override
    public boolean reduceWakeupTime(long wakeupTime, ClientContext context) {
        RandomGrabArray parent = getParentGrabArray();
        if(parent == null) return false;
        return parent.reduceWakeupTime(wakeupTime, context);
    }

    @Override
    public void clearWakeupTime(ClientContext context) {
        RandomGrabArray parent = getParentGrabArray();
        if(parent == null) return;
        parent.clearWakeupTime(context);
    }

    public ClientRequestSchedulerGroup getSchedulerGroup() {
        return getClientRequest().getSchedulerGroup();
    }

}
TOP

Related Classes of freenet.node.SendableRequest

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.