* _SeekDown() now checks if it has already reached the maximum tree

depth, and will bail out if it hasn't reached the leaf level then.
* This should at least avoid the crash of bug #1911; there is not much
  more I can do about that.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24411 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-03-16 16:26:05 +00:00
parent d89cda9ff7
commit 7a3ecb82ba
@@ -59,7 +59,7 @@ class NodeChecker {
// Since BFS supports block sizes of 1024 bytes or greater, and the node size // Since BFS supports block sizes of 1024 bytes or greater, and the node size
// is hard-coded to 1024 bytes, that's not an issue now. // is hard-coded to 1024 bytes, that's not an issue now.
void void
CachedNode::UnsetUnchanged(Transaction &transaction) CachedNode::UnsetUnchanged(Transaction &transaction)
{ {
if (fTree == NULL || fTree->fStream == NULL) if (fTree == NULL || fTree->fStream == NULL)
@@ -75,7 +75,7 @@ CachedNode::UnsetUnchanged(Transaction &transaction)
} }
void void
CachedNode::Unset() CachedNode::Unset()
{ {
if (fTree == NULL || fTree->fStream == NULL) if (fTree == NULL || fTree->fStream == NULL)
@@ -504,7 +504,7 @@ BPlusTree::InitCheck()
} }
int32 int32
BPlusTree::TypeCodeToKeyType(type_code code) BPlusTree::TypeCodeToKeyType(type_code code)
{ {
switch (code) { switch (code) {
@@ -530,7 +530,7 @@ BPlusTree::TypeCodeToKeyType(type_code code)
} }
int32 int32
BPlusTree::ModeToKeyType(mode_t mode) BPlusTree::ModeToKeyType(mode_t mode)
{ {
switch (mode & (S_STR_INDEX | S_INT_INDEX | S_UINT_INDEX | S_LONG_LONG_INDEX switch (mode & (S_STR_INDEX | S_INT_INDEX | S_UINT_INDEX | S_LONG_LONG_INDEX
@@ -588,7 +588,7 @@ BPlusTree::_AddIterator(TreeIterator *iterator)
} }
void void
BPlusTree::_RemoveIterator(TreeIterator *iterator) BPlusTree::_RemoveIterator(TreeIterator *iterator)
{ {
if (fIteratorLock.Lock() < B_OK) if (fIteratorLock.Lock() < B_OK)
@@ -723,13 +723,18 @@ BPlusTree::_SeekDown(Stack<node_and_key> &stack, const uint8 *key,
if (status == B_ENTRY_NOT_FOUND && nextOffset == nodeAndKey.nodeOffset) if (status == B_ENTRY_NOT_FOUND && nextOffset == nodeAndKey.nodeOffset)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
if ((uint32)stack.CountItems() > fHeader->MaxNumberOfLevels()) {
dprintf("BPlusTree::_SeekDown() node walked too deep.\n");
break;
}
// put the node offset & the correct keyIndex on the stack // put the node offset & the correct keyIndex on the stack
stack.Push(nodeAndKey); stack.Push(nodeAndKey);
nodeAndKey.nodeOffset = nextOffset; nodeAndKey.nodeOffset = nextOffset;
} }
FATAL(("BPlusTree::SeekDown() could not open node %Ld\n", FATAL(("BPlusTree::_SeekDown() could not open node %Ld\n",
nodeAndKey.nodeOffset)); nodeAndKey.nodeOffset));
return B_ERROR; return B_ERROR;
} }
@@ -814,7 +819,7 @@ BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
if (array->count < NUM_FRAGMENT_VALUES) { if (array->count < NUM_FRAGMENT_VALUES) {
array->Insert(value); array->Insert(value);
} else { } else {
// test if the fragment will be empty if we remove this key's values // test if the fragment will be empty if we remove this key's values
if (duplicate->FragmentsUsed(fNodeSize) < 2) { if (duplicate->FragmentsUsed(fNodeSize) < 2) {
// the node will be empty without our values, so let us // the node will be empty without our values, so let us
// reuse it as a duplicate node // reuse it as a duplicate node
@@ -1353,7 +1358,7 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
otherOffset, &nodeAndKey.keyIndex, keyBuffer, &keyLength, otherOffset, &nodeAndKey.keyIndex, keyBuffer, &keyLength,
&value) < B_OK) { &value) < B_OK) {
// free root node & other node here // free root node & other node here
cachedOther.Free(transaction, otherOffset); cachedOther.Free(transaction, otherOffset);
cachedNewRoot.Free(transaction, newRoot); cachedNewRoot.Free(transaction, newRoot);
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
@@ -1951,11 +1956,11 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength,
{ {
if (fTree == NULL) if (fTree == NULL)
return B_INTERRUPTED; return B_INTERRUPTED;
bool forward = direction == BPLUSTREE_FORWARD; bool forward = direction == BPLUSTREE_FORWARD;
if (fCurrentNodeOffset == BPLUSTREE_NULL if (fCurrentNodeOffset == BPLUSTREE_NULL
&& Goto(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
@@ -2089,7 +2094,7 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength,
sets the current position in the iterator, regardless of if the sets the current position in the iterator, regardless of if the
key could be found or not. key could be found or not.
*/ */
status_t status_t
TreeIterator::Find(const uint8 *key, uint16 keyLength) TreeIterator::Find(const uint8 *key, uint16 keyLength)
{ {
if (fTree == NULL) if (fTree == NULL)
@@ -2126,14 +2131,14 @@ TreeIterator::Find(const uint8 *key, uint16 keyLength)
} }
void void
TreeIterator::SkipDuplicates() TreeIterator::SkipDuplicates()
{ {
fDuplicateNode = BPLUSTREE_NULL; fDuplicateNode = BPLUSTREE_NULL;
} }
void void
TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 splitAt, int8 change) TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 splitAt, int8 change)
{ {
if (offset != fCurrentNodeOffset) if (offset != fCurrentNodeOffset)
@@ -2157,7 +2162,7 @@ TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 spl
} }
void void
TreeIterator::Stop() TreeIterator::Stop()
{ {
fTree = NULL; fTree = NULL;
@@ -2165,7 +2170,7 @@ TreeIterator::Stop()
#ifdef DEBUG #ifdef DEBUG
void void
TreeIterator::Dump() TreeIterator::Dump()
{ {
__out("TreeIterator at %p:\n", this); __out("TreeIterator at %p:\n", this);
@@ -2183,7 +2188,7 @@ TreeIterator::Dump()
// #pragma mark - // #pragma mark -
void void
bplustree_node::Initialize() bplustree_node::Initialize()
{ {
left_link = right_link = overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL); left_link = right_link = overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);