Package freenet.client.async

Source Code of freenet.client.async.SimpleSingleFileFetcher

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

import java.io.IOException;
import java.io.Serializable;

import freenet.client.ClientMetadata;
import freenet.client.FetchContext;
import freenet.client.FetchException;
import freenet.client.FetchException.FetchExceptionMode;
import freenet.client.FetchResult;
import freenet.keys.ClientKey;
import freenet.keys.ClientKeyBlock;
import freenet.keys.KeyDecodeException;
import freenet.keys.TooBigException;
import freenet.node.LowLevelGetException;
import freenet.node.SendableRequestItem;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;
import freenet.support.api.Bucket;
import freenet.support.io.InsufficientDiskSpaceException;

/**
* Fetch a single block file. Used directly for very simple fetches, but also base class for
* SingleFileFetcher.
*
* WARNING: Changing non-transient members on classes that are Serializable can result in
* restarting downloads or losing uploads.
*/
public class SimpleSingleFileFetcher extends BaseSingleFileFetcher implements ClientGetState, Serializable {

    private static final long serialVersionUID = 1L;

    SimpleSingleFileFetcher(ClientKey key, int maxRetries, FetchContext ctx, ClientRequester parent,
      GetCompletionCallback rcb, boolean isEssential, boolean dontAdd, long l, ClientContext context, boolean deleteFetchContext, boolean realTimeFlag) {
    super(key, maxRetries, ctx, parent, deleteFetchContext, realTimeFlag);
    this.rcb = rcb;
    this.token = l;
    if(!dontAdd) {
      if(isEssential)
        parent.addMustSucceedBlocks(1);
      else
        parent.addBlock();
      parent.notifyClients(context);
    }
  }
   
  final GetCompletionCallback rcb;
  final long token;

        private static volatile boolean logMINOR;
  static {
    Logger.registerLogThresholdCallback(new LogThresholdCallback(){
      @Override
      public void shouldUpdate(){
        logMINOR = Logger.shouldLog(LogLevel.MINOR, this);
      }
    });
  }
 
  // Translate it, then call the real onFailure
  @Override
  public void onFailure(LowLevelGetException e, SendableRequestItem reqTokenIgnored, ClientContext context) {
      onFailure(translateException(e), false, context);
  }

  // Real onFailure
  protected void onFailure(FetchException e, boolean forceFatal, ClientContext context) {
    if(logMINOR) Logger.minor(this, "onFailure( "+e+" , "+forceFatal+")", e);
    if(parent.isCancelled() || cancelled) {
      if(logMINOR) Logger.minor(this, "Failing: cancelled");
      e = new FetchException(FetchExceptionMode.CANCELLED);
      forceFatal = true;
    }
    if(!(e.isFatal() || forceFatal) ) {
      if(retry(context)) {
        if(logMINOR) Logger.minor(this, "Retrying");
        return;
      }
    }
    // :(
    unregisterAll(context);
    synchronized(this) {
      finished = true;
    }
    if(e.isFatal() || forceFatal)
      parent.fatallyFailedBlock(context);
    else
      parent.failedBlock(context);
    rcb.onFailure(e, this, context);
  }

  /** Will be overridden by SingleFileFetcher */
  protected void onSuccess(FetchResult data, ClientContext context) {
    if(parent.isCancelled()) {
      data.asBucket().free();
      onFailure(new FetchException(FetchExceptionMode.CANCELLED), false, context);
      return;
    }
    rcb.onSuccess(new SingleFileStreamGenerator(data.asBucket(), persistent), data.getMetadata(), null, this, context);
  }

  @Override
  public void onSuccess(ClientKeyBlock block, boolean fromStore, Object reqTokenIgnored, ClientContext context) {
    if(parent instanceof ClientGetter)
      ((ClientGetter)parent).addKeyToBinaryBlob(block, context);
    Bucket data = extract(block, context);
    if(data == null) return; // failed
    context.uskManager.checkUSK(key.getURI(), fromStore, block.isMetadata());
    if(!block.isMetadata()) {
      onSuccess(new FetchResult(new ClientMetadata(null), data), context);
    } else {
      onFailure(new FetchException(FetchExceptionMode.INVALID_METADATA, "Metadata where expected data"), false, context);
    }
  }

  /** Convert a ClientKeyBlock to a Bucket. If an error occurs, report it via onFailure
   * and return null.
   */
  protected Bucket extract(ClientKeyBlock block, ClientContext context) {
    Bucket data;
    try {
      data = block.decode(context.getBucketFactory(parent.persistent()), (int)(Math.min(ctx.maxOutputLength, Integer.MAX_VALUE)), false);
    } catch (KeyDecodeException e1) {
      if(logMINOR)
        Logger.minor(this, "Decode failure: "+e1, e1);
      onFailure(new FetchException(FetchExceptionMode.BLOCK_DECODE_ERROR, e1.getMessage()), false, context);
      return null;
    } catch (TooBigException e) {
      onFailure(new FetchException(FetchExceptionMode.TOO_BIG, e), false, context);
      return null;
    } catch (InsufficientDiskSpaceException e) {
        onFailure(new FetchException(FetchExceptionMode.NOT_ENOUGH_DISK_SPACE), false, context);
        return null;
    } catch (IOException e) {
      Logger.error(this, "Could not capture data - disk full?: "+e, e);
      onFailure(new FetchException(FetchExceptionMode.BUCKET_ERROR, e), false, context);
      return null;
    }
    return data;
  }

  /** getToken() is not supported */
  @Override
  public long getToken() {
    return token;
  }

  @Override
  public void onFailed(KeyListenerConstructionException e, ClientContext context) {
    onFailure(e.getFetchException(), false, context);
  }

  @Override
  public void cancel(ClientContext context) {
    super.cancel(context);
    rcb.onFailure(new FetchException(FetchExceptionMode.CANCELLED), this, context);
  }

  @Override
  protected void notFoundInStore(ClientContext context) {
    this.onFailure(new FetchException(FetchExceptionMode.DATA_NOT_FOUND), true, context);
  }

  @Override
  protected void onBlockDecodeError(SendableRequestItem token, ClientContext context) {
    onFailure(new FetchException(FetchExceptionMode.BLOCK_DECODE_ERROR, "Could not decode block with the URI given, probably invalid as inserted, possible the URI is wrong"), true, context);
  }

    @Override
    public void onShutdown(ClientContext context) {
        // Do nothing.
    }

    @Override
    protected ClientGetState getClientGetState() {
        return this;
    }
   
}
TOP

Related Classes of freenet.client.async.SimpleSingleFileFetcher

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.