private void afterRemoveProcessing() {
   if (root instanceof InnerNode && root.getLength() == 0) {
     InnerNode<K, V> inner = (InnerNode<K, V>) root;
     this.root = inner.getFirstChild();
   }
   this.size--;
 }
Exemple #2
0
  /**
   * Remove an element from the right digit.
   *
   * @param pos position inside the right digit
   * @return resulting tree
   */
  private FingerTree<N, E> removeRight(final long pos) {
    if (right.length > 1) {
      // right digit cannot underflow, just delete the element
      return new DeepTree<>(left, leftSize, middle, remove(right, pos), size - 1);
    }

    // singleton digit might underflow
    final Node<N, E> node = right[0];

    if (!middle.isEmpty()) {
      // potentially balance with middle tree
      final InnerNode<N, E> last = (InnerNode<N, E>) middle.last();
      final Node<N, E> lastSub = last.getSub(last.arity() - 1);
      final NodeLike<N, E>[] rem = node.remove(lastSub, null, pos);
      final Node<N, E> newLastSub = (Node<N, E>) rem[0], newNode = (Node<N, E>) rem[1];

      if (newNode == null) {
        // nodes were merged
        final Node<N, E>[] newRight = last.children.clone();
        newRight[newRight.length - 1] = newLastSub;
        return new DeepTree<>(left, leftSize, middle.init(), newRight, size - 1);
      }

      @SuppressWarnings("unchecked")
      final Node<N, E>[] newRight = new Node[] {newNode};

      // replace last node in middle tree
      final Node<Node<N, E>, E> newLast = last.replaceLast(newLastSub);
      return new DeepTree<>(left, leftSize, middle.replaceLast(newLast), newRight, size - 1);
    }

    // balance with left digit
    final Node<N, E> lastLeft = left[left.length - 1];
    final NodeLike<N, E>[] rem = node.remove(lastLeft, null, pos);
    final Node<N, E> newLastLeft = (Node<N, E>) rem[0], newNode = (Node<N, E>) rem[1];
    if (newNode == null) {
      // nodes were merged
      if (left.length == 1) {
        // only one node left
        return new SingletonTree<>(newLastLeft);
      }

      @SuppressWarnings("unchecked")
      final Node<N, E>[] newRight = new Node[] {newLastLeft};
      return get(slice(left, 0, left.length - 1), newRight, size - 1);
    }

    @SuppressWarnings("unchecked")
    final Node<N, E>[] newRight = new Node[] {newNode};

    if (newLastLeft == lastLeft) {
      // deletion could be absorbed
      return get(left, leftSize, newRight, size - 1);
    }

    // adapt the left digit
    final Node<N, E>[] newLeft = left.clone();
    newLeft[newLeft.length - 1] = newLastLeft;
    return get(newLeft, newRight, size - 1);
  }
Exemple #3
0
  @Override
  public FingerTree<N, E> tail() {
    final long fstSize = left[0].size(), newSize = size - fstSize;

    if (left.length > 1) {
      // left digit is safe, just shrink it
      final Node<N, E>[] newLeft = slice(left, 1, left.length);
      return new DeepTree<>(newLeft, leftSize - fstSize, middle, right, newSize);
    }

    if (middle.isEmpty()) {
      // middle tree empty, make a tree from the right list
      if (right.length == 1) return new SingletonTree<>(right[0]);

      final int mid = right.length / 2;
      return get(slice(right, 0, mid), slice(right, mid, right.length), newSize);
    }

    // extract values for the left digit from the middle
    final InnerNode<N, E> head = (InnerNode<N, E>) middle.head();
    return new DeepTree<>(head.children, head.size(), middle.tail(), right, newSize);
  }
  public boolean colocate(LocatedKey treeKey) {
    List<InnerNode>[] allRoots = new List[this.keys.length];
    sleep();

    int cutoff = tree.getCutoff(true, tree.cutoffKey);
    BPlusTree.wrapper.startTransaction(false);
    tree.applyCutoff(treeKey, cutoff);
    BPlusTree.wrapper.endTransaction(true);

    boolean successful = false;
    while (!successful) {
      try {
        BPlusTree.wrapper.startTransaction(false);
        int i = 0;
        int s = 0;
        List<InnerNode> source = null;
        for (LocatedKey lrKey : this.keys) {
          allRoots[i] = BPlusTree.getLocalRoots(lrKey);
          if (allRoots[i] != null && allRoots[i].size() > 0) {
            source = allRoots[i];
            s = i;
            System.out.println("Found source for local roots with length: " + source.size());
          }
          i++;
        }

        int members = allRoots.length;
        int localRoots = source.size();
        int division = (int) Math.floor((localRoots + 0.0) / (members + 0.0));
        if (division == 0) {
          BPlusTree.wrapper.endTransaction(true);
          System.out.println("Division is zero, not co-locating! Had members: " + members);
          return false;
        }

        int groupFrom = s;
        int groupTo = -1;
        InnerNode toMove = null;
        source = new ArrayList<InnerNode>(source);

        for (int k = 0; k < allRoots.length; k++) {
          if (k == s) {
            continue;
          }

          List<InnerNode> otherRoots = allRoots[k];
          if (otherRoots == null) {
            otherRoots = new ArrayList<InnerNode>();
          } else {
            otherRoots = new ArrayList<InnerNode>(otherRoots);
          }

          groupTo = k;
          for (int l = 0; l < division; l++) {
            toMove = source.remove(source.size() - 1);
            toMove = toMove.startChangeGroup(this.keys[k].getGroup());
            otherRoots.add(toMove);

            BPlusTree.wrapper.endTransaction(true);
            System.out.println(
                "Async ColocationThread moved Root "
                    + toMove
                    + " from "
                    + this.keys[groupFrom].getGroup()
                    + " to "
                    + this.keys[groupTo].getGroup());
            BPlusTree.wrapper.startTransaction(false);
          }
          BPlusTree.setLocalRoots(this.keys[k], otherRoots);
        }
        BPlusTree.setLocalRoots(this.keys[s], source);

        BPlusTree.wrapper.endTransaction(true);
        successful = true;
      } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Colocation should not have exceptions");
        System.exit(-1);
        //		try { BPlusTree.wrapper.endTransaction(false); }
        //		catch (Exception e2) {
        //
        //		}
        //		sleep();
      }
    }

    return false;
  }
Exemple #5
0
  @Override
  public TreeSlice<N, E> slice(final long from, final long len) {
    if (from == 0 && len == size) return new TreeSlice<>(this);
    final long midSize = middle.size(), rightOff = leftSize + midSize;

    final long inLeft = from + len <= leftSize ? len : from < leftSize ? leftSize - from : 0;
    final long inRight = from >= rightOff ? len : from + len > rightOff ? from + len - rightOff : 0;

    @SuppressWarnings("unchecked")
    final NodeLike<N, E>[] buffer = new NodeLike[2 * MAX_DIGIT + 1];
    int inBuffer = splitDigit(left, from, inLeft, buffer, 0);
    if (inLeft == len) {
      if (inBuffer == 1) return new TreeSlice<>(buffer[0]);
      final int mid1 = inBuffer / 2;
      final Node<N, E>[] ls = slice(buffer, 0, mid1), rs = slice(buffer, mid1, inBuffer);
      return new TreeSlice<>(get(ls, rs, len));
    }

    final long inMiddle = len - inLeft - inRight;
    final FingerTree<Node<N, E>, E> mid;
    final TreeSlice<Node<N, E>, E> slice;
    if (inMiddle == 0) {
      mid = EmptyTree.getInstance();
      slice = new TreeSlice<>(mid);
    } else {
      final long midOff = from <= leftSize ? 0 : from - leftSize;
      slice = middle.slice(midOff, inMiddle);
      if (slice.isTree()) {
        mid = slice.getTree();
      } else {
        final NodeLike<N, E> sub = ((PartialInnerNode<N, E>) slice.getPartial()).sub;
        inBuffer = sub.append(buffer, inBuffer);
        mid = EmptyTree.getInstance();
      }
    }

    final long rightFrom = from < rightOff ? 0 : from - rightOff;
    if (mid.isEmpty()) {
      inBuffer = splitDigit(right, rightFrom, inRight, buffer, inBuffer);
      return slice.setNodes(buffer, inBuffer, len);
    }

    final FingerTree<Node<N, E>, E> mid2;
    if (inBuffer > 1 || buffer[0] instanceof Node) {
      mid2 = mid;
    } else {
      final InnerNode<N, E> head = (InnerNode<N, E>) mid.head();
      final int k = head.arity();
      inBuffer = head.getSub(0).append(buffer, inBuffer);
      for (int i = 1; i < k; i++) buffer[inBuffer++] = head.getSub(i);
      mid2 = mid.tail();
    }

    if (mid2.isEmpty()) {
      inBuffer = splitDigit(right, rightFrom, inRight, buffer, inBuffer);
      return slice.setNodes(buffer, inBuffer, len);
    }

    final Node<N, E>[] newLeft = slice(buffer, 0, inBuffer);
    inBuffer = splitDigit(right, rightFrom, inRight, buffer, 0);

    final FingerTree<Node<N, E>, E> mid3;
    final Node<N, E>[] newRight;
    if (inBuffer == 0) {
      mid3 = mid2.init();
      newRight = ((InnerNode<N, E>) mid2.last()).children;
    } else if (inBuffer > 1 || buffer[0] instanceof Node) {
      mid3 = mid2;
      newRight = slice(buffer, 0, inBuffer);
    } else {
      final NodeLike<N, E> partial = buffer[0];
      final InnerNode<N, E> last = (InnerNode<N, E>) mid2.last();
      final int k = last.arity();
      for (int i = 0; i < k; i++) buffer[i] = last.getSub(i);
      inBuffer = partial.append(buffer, k);
      mid3 = mid2.init();
      newRight = slice(buffer, 0, inBuffer);
    }

    return slice.setTree(get(newLeft, mid3, newRight, len));
  }
Exemple #6
0
  /**
   * Remove an element from the left digit.
   *
   * @param pos position inside the left digit
   * @return resulting tree
   */
  private FingerTree<N, E> removeLeft(final long pos) {
    if (left.length > 1) {
      // left digit cannot underflow, just delete the element
      return new DeepTree<>(remove(left, pos), leftSize - 1, middle, right, size - 1);
    }

    // singleton digit might underflow
    final Node<N, E> node = left[0];

    if (!middle.isEmpty()) {
      // next node for balancing is in middle tree
      final InnerNode<N, E> head = (InnerNode<N, E>) middle.head();
      final Node<N, E> first = head.getSub(0);
      final NodeLike<N, E>[] rem = node.remove(null, first, pos);
      final Node<N, E> newNode = (Node<N, E>) rem[1], newFirst = (Node<N, E>) rem[2];

      if (newNode == null) {
        // nodes were merged
        final Node<N, E>[] newLeft = head.children.clone();
        newLeft[0] = newFirst;
        return get(newLeft, middle.tail(), right, size - 1);
      }

      @SuppressWarnings("unchecked")
      final Node<N, E>[] newLeft = new Node[] {newNode};

      if (newFirst != first) {
        // nodes were balanced
        final FingerTree<Node<N, E>, E> newMid = middle.replaceHead(head.replaceFirst(newFirst));
        return new DeepTree<>(newLeft, newNode.size(), newMid, right, size - 1);
      }

      // no changes to this tree's structure
      return new DeepTree<>(newLeft, newNode.size(), middle, right, size - 1);
    }

    // potentially balance with right digit
    final NodeLike<N, E>[] rem = node.remove(null, right[0], pos);
    final Node<N, E> newNode = (Node<N, E>) rem[1], newFirstRight = (Node<N, E>) rem[2];

    if (newNode == null) {
      // nodes were merged
      if (right.length == 1) return new SingletonTree<>(newFirstRight);
      final int mid = right.length / 2;
      final Node<N, E>[] newLeft = slice(right, 0, mid);
      newLeft[0] = newFirstRight;
      return get(newLeft, middle, slice(right, mid, right.length), size - 1);
    }

    // structure does not change
    @SuppressWarnings("unchecked")
    final Node<N, E>[] newLeft = new Node[] {newNode};

    if (newFirstRight == right[0]) {
      // right digit stays the same
      return new DeepTree<>(newLeft, newLeft[0].size(), middle, right, size - 1);
    }

    // adapt the right digit
    final Node<N, E>[] newRight = right.clone();
    newRight[0] = newFirstRight;
    return new DeepTree<>(newLeft, newNode.size(), middle, newRight, size - 1);
  }