예제 #1
0
  /** {@inheritDoc} */
  @Override
  public final Set<Entry> retrieveEntries(ID id) throws CommunicationException {

    // Possible, but rare situation: a new node has joined which now is
    // responsible for the id!
    if (this.references.getPredecessor() != null
        && !id.isInInterval(this.references.getPredecessor().getNodeID(), this.nodeID)) {
      this.logger.fatal(
          "The rare situation has occured at time "
              + System.currentTimeMillis()
              + ", id to look up="
              + id
              + ", id of local node="
              + this.nodeID
              + ", id of predecessor="
              + this.references.getPredecessor().getNodeID());
      return this.references.getPredecessor().retrieveEntries(id);
    }

    // return entries from local repository
    // for this purpose create a copy of the Set in order to allow the
    // thread retrieving the entries to modify the Set without modifying the
    // internal Set of entries. sven
    return this.entries.getEntries(id);
  }
예제 #2
0
  /**
   * Determines the closest preceding node for the given ID based on finger table, successor list,
   * and predecessor, but without testing the node's liveliness.
   *
   * @param key ID to find closest preceding node for.
   * @throws NullPointerException If ID is <code>null</code>.
   * @return Reference on closest preceding node.
   */
  final synchronized Node getClosestPrecedingNode(ID key) {

    if (key == null) {
      NullPointerException e = new NullPointerException("ID may not be null!");
      this.logger.error("Null pointer", e);
      throw e;
    }

    Map<ID, Node> foundNodes = new HashMap<ID, Node>();
    // determine closest preceding reference of finger table
    Node closestNodeFT = this.fingerTable.getClosestPrecedingNode(key);
    if (closestNodeFT != null) {
      foundNodes.put(closestNodeFT.getNodeID(), closestNodeFT);
    }

    // determine closest preceding reference of successor list
    Node closestNodeSL = this.successorList.getClosestPrecedingNode(key);
    if (closestNodeSL != null) {
      foundNodes.put(closestNodeSL.getNodeID(), closestNodeSL);
    }

    // predecessor is appropriate only if it precedes the given id
    Node predecessorIfAppropriate = null;
    if (this.predecessor != null && key.isInInterval(this.predecessor.getNodeID(), this.localID)) {
      predecessorIfAppropriate = this.predecessor;
      foundNodes.put(this.predecessor.getNodeID(), predecessor);
    }

    // with three references which may be null, there are eight (8) cases we
    // have to enumerate...
    Node closestNode = null;
    List<ID> orderedIDList = new ArrayList<ID>(foundNodes.keySet());
    orderedIDList.add(key);
    int sizeOfList = orderedIDList.size();
    // size of list must be greater than one to not only contain the key.
    // if (sizeOfList > 1) {

    /*
     * Sort list in ascending order
     */
    Collections.sort(orderedIDList);
    /*
     * The list item with one index lower than that of the key must be the
     * id of the closest predecessor or the key.
     */
    int keyIndex = orderedIDList.indexOf(key);
    /*
     * As all ids are located on a ring if the key is the first item in the
     * list we have to select the last item as predecessor with help of this
     * calculation.
     */
    int index = (sizeOfList + (keyIndex - 1)) % sizeOfList;
    /*
     * Get the references to the node from the map of collected nodes.
     */
    ID idOfclosestNode = orderedIDList.get(index);
    closestNode = foundNodes.get(idOfclosestNode);
    if (closestNode == null) {
      throw new NullPointerException("closestNode must not be null!");
    }

    /*
     * Following code is too complicated.
     */
    // if (closestNodeFT == null) {
    // if (closestNodeSL == null) {
    // if (predecessorIfAppropriate == null) {
    // // no reference is appropriate
    // closestNode = null;
    // } else {
    // // only predecessor is appropriate (case should not occur,
    // // but anyway...
    // closestNode = predecessorIfAppropriate;
    // }
    // } else {
    // if (predecessorIfAppropriate == null) {
    // // only reference of successor list is appropriate
    // closestNode = closestNodeSL;
    // } else {
    // // either predecessor or reference of successor list is
    // // appropriate; determine one of both
    // if (predecessorIfAppropriate.nodeID.isInInterval(
    // closestNodeSL.nodeID, key)) {
    // closestNode = predecessorIfAppropriate;
    // } else {
    // closestNode = closestNodeSL;
    // }
    // }
    // }
    // } else {
    // if (closestNodeSL == null) {
    // if (predecessorIfAppropriate == null) {
    // // only reference of finger table is appropriate
    // closestNode = closestNodeFT;
    // } else {
    // // either predecessor or reference of finger table is
    // // appropriate; determine one of both
    // if (predecessorIfAppropriate.nodeID.isInInterval(
    // closestNodeFT.nodeID, key)) {
    // closestNode = predecessorIfAppropriate;
    // } else {
    // closestNode = closestNodeFT;
    // }
    // }
    // } else {
    // if (predecessorIfAppropriate == null) {
    // // either reference of successor list or reference of finger
    // // table is appropriate; determine one of both
    // if (closestNodeSL.nodeID.isInInterval(closestNodeFT.nodeID,
    // key)) {
    // closestNode = closestNodeSL;
    // } else {
    // closestNode = closestNodeFT;
    // }
    // } else {
    // // either of the three reference is appropriate; determine
    // // first one of the references of successor list and finger
    // // table is more appropriate and afterwards compare with
    // // predecessor
    // if (closestNodeSL.nodeID.isInInterval(closestNodeFT.nodeID,
    // key)) {
    // if (predecessorIfAppropriate.nodeID.isInInterval(
    // closestNodeSL.nodeID, key)) {
    // closestNode = predecessorIfAppropriate;
    // } else {
    // closestNode = closestNodeSL;
    // }
    // } else {
    // if (predecessorIfAppropriate.nodeID.isInInterval(
    // closestNodeFT.nodeID, key)) {
    // closestNode = predecessorIfAppropriate;
    // } else {
    // closestNode = closestNodeFT;
    // }
    // }
    // }
    // }
    // }
    if (this.logger.isEnabledFor(DEBUG)) {
      this.logger.debug(
          "Closest preceding node of ID "
              + key
              + " at node "
              + this.localID.toString()
              + " is "
              + closestNode.getNodeID()
              + " with closestNodeFT="
              + (closestNodeFT == null ? "null" : "" + closestNodeFT.getNodeID())
              + " and closestNodeSL="
              + (closestNodeSL == null ? "null" : "" + closestNodeSL.getNodeID())
              + " and predecessor (only if it precedes given ID)="
              + (predecessorIfAppropriate == null
                  ? "null"
                  : "" + predecessorIfAppropriate.getNodeID()));
    }
    return closestNode;
  }