Porting r18992 to the R5 version of BFS (and therefore, bfs_shell used to build the

Haiku image) revealed a problem with that change:
* If the root node only contained a single entry it was freed instead of just making
  it a leaf node - that could produce an invalid b+tree (could only happen with
  attribute or index trees, as directories always contain '.' and '..').


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19006 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-10-05 17:34:11 +00:00
parent bad41d39a2
commit ecf0475ad0
2 changed files with 17 additions and 10 deletions

View File

@ -1641,16 +1641,17 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
return B_IO_ERROR;
// if it's an empty root node, we have to convert it
// to a leaf node by dropping the overflow link
// to a leaf node by dropping the overflow link, or,
// if it's already a leaf node, just empty it
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->all_key_count = 0;
writableNode->all_key_length = 0;
// if we've cleared the root node, reset the maximum
// number of levels in the header
if (nodeAndKey.nodeOffset == fHeader->RootNode()) {
// if we've made a leaf node out of the root node, we need
// to reset the maximum number of levels in the header
if (fHeader->MaxNumberOfLevels() != 1) {
bplustree_header *header = fCachedHeader.MakeWritableHeader(transaction);
if (header == NULL)
return B_IO_ERROR;

View File

@ -616,6 +616,7 @@ BPlusTree::SeekDown(Stack<node_and_key> &stack, const uint8 *key, uint16 keyLeng
nodeAndKey.nodeOffset = nextOffset;
}
RETURN_ERROR(B_ERROR);
}
@ -1192,6 +1193,7 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
}
}
}
RETURN_ERROR(B_ERROR);
}
@ -1487,9 +1489,9 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
// if it's an empty root node, we have to convert it
// to a leaf node by dropping the overflow link, or,
// if it's a leaf node, just empty it
// if it's already a leaf node, just empty it
if (nodeAndKey.nodeOffset == fHeader->RootNode()
&& node->NumKeys() == 0) {
&& (node->NumKeys() == 0 || node->NumKeys() == 1 && node->IsLeaf())) {
node->overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
node->all_key_count = 0;
node->all_key_length = 0;
@ -1497,9 +1499,13 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
if (cached.WriteBack(transaction) < B_OK)
return B_IO_ERROR;
// reset the maximum number of levels in the header
fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1);
return fCachedHeader.WriteBack(transaction);
// if we've made a leaf node out of the root node, we need
// to reset the maximum number of levels in the header
if (fHeader->MaxNumberOfLevels() != 1) {
fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1);
return fCachedHeader.WriteBack(transaction);
}
return B_OK;
}
// if there is only one key left, we don't have to remove