/**
 * Applies a jitter that is equally distributed from 0 to max.
 *
 * <p>Parameters: max (long)
 *
 * @author Leo Nobach <*****@*****.**>
 * @version 05/06/2011
 */
public class EqualDistJitter implements JitterStrategy {

  public long max = 5 * Simulator.MILLISECOND_UNIT;

  RandomGenerator rand = Simulator.getRandom();

  @Override
  public long getJitter(
      long cleanMsgPropagationDelay,
      NetMessage msg,
      ModularNetLayer nlSender,
      ModularNetLayer nlReceiver,
      NetMeasurementDB db) {
    return Math.round(rand.nextDouble() * max);
  }

  /**
   * Sets the maximum jitter in simulation time units.
   *
   * @param maxJitter
   */
  public void setMax(long maxJitter) {
    this.max = maxJitter;
  }

  @Override
  public void writeBackToXML(BackWriter bw) {
    bw.writeTime("max", max);
  }
}
 @Override
 public void calledOperationFailed(Operation op) {
   if (op instanceof BTOperationDownload) {
     logger.process(
         this.getClass().toString(),
         new Object[] {op, new Long(Simulator.getCurrentTime()), new Boolean(false)});
   }
 }
  public void startRandomLookup(ChordNode starter) {
    log.debug("lookup counter " + Arrays.toString(lookupCount));
    lookupCount[0]++;
    long randomLong = Simulator.getRandom().nextLong();
    String token = Long.toString(Math.abs(randomLong), 32);
    ChordID key = ChordIDFactory.getInstance().getChordID(token);
    int lookupID = starter.overlayNodeLookup(key, new MyCallback());

    log.debug("started lookup request key = " + key + " id = " + lookupID + " from = " + starter);
    lookupList.add(lookupID);
  }
 /**
  * This method starts a download by creating and activating a download operation.
  *
  * @param theOverlayKey the key/hash of the document that we want to download.
  * @param theOtherPeers a list of peers start also participate in this torrent. We normaly get
  *     this list from the tracker.
  * @return the operation id of the started download operation.
  */
 public int downloadDocument(
     OverlayKey theOverlayKey, List<TransInfo> theOtherPeers, OperationCallback theCallback) {
   log.debug(
       "Time: "
           + Simulator.getCurrentTime()
           + "; Starting download at '"
           + this.itsOwnContact
           + "'.");
   BTDocument document;
   BTConnectionManager connectionManager;
   if (!this.itsContentStorage.containsDocument(theOverlayKey)) {
     document =
         new BTDocument(
             theOverlayKey,
             ((BTTorrent) this.itsDataBus.getPerTorrentData(theOverlayKey, "Torrent")).getSize());
     this.itsContentStorage.storeDocument(document);
   } else {
     document = (BTDocument) this.itsContentStorage.loadDocument(theOverlayKey);
   }
   if (!this.itsConnectionManagers.containsKey(theOverlayKey)) {
     connectionManager = new BTConnectionManager(this.itsOwnContact);
     this.itsConnectionManagers.put(theOverlayKey, connectionManager);
   } else {
     connectionManager = this.itsConnectionManagers.get(theOverlayKey);
   }
   BTOperationDownload<BTPeerDistributeNode> downloadOperation =
       new BTOperationDownload<BTPeerDistributeNode>(
           this.itsDataBus,
           document,
           this.itsOwnContact,
           this,
           this,
           connectionManager,
           this.itsStatistic,
           this.itsRandomGenerator);
   this.itsDownloadOperations.add(downloadOperation);
   downloadOperation.scheduleImmediately();
   return downloadOperation.getOperationID();
 }
  @Override
  public void execute() {
    if (node.getPeerStatus() == PeerStatus.PRESENT
        && delete == false
        && node.neighboursContain(neighbour)) {

      if (allreadyTried < CanConfig.numberPings && succ == false) {
        PingMsg ping =
            new PingMsg(
                node.getLocalContact().getOverlayID(),
                neighbour.getOverlayID(),
                node.getLocalContact().clone());
        ping.setOperationId(this.getOperationID());
        node.getTransLayer()
            .send(ping, neighbour.getTransInfo(), node.getPort(), TransProtocol.UDP);
        allreadyTried++;
        this.operationFinished(true);
        this.scheduleWithDelay(CanConfig.timeout);
      } else if (allreadyTried >= CanConfig.numberPings && succ == false && otherAnswer == false) {
        this.operationFinished(true);
        this.scheduleWithDelay(CanConfig.numberPings * CanConfig.timeout + 2 * CanConfig.timeout);
      } else if (allreadyTried >= CanConfig.numberPings && succ == false) {
        log.warn(
            Simulator.getSimulatedRealtime()
                + " node left, own id: "
                + node.getLocalContact().getOverlayID().toString()
                + " "
                + node.getLocalContact().getArea().toString()
                + " missing node: "
                + neighbour.getOverlayID().toString()
                + " "
                + neighbour.getArea().toString()
                + " "
                + this.getOperationID());
        for (CanOverlayContact neighbour : node.getNeighbours()) {
          log.warn("own neighbours: " + neighbour.getOverlayID().toString());
        }

        CanOverlayContact closestVidNeighbour = null;
        if (neighbour
            .getArea()
            .getVid()
            .getVIDList()
            .get(neighbour.getArea().getVid().getVIDList().size() - 1)
            .equals("0"))
          closestVidNeighbour = node.getVidNeighboursOfCertainNeighbour(neighbour)[1];
        else closestVidNeighbour = node.getVidNeighboursOfCertainNeighbour(neighbour)[0];

        if (closestVidNeighbour != null) { // ////////////normaly used
          // without the case, not
          // well tested
          log.debug(
              "closest vid neighbour: "
                  + closestVidNeighbour.getOverlayID().toString()
                  + " in node "
                  + node.getLocalContact().getOverlayID().toString()
                  + " "
                  + neighbour.getArea().getVid().toString()
                  + " "
                  + node.getLocalContact().getArea().getVid().toString()
                  + " "
                  + neighbour
                      .getArea()
                      .getVid()
                      .closestNeighbour(node.getLocalContact().getArea().getVid()));

          // controll if one of the neighbours is the direct neighbour
          if (neighbour
              .getArea()
              .getVid()
              .closestNeighbour(node.getLocalContact().getArea().getVid())) {
            log.debug(
                "direct Vid neighbour is missing "
                    + " neighbour "
                    + neighbour.getArea().getVid().toString()
                    + " own "
                    + node.getLocalContact().getArea().getVid().toString()
                    + " "
                    + neighbour
                        .getArea()
                        .getVid()
                        .closestNeighbour(node.getLocalContact().getArea().getVid()));
            if (node.getMissingNode() == null) {
              node.setMissingNode(neighbour);
              TakeoverRebuildOperation takeoverRebuildOperation =
                  new TakeoverRebuildOperation(node);
              takeoverRebuildOperation.scheduleWithDelay(CanConfig.waitForTakeover);
              this.operationFinished(true);
            }
          }
          // own node is closest, but not brother
          else if (closestVidNeighbour
                  .getOverlayID()
                  .toString()
                  .equals(node.getLocalContact().getOverlayID().toString())
              && (node.getVIDNeighbours()[0]
                      .getOverlayID()
                      .toString()
                      .equals(neighbour.getOverlayID().toString())
                  || node.getVIDNeighbours()[1]
                      .getOverlayID()
                      .toString()
                      .equals(neighbour.getOverlayID().toString()))) {

            if (node.getMissingNode() == null) {
              node.setMissingNode(neighbour);

              CanOverlayContact n = null;
              if (node.getVIDNeighbours()[0]
                  .getArea()
                  .getVid()
                  .equals(neighbour.getArea().getVid())) n = node.getVIDNeighbours()[1];
              else n = node.getVIDNeighbours()[0];
              TakeoverReorganizeMsg leave =
                  new TakeoverReorganizeMsg(
                      (CanOverlayID) node.getOverlayID(),
                      n.getOverlayID(),
                      node.getLocalContact().clone(),
                      neighbour);
              node.getTransLayer().send(leave, n.getTransInfo(), node.getPort(), TransProtocol.TCP);

              TakeoverRebuildOperation takeoverRebuildOperation =
                  new TakeoverRebuildOperation(node);
              takeoverRebuildOperation.scheduleWithDelay(CanConfig.waitForTakeover);
              this.operationFinished(true);

            } else log.debug("node is allready set");
          } else { // send takeoverMsg
            CanOverlayContact receiver = null;
            if (closestVidNeighbour.getArea().getVid().numberCommon(neighbour.getArea().getVid())
                >= node.getLocalContact()
                    .getArea()
                    .getVid()
                    .numberCommon(neighbour.getArea().getVid())) receiver = closestVidNeighbour;
            else if (neighbour
                .getArea()
                .getVid()
                .getVIDList()
                .get(neighbour.getArea().getVid().getVIDList().size() - 1)
                .toString()
                .equals("0")) receiver = node.getVIDNeighbours()[0];
            else receiver = node.getVIDNeighbours()[1];

            log.debug(
                "send takeovermsg from "
                    + node.getLocalContact().getOverlayID().toString()
                    + " to "
                    + receiver.getOverlayID().toString());
            List<CanOverlayContact> neighboursOfMissing =
                node.getNeighboursOfCertainNeighbour(neighbour);
            CanOverlayContact[] vidNeighboursOfMissing =
                node.getVidNeighboursOfCertainNeighbour(neighbour);
            TakeoverMsg takeoverMsg =
                new TakeoverMsg(
                    node.getLocalContact().getOverlayID(),
                    receiver.getOverlayID(),
                    neighbour,
                    neighboursOfMissing,
                    vidNeighboursOfMissing);
            node.getTransLayer()
                .send(takeoverMsg, receiver.getTransInfo(), node.getPort(), TransProtocol.TCP);

            log.debug(
                "missing node detected and just removed, in node: "
                    + node.getLocalContact().getOverlayID().toString()
                    + " missing node: "
                    + neighbour.getOverlayID().toString());
            node.removeNeighbour(neighbour);
            this.takeoverOperation.takeoverReplyFinished(this.getOperationID());
          }
        } else {
          log.debug(
              "missing node detected and just removed, in node: "
                  + node.getLocalContact().getOverlayID().toString()
                  + " missing node: "
                  + neighbour.getOverlayID().toString());
          node.removeNeighbour(neighbour);
          this.takeoverOperation.takeoverReplyFinished(this.getOperationID());
        }
      } else {
        this.takeoverOperation.takeoverReplyFinished(this.getOperationID());
        this.operationFinished(true);
      }
    }
  }
 public OperationListener(CanNode master) {
   this.master = master;
   log.debug(Simulator.getSimulatedRealtime() + " new OperationListener");
 }
 public void scheduleAtTime(long time) {
   time = Math.max(time, Simulator.getCurrentTime());
   Simulator.scheduleEvent(this, time, this, SimulationEvent.Type.TIMEOUT_EXPIRED);
 }
 public void scheduleWithDelay(long delay) {
   long time = Simulator.getCurrentTime() + delay;
   scheduleAtTime(time);
 }