Beispiel #1
0
 private static Node rightRotate(Object token, Node n) {
   if (Debug) checkArgument(n.token == token);
   Node child = getNode(token, n.left);
   n.left = child.right;
   child.right = n;
   return child;
 }
Beispiel #2
0
  public static boolean treeEqual(
      NodeStack baseStack, Node base, NodeStack forkStack, Node fork, Comparator comparator) {
    if (base == Node.Null) {
      return fork == Node.Null;
    } else if (fork == Node.Null) {
      return base == Node.Null;
    } else {
      DiffIterator iterator =
          new DiffIterator(
              base,
              baseStack = new NodeStack(baseStack),
              fork,
              forkStack = new NodeStack(forkStack),
              Lists.newArrayList(Interval.Unbounded).iterator(),
              true,
              comparator);

      DiffIterator.DiffPair pair = new DiffIterator.DiffPair();
      boolean result = true;
      while (iterator.next(pair)) {
        if (!Node.valuesEqual(pair.base, pair.fork)) {
          result = false;
          break;
        }
      }

      baseStack.popStack();
      forkStack.popStack();

      return result;
    }
  }
Beispiel #3
0
  private static void minimum(Object token, Node n, NodeStack stack) {
    while (n.left != Null) {
      n.left = getNode(token, n.left);
      stack.push(n);
      n = n.left;
    }

    stack.push(n);
  }
Beispiel #4
0
 private static void successor(Object token, Node n, NodeStack stack) {
   if (n.right != Null) {
     n.right = getNode(token, n.right);
     stack.push(n);
     minimum(token, n.right, stack);
   } else {
     while (stack.top != null && n == stack.top.right) {
       n = stack.top;
       stack.pop();
     }
   }
 }
Beispiel #5
0
  public static Node blaze(
      BlazeResult result,
      Object token,
      NodeStack stack,
      Node root,
      Object key,
      Comparator comparator) {
    if (key == null) throw new NullPointerException();

    if (root == null) {
      root = Null;
    }

    if (Debug) {
      token = new Object();
      validate(null, root);
    }

    stack = new NodeStack(stack);
    Node newRoot = getNode(token, root);

    Node old = root;
    Node new_ = newRoot;
    while (old != Null) {
      int difference = Compare.compare(key, old.key, comparator);
      if (difference < 0) {
        stack.push(new_);
        old = old.left;
        new_ = new_.left = getNode(token, old);
      } else if (difference > 0) {
        stack.push(new_);
        old = old.right;
        new_ = new_.right = getNode(token, old);
      } else {
        result.node = new_;
        stack.popStack();
        if (Debug) {
          validate(root, newRoot);
        }
        return newRoot;
      }
    }

    new_.key = key;
    result.node = new_;

    // rebalance
    new_.red = true;

    while (stack.top != null && stack.top.red) {
      if (stack.top == stack.peek().left) {
        if (stack.peek().right.red) {
          stack.top.red = false;
          stack.peek().right = getNode(token, stack.peek().right);
          stack.peek().right.red = false;
          stack.peek().red = true;
          new_ = stack.peek();
          stack.pop(2);
        } else {
          if (new_ == stack.top.right) {
            new_ = stack.top;
            stack.pop();

            Node n = leftRotate(token, new_);
            if (stack.top.right == new_) {
              stack.top.right = n;
            } else {
              stack.top.left = n;
            }
            stack.push(n);
          }
          stack.top.red = false;
          stack.peek().red = true;

          Node n = rightRotate(token, stack.peek());
          if (stack.index <= stack.base + 1) {
            newRoot = n;
          } else if (stack.peek(1).right == stack.peek()) {
            stack.peek(1).right = n;
          } else {
            stack.peek(1).left = n;
          }
          // done
        }
      } else {
        // this is just the above code with left and right swapped:
        if (stack.peek().left.red) {
          stack.top.red = false;
          stack.peek().left = getNode(token, stack.peek().left);
          stack.peek().left.red = false;
          stack.peek().red = true;
          new_ = stack.peek();
          stack.pop(2);
        } else {
          if (new_ == stack.top.left) {
            new_ = stack.top;
            stack.pop();

            Node n = rightRotate(token, new_);
            if (stack.top.right == new_) {
              stack.top.right = n;
            } else {
              stack.top.left = n;
            }
            stack.push(n);
          }
          stack.top.red = false;
          stack.peek().red = true;

          Node n = leftRotate(token, stack.peek());
          if (stack.index <= stack.base + 1) {
            newRoot = n;
          } else if (stack.peek(1).right == stack.peek()) {
            stack.peek(1).right = n;
          } else {
            stack.peek(1).left = n;
          }
          // done
        }
      }
    }

    newRoot.red = false;

    stack.popStack();
    if (Debug) {
      validate(root, newRoot);
    }
    return newRoot;
  }
Beispiel #6
0
  public static Node delete(
      Object token, NodeStack stack, Node root, Object key, Comparator comparator) {
    if (Debug) {
      token = new Object();
      validate(null, root);
    }

    if (root == Null) {
      return root;
    } else if (root.left == Null && root.right == Null) {
      if (Compare.equal(key, root.key, comparator)) {
        return Null;
      } else {
        return root;
      }
    }

    stack = new NodeStack(stack);
    Node newRoot = getNode(token, root);

    Node old = root;
    Node new_ = newRoot;
    while (old != Null) {
      if (key == null) throw new NullPointerException();
      if (old.key == null) {
        throw new NullPointerException();
      }
      int difference = Compare.compare(key, old.key, comparator);
      if (difference < 0) {
        stack.push(new_);
        old = old.left;
        new_ = new_.left = getNode(token, old);
      } else if (difference > 0) {
        stack.push(new_);
        old = old.right;
        new_ = new_.right = getNode(token, old);
      } else {
        break;
      }
    }

    if (old == Null) {
      if (stack.top.left == new_) {
        stack.top.left = Null;
      } else {
        stack.top.right = Null;
      }
      stack.popStack();
      return root;
    }

    Node dead;
    if (new_.left == Null || new_.right == Null) {
      dead = new_;
    } else {
      successor(token, new_, stack);
      dead = stack.top;
      stack.pop();
    }

    Node child;
    if (dead.left != Null) {
      child = getNode(token, dead.left);
    } else if (dead.right != Null) {
      child = getNode(token, dead.right);
    } else {
      child = Null;
    }

    if (stack.top == null) {
      child.red = false;
      stack.popStack();
      if (Debug) {
        validate(root, child);
      }
      return child;
    } else if (dead == stack.top.left) {
      stack.top.left = child;
    } else {
      stack.top.right = child;
    }

    if (dead != new_) {
      new_.key = dead.key;
      new_.value = dead.value;
    }

    if (!dead.red) {
      // rebalance
      while (stack.top != null && !child.red) {
        if (Debug) checkArgument(stack.top.token == token);
        if (child == stack.top.left) {
          Node sibling = stack.top.right = getNode(token, stack.top.right);
          if (sibling.red) {
            if (Debug) checkArgument(sibling.token == token);
            sibling.red = false;
            stack.top.red = true;

            Node n = leftRotate(token, stack.top);
            if (stack.index == stack.base) {
              newRoot = n;
            } else if (stack.peek().right == stack.top) {
              if (Debug) checkArgument(stack.peek().token == token);
              stack.peek().right = n;
            } else {
              if (Debug) checkArgument(stack.peek().token == token);
              stack.peek().left = n;
            }
            Node parent = stack.top;
            stack.top = n;
            stack.push(parent);

            sibling = stack.top.right = getNode(token, stack.top.right);
          }

          if (!(sibling.left.red || sibling.right.red)) {
            if (Debug) checkArgument(sibling.token == token);
            sibling.red = true;
            child = stack.top;
            stack.pop();
          } else {
            if (!sibling.right.red) {
              sibling.left = getNode(token, sibling.left);
              sibling.left.red = false;

              if (Debug) checkArgument(sibling.token == token);
              sibling.red = true;
              sibling = stack.top.right = rightRotate(token, sibling);
            }

            if (Debug) checkArgument(sibling.token == token);
            sibling.red = stack.top.red;
            stack.top.red = false;

            sibling.right = getNode(token, sibling.right);
            sibling.right.red = false;

            Node n = leftRotate(token, stack.top);
            if (stack.index == stack.base) {
              newRoot = n;
            } else if (stack.peek().right == stack.top) {
              if (Debug) checkArgument(stack.peek().token == token);
              stack.peek().right = n;
            } else {
              if (Debug) checkArgument(stack.peek().token == token);
              stack.peek().left = n;
            }

            child = newRoot;
            stack.clear();
          }
        } else {
          // this is just the above code with left and right swapped:
          Node sibling = stack.top.left = getNode(token, stack.top.left);
          if (sibling.red) {
            if (Debug) checkArgument(sibling.token == token);
            sibling.red = false;
            stack.top.red = true;

            Node n = rightRotate(token, stack.top);
            if (stack.index == stack.base) {
              newRoot = n;
            } else if (stack.peek().left == stack.top) {
              if (Debug) checkArgument(stack.peek().token == token);
              stack.peek().left = n;
            } else {
              if (Debug) checkArgument(stack.peek().token == token);
              stack.peek().right = n;
            }
            Node parent = stack.top;
            stack.top = n;
            stack.push(parent);

            sibling = stack.top.left = getNode(token, stack.top.left);
          }

          if (!(sibling.right.red || sibling.left.red)) {
            if (Debug) checkArgument(sibling.token == token);
            sibling.red = true;
            child = stack.top;
            stack.pop();
          } else {
            if (!sibling.left.red) {
              sibling.right = getNode(token, sibling.right);
              sibling.right.red = false;

              if (Debug) checkArgument(sibling.token == token);
              sibling.red = true;
              sibling = stack.top.left = leftRotate(token, sibling);
            }

            if (Debug) checkArgument(sibling.token == token);
            sibling.red = stack.top.red;
            stack.top.red = false;

            sibling.left = getNode(token, sibling.left);
            sibling.left.red = false;

            Node n = rightRotate(token, stack.top);
            if (stack.index == stack.base) {
              newRoot = n;
            } else if (stack.peek().left == stack.top) {
              if (Debug) checkArgument(stack.peek().token == token);
              stack.peek().left = n;
            } else {
              if (Debug) checkArgument(stack.peek().token == token);
              stack.peek().right = n;
            }

            child = newRoot;
            stack.clear();
          }
        }
      }

      if (Debug) checkArgument(child.token == token);
      child.red = false;
    }

    stack.popStack();
    if (Debug) {
      validate(root, newRoot);
    }
    return newRoot;
  }
Beispiel #7
0
 static {
   Null.left = Null;
   Null.right = Null;
   Null.value = Null;
 }
Beispiel #8
0
  public static MyRevision mergeRevisions(
      MyRevision base,
      MyRevision left,
      MyRevision right,
      ConflictResolver conflictResolver,
      ForeignKeyResolver foreignKeyResolver) {
    // System.out.println("base:");
    // Node.dump(base.root, System.out, 0);
    // System.out.println("left:");
    // Node.dump(left.root, System.out, 0);
    // System.out.println("right:");
    // Node.dump(right.root, System.out, 0);

    if (base.equals(right) || left.equals(right)) {
      return left;
    } else if (base.equals(left)) {
      if (left.equals(right)) {
        return left;
      } else {
        return right;
      }
    }

    // The merge builds a new revision starting with the specified
    // left revision via a process which consists of the following
    // steps:
    //
    //  1. Merge the primary key data trees of each table and delete
    //     obsolete index and view data trees.
    //
    //  2. Update non-primary-key index and view data trees, removing
    //     obsolete rows and adding new or updated ones.
    //
    //  3. Build data trees for any new indexes and views added.
    //
    //  4. Verify foreign key constraints.

    MyRevisionBuilder builder = new MyRevisionBuilder(new Object(), left, new NodeStack());

    Set<Index> indexes = new TreeSet<Index>();
    Set<Index> newIndexes = new TreeSet<Index>();

    Set<View> views = new TreeSet<View>();
    Set<View> newViews = new TreeSet<View>();

    NodeStack baseStack = new NodeStack();
    NodeStack leftStack = new NodeStack();
    NodeStack rightStack = new NodeStack();

    {
      MergeIterator[] iterators = new MergeIterator[Constants.MaxDepth + 1];
      iterators[0] =
          new MergeIterator(
              base.root,
              baseStack,
              left.root,
              leftStack,
              right.root,
              rightStack,
              Compare.TableComparator);

      int depth = 0;
      int bottom = -1;
      Table table = null;
      MergeIterator.MergeTriple triple = new MergeIterator.MergeTriple();

      // merge primary key data trees of each table, deleting obsolete
      // rows from any other index data trees as we go
      while (true) {
        if (iterators[depth].next(triple)) {
          expect(triple.base != Node.Null && triple.left != Node.Null && triple.right != Node.Null);

          Comparator comparator = iterators[depth].comparator;

          boolean descend = false;
          boolean conflict = false;
          if (triple.base == null) {
            if (triple.left == null) {
              if (depth != Constants.IndexDataDepth || ((Index) triple.right.key).isPrimary()) {
                builder.insertOrUpdate(depth, triple.right.key, comparator, triple.right.value);
              }
            } else if (triple.right == null) {
              // do nothing -- left already has insert
            } else if (depth == bottom) {
              if (Compare.equal(triple.left.value, triple.right.value)) {
                // do nothing -- inserts match and left already has it
              } else {
                conflict = true;
              }
            } else {
              descend = true;
            }
          } else if (triple.left != null) {
            if (triple.right != null) {
              if (triple.left == triple.base) {
                if (depth == Constants.IndexDataDepth) {
                  indexes.remove(triple.right.key);
                }
                builder.insertOrUpdate(depth, triple.right.key, comparator, triple.right.value);
              } else if (triple.right == triple.base) {
                // do nothing -- left already has update
              } else if (depth == bottom) {
                if (Compare.equal(triple.left.value, triple.right.value)
                    || Compare.equal(triple.base.value, triple.right.value)) {
                  // do nothing -- updates match or only left changed,
                  // and left already has it
                } else if (Compare.equal(triple.base.value, triple.left.value)) {
                  builder.insertOrUpdate(depth, triple.right.key, comparator, triple.right.value);
                } else {
                  conflict = true;
                }
              } else {
                descend = true;
              }
            } else if (depth != bottom) {
              descend = true;
            } else {
              builder.deleteKey(depth, triple.left.key, comparator);
            }
          } else if (depth != bottom) {
            descend = true;
          } else {
            // do nothing -- left already has delete
          }

          Object key =
              triple.base == null
                  ? (triple.left == null ? triple.right.key : triple.left.key)
                  : triple.base.key;

          if (conflict) {
            Object[] primaryKeyValues = new Object[depth - Constants.IndexDataBodyDepth];

            for (int i = 0; i < primaryKeyValues.length; ++i) {
              primaryKeyValues[i] = builder.keys[i + Constants.IndexDataBodyDepth];
            }

            Object result =
                conflictResolver.resolveConflict(
                    table,
                    (Column<?>) key,
                    primaryKeyValues,
                    triple.base == null ? null : triple.base.value,
                    triple.left.value,
                    triple.right.value);

            if (Compare.equal(result, triple.left.value)) {
              // do nothing -- left already has insert
            } else if (result == null) {
              builder.deleteKey(depth, key, comparator);
            } else {
              builder.insertOrUpdate(depth, key, comparator, result);
            }
          } else if (descend) {
            Comparator nextComparator;
            if (depth == Constants.TableDataDepth) {
              table = (Table) key;

              if (Node.pathFind(
                      left.root,
                      Constants.ViewTable,
                      Compare.TableComparator,
                      Constants.ViewTableIndex,
                      Compare.IndexComparator,
                      table,
                      Constants.ViewTableColumn.comparator)
                  != Node.Null) {
                // skip views -- we'll handle them later
                continue;
              }

              nextComparator = Compare.IndexComparator;

              {
                DiffIterator indexIterator =
                    new DiffIterator(
                        Node.pathFind(
                            left.root,
                            Constants.IndexTable,
                            Compare.TableComparator,
                            Constants.IndexTable.primaryKey,
                            Compare.IndexComparator,
                            table,
                            Constants.TableColumn.comparator),
                        baseStack = new NodeStack(baseStack),
                        Node.pathFind(
                            builder.result.root,
                            Constants.IndexTable,
                            Compare.TableComparator,
                            Constants.IndexTable.primaryKey,
                            Compare.IndexComparator,
                            table,
                            Constants.TableColumn.comparator),
                        leftStack = new NodeStack(leftStack),
                        list(Interval.Unbounded).iterator(),
                        true,
                        Constants.IndexColumn.comparator);

                DiffIterator.DiffPair pair = new DiffIterator.DiffPair();
                while (indexIterator.next(pair)) {
                  if (pair.base != null) {
                    if (pair.fork != null) {
                      Index index = (Index) pair.base.key;
                      if (!index.equals(table.primaryKey)) {
                        indexes.add(index);
                      }
                    } else {
                      builder.setKey(Constants.TableDataDepth, table, Compare.TableComparator);
                      builder.deleteKey(
                          Constants.IndexDataDepth, pair.base.key, Compare.IndexComparator);
                    }
                  } else if (pair.fork != null) {
                    Index index = (Index) pair.fork.key;
                    if (!index.equals(table.primaryKey)) {
                      newIndexes.add(index);
                    }
                  }
                }

                baseStack = baseStack.popStack();
                leftStack = leftStack.popStack();
              }

              {
                DiffIterator indexIterator =
                    new DiffIterator(
                        Node.pathFind(
                            left.root,
                            Constants.ViewTable,
                            Compare.TableComparator,
                            Constants.ViewTable.primaryKey,
                            Compare.IndexComparator,
                            table,
                            Constants.TableColumn.comparator),
                        baseStack = new NodeStack(baseStack),
                        Node.pathFind(
                            builder.result.root,
                            Constants.ViewTable,
                            Compare.TableComparator,
                            Constants.ViewTable.primaryKey,
                            Compare.IndexComparator,
                            table,
                            Constants.TableColumn.comparator),
                        leftStack = new NodeStack(leftStack),
                        list(Interval.Unbounded).iterator(),
                        true,
                        Constants.ViewColumn.comparator);

                DiffIterator.DiffPair pair = new DiffIterator.DiffPair();
                while (indexIterator.next(pair)) {
                  if (pair.base != null) {
                    View view = (View) pair.base.key;
                    if (pair.fork != null) {
                      views.add(view);
                    } else {
                      builder.deleteKey(
                          Constants.TableDataDepth, view.table, Compare.TableComparator);
                    }
                  } else if (pair.fork != null) {
                    newViews.add((View) pair.fork.key);
                  }
                }

                baseStack = baseStack.popStack();
                leftStack = leftStack.popStack();
              }
            } else if (depth == Constants.IndexDataDepth) {
              Index index = (Index) key;

              if (Compare.equal(index, table.primaryKey, comparator)) {
                bottom = index.columns.size() + Constants.IndexDataBodyDepth;
              } else {
                // skip non-primary-key index data trees -- we'll handle
                // those later
                continue;
              }

              nextComparator = table.primaryKey.columns.get(0).comparator;
            } else if (depth + 1 == bottom) {
              nextComparator = Compare.ColumnComparator;
            } else {
              nextComparator =
                  table.primaryKey.columns.get(depth + 1 - Constants.IndexDataBodyDepth).comparator;
            }

            builder.setKey(depth, key, comparator);

            ++depth;

            iterators[depth] =
                new MergeIterator(
                    triple.base == null ? Node.Null : (Node) triple.base.value,
                    baseStack = new NodeStack(baseStack),
                    triple.left == null ? Node.Null : (Node) triple.left.value,
                    leftStack = new NodeStack(leftStack),
                    triple.right == null ? Node.Null : (Node) triple.right.value,
                    rightStack = new NodeStack(rightStack),
                    nextComparator);
          }
        } else if (depth == 0) {
          break;
        } else {
          iterators[depth] = null;

          --depth;

          baseStack = baseStack.popStack();
          leftStack = leftStack.popStack();
          rightStack = rightStack.popStack();
        }
      }
    }

    // Update non-primary-key index data trees
    for (Index index : indexes) {
      builder.updateIndexTree(index, left, leftStack, baseStack);
    }

    // Update view data trees
    for (View view : views) {
      builder.updateViewTree(view, left, leftStack, baseStack);
    }

    // build data trees for any new indexes
    for (Index index : newIndexes) {
      builder.updateIndexTree(index, MyRevision.Empty, leftStack, baseStack);
    }

    // build data trees for any new views
    for (View view : newViews) {
      builder.updateViewTree(view, MyRevision.Empty, leftStack, baseStack);
    }

    // verify all foreign key constraints
    ForeignKeys.checkForeignKeys(
        leftStack, left, baseStack, builder, rightStack, foreignKeyResolver, null);

    ForeignKeys.checkForeignKeys(
        rightStack, right, baseStack, builder, leftStack, foreignKeyResolver, null);

    // System.out.println("merge base");
    // Node.dump(base.root, System.out, 1);
    // System.out.println("merge left");
    // Node.dump(left.root, System.out, 1);
    // System.out.println("merge right");
    // Node.dump(right.root, System.out, 1);
    // System.out.println("merge result");
    // Node.dump(builder.result.root, System.out, 1);
    // System.out.println();

    if (left.equals(builder.result)) {
      return left;
    } else if (base.equals(builder.result)) {
      return base;
    } else {
      return builder.result;
    }
  }