Package freenet.io.xfer

Source Code of freenet.io.xfer.PartiallyReceivedBlock$PacketReceivedListener

/*
* Dijjer - A Peer to Peer HTTP Cache
* Copyright (C) 2004,2005 Change.Tv, Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package freenet.io.xfer;

import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;

import freenet.support.Buffer;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;

/**
* @author ian
*
* To change the template for this generated type comment go to Window - Preferences - Java - Code Generation - Code and
* Comments
*/
public class PartiallyReceivedBlock {

  private static volatile boolean logMINOR;
  private static volatile boolean logDEBUG;

  static {
    Logger.registerLogThresholdCallback(new LogThresholdCallback(){
      @Override
      public void shouldUpdate(){
        logMINOR = Logger.shouldLog(LogLevel.MINOR, this);
        logDEBUG = Logger.shouldLog(LogLevel.DEBUG, this);
      }
    });
  }
 
  byte[] _data;
  boolean[] _received;
  int _receivedCount;
  public final int _packets, _packetSize;
  boolean _aborted;
  boolean _abortedLocally;
  int _abortReason;
  String _abortDescription;
  ArrayList<PacketReceivedListener> _packetReceivedListeners = new ArrayList<PacketReceivedListener>();

  public PartiallyReceivedBlock(int packets, int packetSize, byte[] data) {
    if (data.length != packets * packetSize) {
      throw new RuntimeException("Length of data ("+data.length+") doesn't match packet number and size");
    }
    _data = data;
    _received = new boolean[packets];
    for (int x=0; x<_received.length; x++) {
      _received[x] = true;
    }
    _receivedCount = packets;
    _packets = packets;
    _packetSize = packetSize;
  }
 
  public PartiallyReceivedBlock(int packets, int packetSize) {
    _data = new byte[packets * packetSize];
    _received = new boolean[packets];
    _packets = packets;
    _packetSize = packetSize;
  }

  public synchronized Deque<Integer> addListener(PacketReceivedListener listener) throws AbortedException {
    if (_aborted) {
      throw new AbortedException("Adding listener to aborted PRB");
    }
    _packetReceivedListeners.add(listener);
    Deque<Integer> ret = new LinkedList<Integer>();
    for (int x = 0; x < _packets; x++) {
      if (_received[x]) {
        ret.addLast(x);
      }
    }
    return ret;
  }

  public synchronized boolean isReceived(int packetNo) throws AbortedException {
    if (_aborted) {
      throw new AbortedException("PRB is aborted");
    }
    return _received[packetNo];
  }
 
  public synchronized int getNumPackets() throws AbortedException {
    if (_aborted) {
      throw new AbortedException("PRB is aborted");
    }
    return _packets;
  }
 
  public synchronized int getPacketSize() throws AbortedException {
    if (_aborted) {
      throw new AbortedException("PRB is aborted");
    }
    return _packetSize;
  }
 
  public void addPacket(int position, Buffer packet) throws AbortedException {
   
    PacketReceivedListener[] prls;
   
    synchronized(this) {
      if (_aborted) {
        throw new AbortedException("PRB is aborted");
      }
      if (packet.getLength() != _packetSize) {
        throw new RuntimeException("New packet size "+packet.getLength()+" but expecting packet of size "+_packetSize);
      }
      if (_received[position])
        return;
     
      _receivedCount++;
      packet.copyTo(_data, position * _packetSize);
      _received[position] = true;
     
      // FIXME keep it as as an array
      prls = _packetReceivedListeners.toArray(new PacketReceivedListener[_packetReceivedListeners.size()]);
    }
   
   
    for (PacketReceivedListener prl: prls) {
      prl.packetReceived(position);
    }
  }
 
  public synchronized boolean allReceivedAndNotAborted() {
    return _receivedCount == _packets && !_aborted;
  }

  public synchronized boolean allReceived() throws AbortedException {
    if(_receivedCount == _packets) {
      if(logDEBUG) Logger.debug(this, "Received "+_receivedCount+" of "+_packets+" on "+this);
      return true;
    }
    if (_aborted) {
      throw new AbortedException("PRB is aborted: "+_abortReason+" : "+_abortDescription+" received "+_receivedCount+" of "+_packets+" on "+this);
    }
    return false;
  }
 
  public synchronized byte[] getBlock() throws AbortedException {
    if(allReceived()) return _data;
    throw new RuntimeException("Tried to get block before all packets received");
  }
 
  public synchronized Buffer getPacket(int x) throws AbortedException {
    if (_aborted) {
      throw new AbortedException("PRB is aborted");
    }
    if (!_received[x]) {
      throw new IllegalStateException("that packet is not received");
    }
    return new Buffer(_data, x * _packetSize, _packetSize);
  }
 

  public synchronized void removeListener(PacketReceivedListener listener) {
    _packetReceivedListeners.remove(listener);
  }

  /**
   * Abort the transfer.
   * @param reason
   * @param description
   * @param cancelledLocally If true, the transfer was deliberately aborted by *this node*,
   * not as the result of a timeout.
   * @return Null if the PRB is aborted now. The data if it is not.
   */
  public byte[] abort(int reason, String description, boolean cancelledLocally) {
    PacketReceivedListener[] listeners;
    synchronized(this) {
      if(_aborted) {
        if(logMINOR) Logger.minor(this, "Already aborted "+this+" : reason="+_abortReason+" description="+_abortDescription);
        return null;
      }
      if(_receivedCount == _packets) {
        if(logMINOR) Logger.minor(this, "Already received");
        return _data;
      }
      Logger.normal(this, "Aborting PRB: "+reason+" : "+description+" on "+this, new Exception("debug"));
      _aborted = true;
      _abortedLocally = cancelledLocally;
      _abortReason = reason;
      _abortDescription = description;
      listeners = _packetReceivedListeners.toArray(new PacketReceivedListener[_packetReceivedListeners.size()]);
      _packetReceivedListeners.clear();
    }
    for (PacketReceivedListener prl : listeners) {
      prl.receiveAborted(reason, description);
    }
    return null;
  }
 
  public synchronized boolean isAborted() {
    return _aborted;
  }
 
  public synchronized int getAbortReason() {
    return _abortReason;
  }
 
  public synchronized String getAbortDescription() {
    return _abortDescription;
  }
 
  public static interface PacketReceivedListener {

    public void packetReceived(int packetNo);
   
    public void receiveAborted(int reason, String description);
  }

  public boolean abortedLocally() {
    return _abortedLocally;
  }
}
TOP

Related Classes of freenet.io.xfer.PartiallyReceivedBlock$PacketReceivedListener

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.