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 + -
显示快捷键?