/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.github.geophile.erdo.map.mergescan; import com.github.geophile.erdo.AbstractKey; import java.io.IOException; class FastMergeNode extends FastNode { public String toString() { return String.format("FastMergeNode(#%s)", position); } public void prime() throws IOException, InterruptedException { left.prime(); right.prime(); promote(); } public void fastPromote() throws IOException, InterruptedException { if (left.key != null && right.key != null) { int c = compareChildKeys(); if ((c & LEFT_BEFORE_RIGHT) != 0) { key = left.key; record = left.record; left.promote(); } else if ((c & RIGHT_BEFORE_LEFT) != 0) { key = right.key; record = right.record; right.promote(); } else { if ((c & KEY_RANGE) != 0) { left.goSlow(); right.goSlow(); promote(); } else { Node keep = null; switch (mergeCursor.merger.merge(left.key, right.key)) { case LEFT: keep = left; break; case RIGHT: keep = right; break; } key = keep.key; record = keep.record; left.promote(); right.promote(); } } } else if (left.key == null) { key = right.key; record = right.record; right.promote(); } else { key = left.key; record = left.record; left.promote(); } } @Override protected void dump(int level) { super.dump(level); left.dump(level + 1); right.dump(level + 1); } public FastMergeNode(MergeCursor mergeCursor, int position, FastNode left, FastNode right, boolean forward) { super(position, forward); this.mergeCursor = mergeCursor; this.left = left; this.right = right; } private int compareChildKeys() { AbstractKey leftKey = left.key; AbstractKey rightKey = right.key; boolean isLeftRange = leftKey instanceof MultiRecordKey; boolean isRightRange = rightKey instanceof MultiRecordKey; int c; if (isLeftRange == isRightRange) { c = leftKey.compareTo(rightKey); } else if (isLeftRange) { MultiRecordKey leftMultiRecordKey = (MultiRecordKey) leftKey; c = leftMultiRecordKey.hi() != null && leftMultiRecordKey.hi().compareTo(rightKey) <= 0 ? -1 : leftMultiRecordKey.lo() != null && leftMultiRecordKey.lo().compareTo(rightKey) > 0 ? 1 : 0; } else /* isRightRange */ { MultiRecordKey rightMultiRecordKey = (MultiRecordKey) rightKey; c = rightMultiRecordKey.lo() != null && leftKey.compareTo(rightMultiRecordKey.lo()) < 0 ? -1 : rightMultiRecordKey.hi() != null && leftKey.compareTo(rightMultiRecordKey.hi()) >= 0 ? 1 : 0; } if (!forward) { c = -c; } boolean leftBeforeRight = c < 0; boolean rightBeforeLeft = c > 0; return (isLeftRange || isRightRange ? KEY_RANGE : 0) | (leftBeforeRight ? LEFT_BEFORE_RIGHT : 0) | (rightBeforeLeft ? RIGHT_BEFORE_LEFT : 0); } // Class state private static final int KEY_RANGE = 0x1; private static final int LEFT_BEFORE_RIGHT = 0x2; private static final int RIGHT_BEFORE_LEFT = 0x4; // Object state private final MergeCursor mergeCursor; private FastNode left; private FastNode right; }