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; }
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; } }
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); }
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(); } } }
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; }
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; }
static { Null.left = Null; Null.right = Null; Null.value = Null; }
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; } }