btree.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,613 行 · 第 1/3 页
JAVA
1,613 行
// copy the pointer from the left pointer setPointer(parentBuffer, parentOffset, getPointer(parentBuffer, parentOffset - tupleSize)); if (parentOffset - tupleSize < HEADER_SIZE) throw new IllegalStateException(); // shift the parent System.arraycopy(parentBuffer, parentOffset, parentBuffer, parentOffset - tupleSize, parentEnd - parentOffset); setLength(parentBuffer, parentLength - 1); // the new left.next value is the buffer's next value setPointer(leftBuffer, NEXT_OFFSET, getPointer(buffer, NEXT_OFFSET)); if (leftOffset < HEADER_SIZE) throw new IllegalStateException(); // append the buffer to the left buffer // XXX: leaf vs non-leaf? System.arraycopy(buffer, HEADER_SIZE, leftBuffer, leftOffset, length * tupleSize); setLength(leftBuffer, leftLength + length); return; } } long pointer = getPointer(parentBuffer, NEXT_OFFSET); if (pointer != blockId) { log.warning("BTree remove can't find matching block: " + debugId(blockId)); return; } int leftOffset = HEADER_SIZE + (parentLength - 1) * tupleSize; long leftPointer = getPointer(parentBuffer, leftOffset); setPointer(parentBuffer, NEXT_OFFSET, leftPointer); setLength(parentBuffer, parentLength - 1); // XXX: leaf vs non-leaf? // the new left.next value is the buffer's next value setPointer(leftBuffer, NEXT_OFFSET, getPointer(buffer, NEXT_OFFSET)); // append the buffer to the left buffer System.arraycopy(buffer, HEADER_SIZE, leftBuffer, HEADER_SIZE + leftLength * tupleSize, length * tupleSize); setLength(leftBuffer, leftLength + length); } /** * Returns the index to the right of the current one */ private long getRightBlockId(Block parent, long blockId) { byte []buffer = parent.getBuffer(); int length = getLength(buffer); int offset = HEADER_SIZE; int tupleSize = _tupleSize; int end = offset + length * tupleSize; for (; offset < end; offset += tupleSize) { long pointer = getPointer(buffer, offset); if (pointer == blockId) { if (offset + tupleSize < end) { return getPointer(buffer, offset + tupleSize); } else return getPointer(buffer, NEXT_OFFSET); } } return -1; } /** * Takes the first entry from the right block and moves it to the * last entry in the current block. * * @param parentBuffer the parent block buffer * @param rightBuffer the right block buffer * @param buffer the block's buffer * @param index the index of the block */ private void moveFromRight(byte []parentBuffer, byte []buffer, byte []rightBuffer, long blockId) { int parentLength = getLength(parentBuffer); int tupleSize = _tupleSize; int parentOffset = HEADER_SIZE; int parentEnd = parentOffset + parentLength * tupleSize; int rightLength = getLength(rightBuffer); int length = getLength(buffer); for (; parentOffset < parentEnd; parentOffset += tupleSize) { long pointer = getPointer(parentBuffer, parentOffset); if (pointer == blockId) break; } if (parentEnd <= parentOffset) { log.warning("Can't find buffer in deletion borrow right "); return; } // copy the first item in the right to the buffer System.arraycopy(rightBuffer, HEADER_SIZE, buffer, HEADER_SIZE + length * tupleSize, tupleSize); // shift the data in the right buffer System.arraycopy(rightBuffer, HEADER_SIZE + tupleSize, rightBuffer, HEADER_SIZE, (rightLength - 1) * tupleSize); // add the buffer length setLength(buffer, length + 1); // subtract from the right length setLength(rightBuffer, rightLength - 1); // copy the entry from the new buffer tail to the parent System.arraycopy(buffer, HEADER_SIZE + length * tupleSize + PTR_SIZE, parentBuffer, parentOffset + PTR_SIZE, tupleSize - PTR_SIZE); } /** * Merges the buffer with the right-most one. */ private void mergeRight(byte []parentBuffer, byte []buffer, byte []rightBuffer, long blockId) { int parentLength = getLength(parentBuffer); int tupleSize = _tupleSize; int parentOffset = HEADER_SIZE; int parentEnd = parentOffset + parentLength * tupleSize; int rightLength = getLength(rightBuffer); int length = getLength(buffer); for (; parentOffset < parentEnd; parentOffset += tupleSize) { long pointer = getPointer(parentBuffer, parentOffset); if (pointer == blockId) { // add space in the right buffer System.arraycopy(rightBuffer, HEADER_SIZE, rightBuffer, HEADER_SIZE + length * tupleSize, rightLength * tupleSize); // add the buffer to the right buffer System.arraycopy(buffer, HEADER_SIZE, rightBuffer, HEADER_SIZE, length * tupleSize); setLength(rightBuffer, length + rightLength); if (parentOffset < HEADER_SIZE) throw new IllegalStateException(); // remove the buffer's pointer from the parent System.arraycopy(parentBuffer, parentOffset + tupleSize, parentBuffer, parentOffset, parentEnd - parentOffset - tupleSize); setLength(parentBuffer, parentLength - 1); return; } } log.warning("BTree merge right can't find matching index: " + debugId(blockId)); } /** * Looks up the next block given the current block and the given key. */ private long lookupTuple(long blockId, byte []buffer, byte []keyBuffer, int keyOffset, int keyLength, boolean isLeaf) throws IOException { int length = getLength(buffer); int offset = HEADER_SIZE; int tupleSize = _tupleSize; int end = offset + length * tupleSize; long value; while (length > 0) { int tail = offset + tupleSize * length; int delta = tupleSize * (length / 2); int newOffset = offset + delta; if (newOffset < 0) { System.out.println("UNDERFLOW: " + debugId(blockId) + " LENGTH:" + length + " STU:" + getLength(buffer) + " DELTA:" + delta); throw new IllegalStateException("lookupTuple underflow newOffset:" + newOffset); } else if (newOffset > 65536) { System.out.println("OVERFLOW: " + debugId(blockId) + " LENGTH:" + length + " STU:" + getLength(buffer) + " DELTA:" + delta); throw new IllegalStateException("lookupTuple overflow newOffset:" + newOffset); } int cmp = _keyCompare.compare(keyBuffer, keyOffset, buffer, PTR_SIZE + newOffset, keyLength); if (cmp == 0) { value = getPointer(buffer, newOffset); if (value == 0 && ! isLeaf) throw new IllegalStateException("illegal 0 value at " + newOffset + " for block " + debugId(blockId)); return value; } else if (cmp > 0) { offset = newOffset + tupleSize; length = (tail - offset) / tupleSize; } else if (cmp < 0) { length = length / 2; } if (length > 0) { } else if (isLeaf) return 0; else if (cmp < 0) { value = getPointer(buffer, newOffset); if (value == 0 && ! isLeaf) throw new IllegalStateException("illegal 0 value at " + newOffset + " for block " + debugId(blockId)); return value; } else if (offset == end) { value = getPointer(buffer, NEXT_OFFSET); if (value == 0 && ! isLeaf) throw new IllegalStateException("illegal 0 value at " + newOffset + " for block " + debugId(blockId)); return value; } else { value = getPointer(buffer, offset); if (value == 0 && ! isLeaf) throw new IllegalStateException("illegal 0 value at " + newOffset + " for block " + debugId(blockId)); return value; } } if (isLeaf) return 0; else { value = getPointer(buffer, NEXT_OFFSET); if (value == 0 && ! isLeaf) throw new IllegalStateException("illegal 0 value at NEXT_OFFSET for block " + debugId(blockId)); return value; } } /** * Removes from the next block given the current block and the given key. */ private long removeLeafEntry(long blockIndex, byte []buffer, byte []keyBuffer, int keyOffset, int keyLength) throws IOException { int offset = HEADER_SIZE; int tupleSize = _tupleSize; int length = getLength(buffer); for (int i = 0; i < length; i++) { int cmp = _keyCompare.compare(keyBuffer, keyOffset, buffer, offset + PTR_SIZE, keyLength); if (0 < cmp) { offset += tupleSize; continue; } else if (cmp == 0) { int tupleLength = length * tupleSize; if (offset + tupleSize < HEADER_SIZE + tupleLength) { if (offset < HEADER_SIZE) throw new IllegalStateException(); System.arraycopy(buffer, offset + tupleSize, buffer, offset, HEADER_SIZE + tupleLength - offset - tupleSize); } setLength(buffer, length - 1); return i; } else { return 0; } } return 0; } private boolean isLeaf(byte []buffer) { return (getInt(buffer, FLAGS_OFFSET) & LEAF_FLAG) == 0; } private void setLeaf(byte []buffer, boolean isLeaf) { if (isLeaf) setInt(buffer, FLAGS_OFFSET, getInt(buffer, FLAGS_OFFSET) & ~LEAF_FLAG); else setInt(buffer, FLAGS_OFFSET, getInt(buffer, FLAGS_OFFSET) | LEAF_FLAG); } /** * Reads an int */ private int getInt(byte []buffer, int offset) { return (((buffer[offset + 0] & 0xff) << 24) + ((buffer[offset + 1] & 0xff) << 16) + ((buffer[offset + 2] & 0xff) << 8) + ((buffer[offset + 3] & 0xff))); } /** * Reads a pointer. */ private long getPointer(byte []buffer, int offset) { return (((buffer[offset + 0] & 0xffL) << 56) + ((buffer[offset + 1] & 0xffL) << 48) + ((buffer[offset + 2] & 0xffL) << 40) + ((buffer[offset + 3] & 0xffL) << 32) + ((buffer[offset + 4] & 0xffL) << 24) + ((buffer[offset + 5] & 0xffL) << 16) + ((buffer[offset + 6] & 0xffL) << 8) + ((buffer[offset + 7] & 0xffL))); } /** * Sets an int */ private void setInt(byte []buffer, int offset, int value) { buffer[offset + 0] = (byte) (value >> 24); buffer[offset + 1] = (byte) (value >> 16); buffer[offset + 2] = (byte) (value >> 8); buffer[offset + 3] = (byte) (value); } /** * Sets the length */ private void setLength(byte []buffer, int value) { if (value < 0 || BLOCK_SIZE / _tupleSize < value) { System.out.println("BAD-LENGTH: " + value); throw new IllegalArgumentException("BTree: bad length " + value); } setInt(buffer, LENGTH_OFFSET, value); } /** * Sets the length */ private int getLength(byte []buffer) { int value = getInt(buffer, LENGTH_OFFSET); if (value < 0 || value > 65536) { System.out.println("BAD-LENGTH: " + value); throw new IllegalArgumentException("BTree: bad length " + value); } return value; } /** * Sets a pointer. */ private void setPointer(byte []buffer, int offset, long value) { if (offset <= LENGTH_OFFSET) System.out.println("BAD_POINTER: " + offset); buffer[offset + 0] = (byte) (value >> 56); buffer[offset + 1] = (byte) (value >> 48); buffer[offset + 2] = (byte) (value >> 40); buffer[offset + 3] = (byte) (value >> 32); buffer[offset + 4] = (byte) (value >> 24); buffer[offset + 5] = (byte) (value >> 16); buffer[offset + 6] = (byte) (value >> 8); buffer[offset + 7] = (byte) (value); } /** * Opens the BTree. */ private void start() throws IOException { synchronized (this) { if (_isStarted) return; _isStarted = true; } } /** * Testing: returns the keys for a block */ public ArrayList<String> getBlockKeys(long blockIndex) throws IOException { long blockId = _store.addressToBlockId(blockIndex * BLOCK_SIZE); if (_store.isIndexBlock(blockId)) return null; Block block = _store.readBlock(blockId); block.read(); byte []buffer = block.getBuffer(); int length = getInt(buffer, LENGTH_OFFSET); int offset = HEADER_SIZE; int tupleSize = _tupleSize; ArrayList<String> keys = new ArrayList<String>(); for (int i = 0; i < length; i++) { keys.add(_keyCompare.toString(buffer, offset + i * tupleSize + PTR_SIZE, tupleSize - PTR_SIZE)); } block.free(); return keys; } public static BTree createTest(Path path, int keySize) throws IOException, java.sql.SQLException { Database db = new Database(); db.setPath(path); db.init(); Store store = new Store(db, "test", null); store.create(); Block block = store.allocateIndexBlock(); long blockId = block.getBlockId(); block.free(); return new BTree(store, blockId, keySize, new KeyCompare()); } public static BTree createStringTest(Path path, int keySize) throws IOException, java.sql.SQLException { Store store = Store.create(path); Block block = store.allocateIndexBlock(); long blockId = block.getBlockId(); block.free(); return new BTree(store, blockId, keySize, new StringKeyCompare()); } private String debugId(long blockId) { return "" + (blockId % Store.BLOCK_SIZE) + ":" + (blockId / Store.BLOCK_SIZE); } public void close() { Block rootBlock = _rootBlock; _rootBlock = null; if (rootBlock != null) rootBlock.free(); } public String toString() { return "BTree[" + _store + "," + (_rootBlockId / BLOCK_SIZE) + "]"; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?