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:
parent
bad41d39a2
commit
ecf0475ad0
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user