Package freenet.client

Source Code of freenet.client.HighLevelSimpleClientImpl

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

import java.io.IOException;
import java.util.HashMap;
import java.util.Set;

import freenet.client.InsertException.InsertExceptionMode;
import freenet.client.Metadata.DocumentType;
import freenet.client.async.BaseManifestPutter;
import freenet.client.async.ClientGetCallback;
import freenet.client.async.ClientGetter;
import freenet.client.async.ClientPutCallback;
import freenet.client.async.ClientPutter;
import freenet.client.async.DefaultManifestPutter;
import freenet.client.async.PersistenceDisabledException;
import freenet.client.async.TooManyFilesInsertException;
import freenet.client.events.ClientEventListener;
import freenet.client.events.ClientEventProducer;
import freenet.client.events.EventLogger;
import freenet.client.events.SimpleEventProducer;
import freenet.crypt.RandomSource;
import freenet.keys.FreenetURI;
import freenet.keys.InsertableClientSSK;
import freenet.node.Node;
import freenet.node.NodeClientCore;
import freenet.node.RequestClient;
import freenet.node.RequestScheduler;
import freenet.node.RequestStarter;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;
import freenet.support.api.Bucket;
import freenet.support.api.BucketFactory;
import freenet.support.api.RandomAccessBucket;
import freenet.support.compress.Compressor;
import freenet.support.io.BucketTools;
import freenet.support.io.NullBucket;
import freenet.support.io.PersistentFileTracker;

public class HighLevelSimpleClientImpl implements HighLevelSimpleClient, RequestClient, Cloneable {

  private final short priorityClass;
  private final BucketFactory bucketFactory;
  private final BucketFactory persistentBucketFactory;
  private final PersistentFileTracker persistentFileTracker;
  private final NodeClientCore core;
  /** One CEP for all requests and inserts */
  private final ClientEventProducer eventProducer;
  private long curMaxLength;
  private long curMaxTempLength;
  private int curMaxMetadataLength;
  private final RandomSource random;
  private final boolean realTimeFlag;
  static final int MAX_RECURSION = 10;
  static final int MAX_ARCHIVE_RESTARTS = 2;
  static final int MAX_ARCHIVE_LEVELS = 10;
  static final boolean DONT_ENTER_IMPLICIT_ARCHIVES = true;
  // COOLDOWN_RETRIES-1 so we don't have to wait on the cooldown queue; HLSC is designed
  // for interactive requests mostly.
  /** Number of retries allowed per block in a splitfile. */
  static final int SPLITFILE_BLOCK_RETRIES = Math.min(3, RequestScheduler.COOLDOWN_RETRIES-1);
  /** Number of retries allowed on non-splitfile fetches. */
  static final int NON_SPLITFILE_RETRIES = Math.min(3, RequestScheduler.COOLDOWN_RETRIES-1);
  static final int USK_RETRIES = RequestScheduler.COOLDOWN_RETRIES - 1;
  /** Whether to fetch splitfiles. Don't turn this off! */
  static final boolean FETCH_SPLITFILES = true;
  /** Whether to follow redirects etc. If false, we only fetch a plain block of data.
   * Don't turn this off either! */
  static final boolean FOLLOW_REDIRECTS = true;
  /** If set, only check the local datastore, don't send an actual request out.
   * Don't turn this off either. */
  static final boolean LOCAL_REQUESTS_ONLY = false;
  /** By default, write to the client cache. Turn this off if you are fetching big stuff. */
  static final boolean CAN_WRITE_CLIENT_CACHE = true;
  /** By default, don't write local inserts to the client cache. */
  static final boolean CAN_WRITE_CLIENT_CACHE_INSERTS = false;
  /** Number of retries on inserts */
  static final int INSERT_RETRIES = 10;
  /** Number of RNFs on insert that make a success, or -1 on large networks */
  static final int CONSECUTIVE_RNFS_ASSUME_SUCCESS = 2;
  // going by memory usage only; 4kB per stripe
  static final int MAX_SPLITFILE_BLOCKS_PER_SEGMENT = 256;
  static final int MAX_SPLITFILE_CHECK_BLOCKS_PER_SEGMENT = 256;
  // For scaling purposes, 128 data 128 check blocks i.e. one check block per data block.
  public static final int SPLITFILE_SCALING_BLOCKS_PER_SEGMENT = 128;
  /* The number of data blocks in a segment depends on how many segments there are.
   * FECCodec.standardOnionCheckBlocks will automatically reduce check blocks to compensate for more than half data blocks. */
  public static final int SPLITFILE_BLOCKS_PER_SEGMENT = 136;
  public static final int SPLITFILE_CHECK_BLOCKS_PER_SEGMENT = 128;
  public static final int EXTRA_INSERTS_SINGLE_BLOCK = 2;
  public static final int EXTRA_INSERTS_SPLITFILE_HEADER = 2;
  /*Whether or not to filter fetched content*/
  static final boolean FILTER_DATA = false;

  public HighLevelSimpleClientImpl(NodeClientCore node, BucketFactory bf, RandomSource r, short priorityClass, boolean forceDontIgnoreTooManyPathComponents, boolean realTimeFlag) {
    this.core = node;
    this.priorityClass = priorityClass;
    bucketFactory = bf;
    this.persistentFileTracker = node.persistentTempBucketFactory;
    random = r;
    this.eventProducer = new SimpleEventProducer();
    eventProducer.addEventListener(new EventLogger(LogLevel.MINOR, false));
    curMaxLength = Long.MAX_VALUE;
    curMaxTempLength = Long.MAX_VALUE;
    curMaxMetadataLength = 1024 * 1024;
    this.persistentBucketFactory = node.persistentTempBucketFactory;
    this.realTimeFlag = realTimeFlag;
  }

  public HighLevelSimpleClientImpl(HighLevelSimpleClientImpl hlsc) {
    this.eventProducer = new SimpleEventProducer();
    this.priorityClass = hlsc.priorityClass;
    this.bucketFactory = hlsc.bucketFactory;
    this.persistentBucketFactory = hlsc.persistentBucketFactory;
    this.persistentFileTracker = hlsc.persistentFileTracker;
    this.core = hlsc.core;
    this.curMaxLength = hlsc.curMaxLength;
    this.curMaxMetadataLength = hlsc.curMaxMetadataLength;
    this.curMaxTempLength = hlsc.curMaxTempLength;
    this.random = hlsc.random;
    this.realTimeFlag = hlsc.realTimeFlag;
  }

  @Override
  public HighLevelSimpleClientImpl clone() {
    // Cloneable shuts up findbugs, but we need a new SimpleEventProducer().
    return new HighLevelSimpleClientImpl(this);
  }

  @Override
  public void setMaxLength(long maxLength) {
    curMaxLength = maxLength;
  }

  @Override
  public void setMaxIntermediateLength(long maxIntermediateLength) {
    curMaxTempLength = maxIntermediateLength;
  }

  /**
   * Fetch a key. Either returns the data, or throws an exception.
   */
  @Override
  public FetchResult fetch(FreenetURI uri) throws FetchException {
    if(uri == null) throw new NullPointerException();
    FetchContext context = getFetchContext();
    FetchWaiter fw = new FetchWaiter(this);
    ClientGetter get = new ClientGetter(fw, uri, context, priorityClass, null, null, null);
    try {
      core.clientContext.start(get);
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
    return fw.waitForCompletion();
  }

  /**
   * Fetch a key. Either returns the data, or throws an exception.
   */
  @Override
  public FetchResult fetchFromMetadata(Bucket initialMetadata) throws FetchException {
    if(initialMetadata == null) throw new NullPointerException();
    FetchContext context = getFetchContext();
    FetchWaiter fw = new FetchWaiter(this);
    ClientGetter get = new ClientGetter(fw, FreenetURI.EMPTY_CHK_URI, context, priorityClass, null, null, initialMetadata);
    try {
      core.clientContext.start(get);
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
    return fw.waitForCompletion();
  }

  @Override
  public FetchResult fetch(FreenetURI uri, long overrideMaxSize) throws FetchException {
    return fetch(uri, overrideMaxSize, this);
  }

  @Override
  public FetchResult fetch(FreenetURI uri, long overrideMaxSize, RequestClient clientContext) throws FetchException {
    if(uri == null) throw new NullPointerException();
    FetchWaiter fw = new FetchWaiter(clientContext);
    FetchContext context = getFetchContext(overrideMaxSize);
    ClientGetter get = new ClientGetter(fw, uri, context, priorityClass, null, null, null);
    try {
      core.clientContext.start(get);
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
    return fw.waitForCompletion();
  }

  @Override
  public ClientGetter fetch(FreenetURI uri, long maxSize, ClientGetCallback callback, FetchContext fctx) throws FetchException {
    return fetch(uri, maxSize, callback, fctx, priorityClass);
  }

  @Override
  public ClientGetter fetch(FreenetURI uri, long maxSize, ClientGetCallback callback, FetchContext fctx, short prio) throws FetchException {
    return fetch(uri, callback, fctx, prio);
  }
 
  @Override
  public ClientGetter fetch(FreenetURI uri, ClientGetCallback callback, FetchContext fctx, short prio) throws FetchException {
    if(uri == null) throw new NullPointerException();
    ClientGetter get = new ClientGetter(callback, uri, fctx, prio, null, null, null);
    try {
      core.clientContext.start(get);
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
    return get;
  }

  @Override
  public ClientGetter fetchFromMetadata(Bucket initialMetadata, ClientGetCallback callback, FetchContext fctx, short prio) throws FetchException {
    if(initialMetadata == null) throw new NullPointerException();
    ClientGetter get = new ClientGetter(callback, FreenetURI.EMPTY_CHK_URI, fctx, prio, null, null, initialMetadata);
    try {
      core.clientContext.start(get);
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
    return get;
  }

  @Override
  public FreenetURI insert(InsertBlock insert, boolean getCHKOnly, String filenameHint) throws InsertException {
    return insert(insert, getCHKOnly, filenameHint, priorityClass);
  }
 
  @Override
  public FreenetURI insert(InsertBlock insert, boolean getCHKOnly, String filenameHint, short priority) throws InsertException {
    return insert(insert, getCHKOnly, filenameHint, false, priority);
  }

  public FreenetURI insert(InsertBlock insert, boolean getCHKOnly, String filenameHint, boolean isMetadata, short priority) throws InsertException {
    InsertContext context = getInsertContext(true);
    context.getCHKOnly = getCHKOnly;
    return insert(insert, filenameHint, isMetadata, priority, context);
  }
 
  @Override
  public FreenetURI insert(InsertBlock insert, String filenameHint, short priority, InsertContext ctx) throws InsertException {
    return insert(insert, filenameHint, false, priority, ctx);
  }
 
  public FreenetURI insert(InsertBlock insert, String filenameHint, boolean isMetadata, short priority, InsertContext ctx) throws InsertException {
    return insert(insert, filenameHint, isMetadata, priority, ctx, null);
  }
 
  public FreenetURI insert(InsertBlock insert, String filenameHint, boolean isMetadata, short priority, InsertContext ctx, byte[] forceCryptoKey) throws InsertException {
    PutWaiter pw = new PutWaiter(this);
    ClientPutter put = new ClientPutter(pw, insert.getData(), insert.desiredURI, insert.clientMetadata,
        ctx, priority,
        isMetadata, filenameHint, false, core.clientContext, forceCryptoKey, -1);
    try {
      core.clientContext.start(put);
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
    return pw.waitForCompletion();
  }

  @Override
  public ClientPutter insert(InsertBlock insert, String filenameHint, boolean isMetadata, InsertContext ctx, ClientPutCallback cb) throws InsertException {
    return insert(insert, filenameHint, isMetadata, ctx, cb, priorityClass);
  }
 
  @Override
  public ClientPutter insert(InsertBlock insert, String filenameHint, boolean isMetadata, InsertContext ctx, ClientPutCallback cb, short priority) throws InsertException {
    ClientPutter put = new ClientPutter(cb, insert.getData(), insert.desiredURI, insert.clientMetadata,
        ctx, priority,
        isMetadata, filenameHint, false, core.clientContext, null, -1);
    try {
      core.clientContext.start(put);
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
    return put;
  }

  @Override
  public FreenetURI insertRedirect(FreenetURI insertURI, FreenetURI targetURI) throws InsertException {
    Metadata m = new Metadata(DocumentType.SIMPLE_REDIRECT, null, null, targetURI, new ClientMetadata());
    RandomAccessBucket b;
    try {
      b = m.toBucket(bucketFactory);
    } catch (IOException e) {
      Logger.error(this, "Bucket error: "+e, e);
      throw new InsertException(InsertExceptionMode.INTERNAL_ERROR, e, null);
    } catch (MetadataUnresolvedException e) {
      Logger.error(this, "Impossible error: "+e, e);
      throw new InsertException(InsertExceptionMode.INTERNAL_ERROR, e, null);
    }

    InsertBlock block = new InsertBlock(b, null, insertURI);
    return insert(block, false, null, true, priorityClass);
  }

  @Override
  public FreenetURI insertManifest(FreenetURI insertURI, HashMap<String, Object> bucketsByName, String defaultName) throws InsertException {
    return insertManifest(insertURI, bucketsByName, defaultName, priorityClass);
  }

  @Override
  public FreenetURI insertManifest(FreenetURI insertURI, HashMap<String, Object> bucketsByName, String defaultName, short priorityClass) throws InsertException {
    return insertManifest(insertURI, bucketsByName, defaultName, priorityClass, null);
  }
 
  @Override
  public FreenetURI insertManifest(FreenetURI insertURI, HashMap<String, Object> bucketsByName, String defaultName, short priorityClass, byte[] forceCryptoKey) throws InsertException {
    PutWaiter pw = new PutWaiter(this);
    DefaultManifestPutter putter;
        try {
            putter = new DefaultManifestPutter(pw, BaseManifestPutter.bucketsByNameToManifestEntries(bucketsByName), priorityClass, insertURI, defaultName, getInsertContext(true), false, forceCryptoKey, core.clientContext);
        } catch (TooManyFilesInsertException e1) {
            throw new InsertException(InsertExceptionMode.TOO_MANY_FILES);
        }
    try {
      core.clientContext.start(putter);
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
    return pw.waitForCompletion();
  }

  @Override
  public void addEventHook(ClientEventListener listener) {
    eventProducer.addEventListener(listener);
  }

  @Override
  public FetchContext getFetchContext() {
    return getFetchContext(-1);
  }

  @Override
  public FetchContext getFetchContext(long overrideMaxSize) {
    long maxLength = curMaxLength;
    long maxTempLength = curMaxTempLength;
    if(overrideMaxSize >= 0) {
      maxLength = overrideMaxSize;
      maxTempLength = overrideMaxSize;
    }
    return
      new FetchContext(maxLength, maxTempLength, curMaxMetadataLength,
        MAX_RECURSION, MAX_ARCHIVE_RESTARTS, MAX_ARCHIVE_LEVELS, DONT_ENTER_IMPLICIT_ARCHIVES,
        SPLITFILE_BLOCK_RETRIES, NON_SPLITFILE_RETRIES, USK_RETRIES,
        FETCH_SPLITFILES, FOLLOW_REDIRECTS, LOCAL_REQUESTS_ONLY,
        FILTER_DATA, MAX_SPLITFILE_BLOCKS_PER_SEGMENT, MAX_SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
        bucketFactory, eventProducer,
        false, CAN_WRITE_CLIENT_CACHE, null, null);
  }
 
  public static FetchContext makeDefaultFetchContext(long maxLength, long maxTempLength,
          BucketFactory bucketFactory, SimpleEventProducer eventProducer) {
        return
        new FetchContext(maxLength, maxTempLength, 1024*1024,
            MAX_RECURSION, MAX_ARCHIVE_RESTARTS, MAX_ARCHIVE_LEVELS, DONT_ENTER_IMPLICIT_ARCHIVES,
            SPLITFILE_BLOCK_RETRIES, NON_SPLITFILE_RETRIES, USK_RETRIES,
            FETCH_SPLITFILES, FOLLOW_REDIRECTS, LOCAL_REQUESTS_ONLY,
            FILTER_DATA, MAX_SPLITFILE_BLOCKS_PER_SEGMENT, MAX_SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
            bucketFactory, eventProducer,
            false, CAN_WRITE_CLIENT_CACHE, null, null);
  }

  @Override
  public InsertContext getInsertContext(boolean forceNonPersistent) {
    return new InsertContext(
        INSERT_RETRIES, CONSECUTIVE_RNFS_ASSUME_SUCCESS,
        SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
        eventProducer, CAN_WRITE_CLIENT_CACHE_INSERTS, Node.FORK_ON_CACHEABLE_DEFAULT, false,
        Compressor.DEFAULT_COMPRESSORDESCRIPTOR, EXTRA_INSERTS_SINGLE_BLOCK,
        EXTRA_INSERTS_SPLITFILE_HEADER, InsertContext.CompatibilityMode.COMPAT_DEFAULT);
  }

    public static InsertContext makeDefaultInsertContext(BucketFactory bucketFactory,
            SimpleEventProducer eventProducer) {
        return new InsertContext(
                INSERT_RETRIES, CONSECUTIVE_RNFS_ASSUME_SUCCESS,
                SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
                eventProducer, CAN_WRITE_CLIENT_CACHE_INSERTS, Node.FORK_ON_CACHEABLE_DEFAULT, false,
                Compressor.DEFAULT_COMPRESSORDESCRIPTOR, EXTRA_INSERTS_SINGLE_BLOCK,
                EXTRA_INSERTS_SPLITFILE_HEADER, InsertContext.CompatibilityMode.COMPAT_DEFAULT);
    }

  @Override
  public FreenetURI[] generateKeyPair(String docName) {
    InsertableClientSSK key = InsertableClientSSK.createRandom(random, docName);
    return new FreenetURI[] { key.getInsertURI(), key.getURI() };
  }

  private final ClientGetCallback nullCallback = new NullClientCallback(this);

  @Override
  public void prefetch(FreenetURI uri, long timeout, long maxSize, Set<String> allowedTypes) {
    prefetch(uri, timeout, maxSize, allowedTypes, RequestStarter.PREFETCH_PRIORITY_CLASS);
  }

  @Override
  public void prefetch(FreenetURI uri, long timeout, long maxSize, Set<String> allowedTypes, short prio) {
    FetchContext ctx = getFetchContext(maxSize);
    ctx.allowedMIMETypes = allowedTypes;
    final ClientGetter get = new ClientGetter(nullCallback, uri, ctx, prio, new NullBucket(), null, null);
    core.getTicker().queueTimedJob(new Runnable() {
      @Override
      public void run() {
        get.cancel(core.clientContext);
      }

    }, timeout);
    try {
      core.clientContext.start(get);
    } catch (FetchException e) {
      // Ignore
    } catch (PersistenceDisabledException e) {
      // Impossible
    }
  }

  @Override
  public boolean persistent() {
    return false;
  }

  @Override
  public boolean realTimeFlag() {
    return realTimeFlag;
  }

}
TOP

Related Classes of freenet.client.HighLevelSimpleClientImpl

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.