Example #1
0
  /**
   * Add a node to the overlay network topology.
   *
   * @param data unused for this hash ring; nodes are placed evenly based on current topology
   *     characteristics. You may safely pass 'null' to this method.
   * @return the location of the new node in the hash space.
   */
  @Override
  public BigInteger addNode(T data) throws HashTopologyException, HashException {
    /* Edge case: when there are no entries in the hash ring yet. */
    if (entryMap.values().size() == 0) {
      BigInteger pos;

      if (randomize) {
        /* Find a random location to start with */
        pos = function.randomHash();
      } else {
        pos = BigInteger.ZERO;
      }

      HashRingEntry firstEntry = new HashRingEntry(pos);
      entryMap.put(pos, firstEntry);

      return pos;
    }

    /* Edge case: only one entry in the hash ring */
    if (entryMap.values().size() == 1) {
      HashRingEntry firstEntry = entryMap.values().iterator().next();
      BigInteger halfSize = maxHash.divide(BigInteger.valueOf(2));
      BigInteger secondPos = firstEntry.position.add(halfSize);

      if (secondPos.compareTo(maxHash) > 0) {
        secondPos = secondPos.subtract(maxHash);
      }

      HashRingEntry secondEntry = new HashRingEntry(secondPos, firstEntry);
      firstEntry.neighbor = secondEntry;
      entryMap.put(secondPos, secondEntry);

      return secondPos;
    }

    /* Find the largest empty span of hash space */
    BigInteger largestSpan = BigInteger.ZERO;
    HashRingEntry largestEntry = null;
    for (HashRingEntry entry : entryMap.values()) {
      BigInteger len = lengthBetween(entry, entry.neighbor);
      if (len.compareTo(largestSpan) > 0) {
        largestSpan = len;
        largestEntry = entry;
      }
    }

    if (largestEntry == null) {
      return BigInteger.ONE.negate();
    }

    /* Put the new node in the middle of the largest span */
    BigInteger half = half(largestEntry, largestEntry.neighbor);
    addRingEntry(half, largestEntry);
    return half;
  }
Example #2
0
  /**
   * Insert a node into the hash ring internal data structures. Nodes are relinked with the proper
   * neighbors.
   *
   * @param position place in the hash space
   * @param predecessor the predecessor node in the hash space.
   */
  private void addRingEntry(BigInteger position, HashRingEntry predecessor)
      throws HashTopologyException {
    if (entryMap.get(position) != null) {
      /* Something is already here! */
      System.out.println(position);
      throw new HashTopologyException("Hash space exhausted!");
    }

    HashRingEntry newEntry = new HashRingEntry(position, predecessor.neighbor);
    predecessor.neighbor = newEntry;
    entryMap.put(position, newEntry);
  }