From ecf0475ad0e8b4612363562992f3ef29eb4be646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 5 Oct 2006 17:34:11 +0000 Subject: [PATCH] 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 --- .../kernel/file_systems/bfs/BPlusTree.cpp | 11 ++++++----- .../kernel/file_systems/bfs/r5/BPlusTree.cpp | 16 +++++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp b/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp index 12d08e2fbe..eeb147ac97 100644 --- a/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp @@ -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; diff --git a/src/tests/add-ons/kernel/file_systems/bfs/r5/BPlusTree.cpp b/src/tests/add-ons/kernel/file_systems/bfs/r5/BPlusTree.cpp index f961ade77d..7798083be0 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/r5/BPlusTree.cpp +++ b/src/tests/add-ons/kernel/file_systems/bfs/r5/BPlusTree.cpp @@ -616,6 +616,7 @@ BPlusTree::SeekDown(Stack &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