recordstoreindex.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,179 行 · 第 1/3 页
JAVA
1,179 行
* Gets the offset to the root of the recordId tree. * * @exception IOException if there is an error accessing the index file * * @return the offset of the recordId tree root */ int getRecordIdRootOffset() throws IOException { return RecordStoreUtil.getInt(idxHeader, IDX1_ID_ROOT); } /** * Sets the offset to the root of the recordId tree. * * @param newOffset the new root offset * * @exception IOException if there is an error accessing the index file */ void setRecordIdRootOffset(int newOffset) throws IOException { RecordStoreUtil.putInt(newOffset, idxHeader, IDX1_ID_ROOT); idxFile.seek(0); idxFile.write(idxHeader); idxFile.commitWrite(); } /** * Gets the offset to the root of the free block tree. * * @exception IOException if there is an error accessing the index file * * @return the offset of the free block tree */ int getFreeBlockRootOffset() throws IOException { return RecordStoreUtil.getInt(idxHeader, IDX2_FREE_BLOCK_ROOT); } /** * Sets the offset to the root of the free block tree. * * @param newOffset the new root offset * * @exception IOException if there is an error accessing the index file */ void setFreeBlockRootOffset(int newOffset) throws IOException { RecordStoreUtil.putInt(newOffset, idxHeader, IDX2_FREE_BLOCK_ROOT); idxFile.seek(0); idxFile.write(idxHeader); idxFile.commitWrite(); } /** * node allocation and free management */ /** * Returns the offset to a free node if one exists. Otherwise, * returns the offset of a newly create node. * * @exception IOException if there is an error accessing the index file * * @return the offset the new node in the index file */ private int allocateNode() throws IOException { // check if there is a free node to use int loc_offset = RecordStoreUtil.getInt(idxHeader, IDX3_FREE_NODE_HEAD); if (loc_offset == 0) { // no free blocks, add one to the end of the index file loc_offset = RecordStoreUtil.getInt(idxHeader, IDX0_SIZE); RecordStoreUtil.putInt(loc_offset + NODE_SIZE, idxHeader, IDX0_SIZE); } else { idxFile.seek(loc_offset); idxFile.read(idxHeader, IDX3_FREE_NODE_HEAD, 4); } idxFile.seek(0); idxFile.write(idxHeader); idxFile.commitWrite(); return loc_offset; } /** * Adds the node to the list of free nodes. * * @param inp_offset the offset of the node to free * * @exception IOException if there is an error accessing the index file */ private void freeNode(int inp_offset) throws IOException { idxFile.seek(inp_offset); idxFile.write(idxHeader, IDX3_FREE_NODE_HEAD, 4); RecordStoreUtil.putInt(inp_offset, idxHeader, IDX3_FREE_NODE_HEAD); idxFile.seek(0); idxFile.write(idxHeader); idxFile.commitWrite(); } /** * Tree management */ /** * Walks the tree starting at the given node and loads all of the tree's * keys into the given array. * * @param node the root node of the tree to walk * @param keyList array to fill with the tree's keys * @param count must be 0 for user call, other value for recursive call * * @exception IOException if there is an error accessing the index file * * @return the number of keys placed into the array. */ int walk(Node node, int[] keyList, int count) throws IOException { // number of keys in the key list int i; if (count > keyList.length - 1) { // array is filled return keyList.length; } for (i = 0; i < NODE_ELEMENTS + 1 && count < keyList.length; i++) { if (node.child[i] > 0) { // subtree // load the node int parent_offset = node.offset; // save the parent's offset node.load(node.child[i]); count = walk(node, keyList, count); // walk along subtree node.load(parent_offset); // the parent node } if (node.key[i] > 0 && count < keyList.length) { // add the current key keyList[count++] = node.key[i]; } else { // no more keys - stop walking break; } } return count; } /** * Searches the tree starting at the given node for the given key and * returns the value associated with the key * * @param node the root node of the tree to search for the key * @param key the search key * * @exception IOException if there is an error accessing the index file * * @return the value for the key or 0 if the key was not found */ int getKeyValue(Node node, int key) throws IOException { // find the node that contains the key int index = findNodeWithKey(node, key); if (node.key[index] == key) { return node.value[index]; } return 0; } /** * Updates the tree starting with the given node with the key value pair. * If the key is already in the tree, the value is updated. If the key * is not in the tree, it is inserted. If the insertion causes the root * node to be split, the offset to the new root is returned, otherwise 0 * is returned. * * @param node the root node of the tree to update the key with * @param key the key to update * @param value the new value * * @exception IOException if there is an error accessing the index file * * @return the offset of the new tree root if one was added, 0 otherwise */ int updateKey(Node node, int key, int value) throws IOException { // find the node that contains the key int index = findNodeWithKey(node, key); if (node.key[index] == key) { // key is already in the tree, update it node.value[index] = value; node.save(); return 0; } // add the key to the node Node newNode = new Node(idxFile); int rightChild = 0; while (key > 0) { // add new triplet at index node.addKey(key, value, rightChild, index); // check if node has overflowed if (node.key[NODE_ELEMENTS] == 0) { node.save(); break; } // node overflowed, split node newNode.init(allocateNode()); // save the midpoint value key = node.key[NODE_ELEMENTS/2]; value = node.value[NODE_ELEMENTS/2]; rightChild = node.child[NODE_ELEMENTS/2 + 1]; // clear midpoint node.key[NODE_ELEMENTS/2] = 0; node.value[NODE_ELEMENTS/2] = 0; node.child[NODE_ELEMENTS/2 + 1] = 0; // copy the top half of original node to new node int j = 0; newNode.child[0] = rightChild; for (int i = NODE_ELEMENTS/2 + 1; i < NODE_ELEMENTS+1; i++, j++) { newNode.key[j] = node.key[i]; newNode.value[j] = node.value[i]; newNode.child[j + 1] = node.child[i + 1]; node.key[i] = 0; node.value[i] = 0; node.child[i + 1] = 0; } node.numKeys = NODE_ELEMENTS/2; newNode.numKeys = j; rightChild = newNode.offset; int leftChild = node.offset; // save both nodes node.save(); newNode.save(); // load the parent of the node int parentOffset = node.popParent(); if (parentOffset == 0) { // need to add a new root to tree int newRoot = allocateNode(); node.init(newRoot); node.key[0] = key; node.value[0] = value; node.child[0] = leftChild; node.child[1] = rightChild; node.save(); // done with split return newRoot; } // load the parent node.load(parentOffset); // find position to insert the midpoint of split for (index = 0; index < NODE_ELEMENTS && node.child[index] != leftChild; index++); } return 0; } /** * Searches the tree starting with the given node for the given key. If * the key is in the tree, the key value pair is deleted. If the key * is not in the tree, nothing happens. If the deletion causes the root * node to be merged, the offset to the new root is returned, otherwise 0 * is returned. * * @param node the root node of the tree to remove key from * @param key the key to remove * * @exception IOException if there is an error accessing the index file * * @return the offset of the new tree root if the old one was removed, * otherwise 0 */ int deleteKey(Node node, int key) throws IOException { // find the key's node int index = findNodeWithKey(node, key); // check if key was found if (node.key[index] == key) { return deleteKeyFromNode(node, index); } return 0; } /** * Deleted the key value pair at the given index from the given node. If * the deletion causes the root node to be merged, the offset to the new * root is returned, otherwise 0 is returned. * * @param node the root node of the tree to remove key from * @param index the index to the key to remove * * @exception IOException if there is an error accessing the index file * * @return the offset of the new tree root if the old one was removed, * otherwise 0 */ private int deleteKeyFromNode(Node node, int index) throws IOException { // check if this node has right child if (node.child[index+1] > 0) { // find the least key in the subtree Node rootNode = node; node = new Node(idxFile); node.load(rootNode.child[index+1]); node.copyStack(rootNode); node.pushParent(rootNode.offset); while (node.child[0] > 0) { node.pushParent(node.offset); node.load(node.child[0]); } // replace delete key with discovered key rootNode.key[index] = node.key[0]; rootNode.value[index] = node.value[0]; rootNode.save(); // now delete discovered key index = 0; // preserve right subtree from deleting node.child[0] = node.child[1]; } // the node has no right child for the key, remove the key node.deleteKey(index); node.save(); // get the parent offset int parentOffset = node.popParent(); // rebalance tree as needed while (parentOffset > 0) { // check if node needs to be merged with sibling if (node.numKeys >= NODE_ELEMENTS/2) { // this node has at least the minimum number of keys node.load(parentOffset); parentOffset = node.popParent(); continue; } // load the parent of this node Node parentNode = new Node(idxFile); parentNode.load(parentOffset); // find the offset of the node in the parent int childIdx = 0; for (; parentNode.child[childIdx] != node.offset && childIdx < NODE_ELEMENTS+1; childIdx++); int midpointIdx = childIdx; Node siblingNode = null; // try loading the left sibling if (childIdx-1 >= 0) { // load the left sibling siblingNode = new Node(idxFile); siblingNode.load(parentNode.child[childIdx-1]); midpointIdx = childIdx-1; } // check if this is a merge candidate if (siblingNode == null || node.numKeys + siblingNode.numKeys + 1 > NODE_ELEMENTS) { if (siblingNode == null) { siblingNode = new Node(idxFile); } // not a merge candidate, check the right sibling if (childIdx+1 < NODE_ELEMENTS+1 && parentNode.child[childIdx+1] > 0) { // load the right sibling siblingNode.load(parentNode.child[childIdx+1]); midpointIdx = childIdx; } } // check if a merge is needed if (node.numKeys + siblingNode.numKeys + 1 <= NODE_ELEMENTS) { // merge the siblings Node leftNode, rightNode; if (childIdx == midpointIdx) { leftNode = node;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?