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:
@@ -1641,16 +1641,17 @@ 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
|
// 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()
|
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;
|
||||||
|
|
||||||
// if we've cleared the root node, reset the maximum
|
// if we've made a leaf node out of the root node, we need
|
||||||
// number of levels in the header
|
// to reset the maximum number of levels in the header
|
||||||
if (nodeAndKey.nodeOffset == fHeader->RootNode()) {
|
if (fHeader->MaxNumberOfLevels() != 1) {
|
||||||
bplustree_header *header = fCachedHeader.MakeWritableHeader(transaction);
|
bplustree_header *header = fCachedHeader.MakeWritableHeader(transaction);
|
||||||
if (header == NULL)
|
if (header == NULL)
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
|
|||||||
@@ -616,6 +616,7 @@ BPlusTree::SeekDown(Stack<node_and_key> &stack, const uint8 *key, uint16 keyLeng
|
|||||||
|
|
||||||
nodeAndKey.nodeOffset = nextOffset;
|
nodeAndKey.nodeOffset = nextOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(B_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1192,6 +1193,7 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_ERROR(B_ERROR);
|
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
|
// 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, 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()
|
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->overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
|
||||||
node->all_key_count = 0;
|
node->all_key_count = 0;
|
||||||
node->all_key_length = 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)
|
if (cached.WriteBack(transaction) < B_OK)
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
|
|
||||||
// reset the maximum number of levels in the header
|
// if we've made a leaf node out of the root node, we need
|
||||||
fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1);
|
// to reset the maximum number of levels in the header
|
||||||
return fCachedHeader.WriteBack(transaction);
|
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
|
// if there is only one key left, we don't have to remove
|
||||||
|
|||||||
Reference in New Issue
Block a user