Fixed a stupid bug found by accident:
* When removing the last key from a leaf node, the node wasn't freed, but just emptied, and thus the whole tree structure would never combast. * This could also cause a bug in the TreeIterator: if the last entry was not in the last node, every second readdir() after the last one would return the last entry again. I only found this because that happens to be what Tracker does (which would run in an endless loop while scanning the directory then). * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18992 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1641,11 +1641,9 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
|
|||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
|
|
||||||
// if it's an empty root node, we have to convert it
|
// if it's an empty root node, we have to convert it
|
||||||
// to a leaf node by dropping the overflow link, or,
|
// to a leaf node by dropping the overflow link
|
||||||
// if it's a leaf node, just empty it
|
|
||||||
if (nodeAndKey.nodeOffset == fHeader->RootNode()
|
if (nodeAndKey.nodeOffset == fHeader->RootNode()
|
||||||
&& node->NumKeys() == 0
|
&& node->NumKeys() == 0) {
|
||||||
|| node->NumKeys() == 1 && node->IsLeaf()) {
|
|
||||||
writableNode->overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
|
writableNode->overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
|
||||||
writableNode->all_key_count = 0;
|
writableNode->all_key_count = 0;
|
||||||
writableNode->all_key_length = 0;
|
writableNode->all_key_length = 0;
|
||||||
@@ -1883,8 +1881,11 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
|
|||||||
{
|
{
|
||||||
if (fTree == NULL)
|
if (fTree == NULL)
|
||||||
return B_INTERRUPTED;
|
return B_INTERRUPTED;
|
||||||
|
|
||||||
|
bool forward = direction == BPLUSTREE_FORWARD;
|
||||||
|
|
||||||
if (fCurrentNodeOffset == BPLUSTREE_NULL
|
if (fCurrentNodeOffset == BPLUSTREE_NULL
|
||||||
&& Goto(direction == BPLUSTREE_FORWARD ? BPLUSTREE_BEGIN : BPLUSTREE_END) < B_OK)
|
&& Goto(forward ? BPLUSTREE_BEGIN : BPLUSTREE_END) < B_OK)
|
||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(B_ERROR);
|
||||||
|
|
||||||
// if the tree was emptied since the last call
|
// if the tree was emptied since the last call
|
||||||
@@ -1928,6 +1929,8 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
|
|||||||
}
|
}
|
||||||
|
|
||||||
off_t savedNodeOffset = fCurrentNodeOffset;
|
off_t savedNodeOffset = fCurrentNodeOffset;
|
||||||
|
int32 savedKey = fCurrentKey;
|
||||||
|
|
||||||
if ((node = cached.SetTo(fCurrentNodeOffset)) == NULL)
|
if ((node = cached.SetTo(fCurrentNodeOffset)) == NULL)
|
||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(B_ERROR);
|
||||||
|
|
||||||
@@ -1937,9 +1940,9 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
|
|||||||
fCurrentKey += direction;
|
fCurrentKey += direction;
|
||||||
|
|
||||||
// is the current key in the current node?
|
// is the current key in the current node?
|
||||||
while ((direction == BPLUSTREE_FORWARD && fCurrentKey >= node->NumKeys())
|
while ((forward && fCurrentKey >= node->NumKeys())
|
||||||
|| (direction == BPLUSTREE_BACKWARD && fCurrentKey < 0)) {
|
|| (!forward && fCurrentKey < 0)) {
|
||||||
fCurrentNodeOffset = direction == BPLUSTREE_FORWARD ? node->RightLink() : node->LeftLink();
|
fCurrentNodeOffset = forward ? node->RightLink() : node->LeftLink();
|
||||||
|
|
||||||
// are there any more nodes?
|
// are there any more nodes?
|
||||||
if (fCurrentNodeOffset != BPLUSTREE_NULL) {
|
if (fCurrentNodeOffset != BPLUSTREE_NULL) {
|
||||||
@@ -1948,11 +1951,11 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
|
|||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(B_ERROR);
|
||||||
|
|
||||||
// reset current key
|
// reset current key
|
||||||
fCurrentKey = direction == BPLUSTREE_FORWARD ? 0 : node->NumKeys();
|
fCurrentKey = forward ? 0 : node->NumKeys();
|
||||||
} else {
|
} else {
|
||||||
// there are no nodes left, so turn back to the last key
|
// there are no nodes left, so turn back to the last key
|
||||||
fCurrentNodeOffset = savedNodeOffset;
|
fCurrentNodeOffset = savedNodeOffset;
|
||||||
fCurrentKey = direction == BPLUSTREE_FORWARD ? node->NumKeys() : -1;
|
fCurrentKey = savedKey;
|
||||||
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user