Fixed the wrong maintainance of the max_number_of_levels field in the

B+tree's header.
Some style cleanups.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1870 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-11-07 12:30:45 +00:00
parent 5f5bb7d7eb
commit e335b08a33
@@ -269,8 +269,10 @@ BPlusTree::~BPlusTree()
} }
/** Create a new B+Tree on the specified stream */
status_t status_t
BPlusTree::SetTo(Transaction *transaction,Inode *stream,int32 nodeSize) BPlusTree::SetTo(Transaction *transaction, Inode *stream, int32 nodeSize)
{ {
// initializes in-memory B+Tree // initializes in-memory B+Tree
@@ -280,7 +282,7 @@ BPlusTree::SetTo(Transaction *transaction,Inode *stream,int32 nodeSize)
fHeader = fCachedHeader.SetToHeader(); fHeader = fCachedHeader.SetToHeader();
if (fHeader == NULL) { if (fHeader == NULL) {
// allocate space for new header + node! // allocate space for new header + node!
fStatus = stream->SetFileSize(transaction,nodeSize * 2); fStatus = stream->SetFileSize(transaction, nodeSize * 2);
if (fStatus < B_OK) if (fStatus < B_OK)
RETURN_ERROR(fStatus); RETURN_ERROR(fStatus);
@@ -429,7 +431,8 @@ BPlusTree::ModeToKeyType(mode_t mode)
void void
BPlusTree::UpdateIterators(off_t offset,off_t nextOffset,uint16 keyIndex,uint16 splitAt,int8 change) BPlusTree::UpdateIterators(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 splitAt,
int8 change)
{ {
// Although every iterator which is affected by this update currently // Although every iterator which is affected by this update currently
// waits on a semaphore, other iterators could be added/removed at // waits on a semaphore, other iterators could be added/removed at
@@ -439,7 +442,7 @@ BPlusTree::UpdateIterators(off_t offset,off_t nextOffset,uint16 keyIndex,uint16
TreeIterator *iterator = NULL; TreeIterator *iterator = NULL;
while ((iterator = fIterators.Next(iterator)) != NULL) while ((iterator = fIterators.Next(iterator)) != NULL)
iterator->Update(offset,nextOffset,keyIndex,splitAt,change); iterator->Update(offset, nextOffset, keyIndex, splitAt, change);
fIteratorLock.Unlock(); fIteratorLock.Unlock();
} }
@@ -497,12 +500,13 @@ BPlusTree::CompareKeys(const void *key1, int keyLength1, const void *key2, int k
type = B_DOUBLE_TYPE; type = B_DOUBLE_TYPE;
break; break;
} }
return compareKeys(type,key1,keyLength1,key2,keyLength2); return compareKeys(type, key1, keyLength1, key2, keyLength2);
} }
status_t status_t
BPlusTree::FindKey(bplustree_node *node,const uint8 *key,uint16 keyLength,uint16 *index,off_t *next) BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uint16 *index,
off_t *next)
{ {
if (node->all_key_count == 0) if (node->all_key_count == 0)
{ {
@@ -529,7 +533,7 @@ BPlusTree::FindKey(bplustree_node *node,const uint8 *key,uint16 keyLength,uint16
RETURN_ERROR(B_BAD_DATA); RETURN_ERROR(B_BAD_DATA);
} }
int32 cmp = CompareKeys(key,keyLength,searchKey,searchLength); int32 cmp = CompareKeys(key, keyLength, searchKey, searchLength);
if (cmp < 0) if (cmp < 0)
{ {
last = i - 1; last = i - 1;
@@ -568,7 +572,7 @@ BPlusTree::FindKey(bplustree_node *node,const uint8 *key,uint16 keyLength,uint16
*/ */
status_t status_t
BPlusTree::SeekDown(Stack<node_and_key> &stack,const uint8 *key,uint16 keyLength) BPlusTree::SeekDown(Stack<node_and_key> &stack, const uint8 *key, uint16 keyLength)
{ {
// set the root node to begin with // set the root node to begin with
node_and_key nodeAndKey; node_and_key nodeAndKey;
@@ -587,7 +591,7 @@ BPlusTree::SeekDown(Stack<node_and_key> &stack,const uint8 *key,uint16 keyLength
} }
off_t nextOffset; off_t nextOffset;
status_t status = FindKey(node,key,keyLength,&nodeAndKey.keyIndex,&nextOffset); status_t status = FindKey(node, key, keyLength, &nodeAndKey.keyIndex, &nextOffset);
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);
@@ -602,7 +606,8 @@ BPlusTree::SeekDown(Stack<node_and_key> &stack,const uint8 *key,uint16 keyLength
status_t status_t
BPlusTree::FindFreeDuplicateFragment(bplustree_node *node,CachedNode *cached,off_t *_offset,bplustree_node **_fragment,uint32 *_index) BPlusTree::FindFreeDuplicateFragment(bplustree_node *node, CachedNode *cached, off_t *_offset,
bplustree_node **_fragment, uint32 *_index)
{ {
off_t *values = node->Values(); off_t *values = node->Values();
for (int32 i = 0;i < node->all_key_count;i++) { for (int32 i = 0;i < node->all_key_count;i++) {
@@ -610,7 +615,7 @@ BPlusTree::FindFreeDuplicateFragment(bplustree_node *node,CachedNode *cached,off
if (bplustree_node::LinkType(values[i]) != BPLUSTREE_DUPLICATE_FRAGMENT) if (bplustree_node::LinkType(values[i]) != BPLUSTREE_DUPLICATE_FRAGMENT)
continue; continue;
bplustree_node *fragment = cached->SetTo(bplustree_node::FragmentOffset(values[i]),false); bplustree_node *fragment = cached->SetTo(bplustree_node::FragmentOffset(values[i]), false);
if (fragment == NULL) { if (fragment == NULL) {
FATAL(("Could not get duplicate fragment at %Ld\n",values[i])); FATAL(("Could not get duplicate fragment at %Ld\n",values[i]));
continue; continue;
@@ -634,7 +639,8 @@ BPlusTree::FindFreeDuplicateFragment(bplustree_node *node,CachedNode *cached,off
status_t status_t
BPlusTree::InsertDuplicate(Transaction *transaction,CachedNode *cached,bplustree_node *node,uint16 index,off_t value) BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustree_node *node,
uint16 index, off_t value)
{ {
CachedNode cachedDuplicate(this); CachedNode cachedDuplicate(this);
off_t *values = node->Values(); off_t *values = node->Values();
@@ -684,7 +690,8 @@ BPlusTree::InsertDuplicate(Transaction *transaction,CachedNode *cached,bplustree
// copy the array from the fragment node to the duplicate node // copy the array from the fragment node to the duplicate node
// and free the old entry (by zero'ing all values) // and free the old entry (by zero'ing all values)
newDuplicate->overflow_link = array->count; newDuplicate->overflow_link = array->count;
memcpy(&newDuplicate->all_key_count,&array->values[0],array->count * sizeof(off_t)); memcpy(&newDuplicate->all_key_count, &array->values[0],
array->count * sizeof(off_t));
memset(array,0,(NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); memset(array,0,(NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
array = newDuplicate->DuplicateArray(); array = newDuplicate->DuplicateArray();
@@ -698,7 +705,7 @@ BPlusTree::InsertDuplicate(Transaction *transaction,CachedNode *cached,bplustree
} }
// update the main pointer to link to a duplicate node // update the main pointer to link to a duplicate node
values[index] = bplustree_node::MakeLink(BPLUSTREE_DUPLICATE_NODE,offset); values[index] = bplustree_node::MakeLink(BPLUSTREE_DUPLICATE_NODE, offset);
if ((status = cached->WriteBack(transaction)) < B_OK) if ((status = cached->WriteBack(transaction)) < B_OK)
return status; return status;
} }
@@ -716,17 +723,18 @@ BPlusTree::InsertDuplicate(Transaction *transaction,CachedNode *cached,bplustree
off_t duplicateOffset; off_t duplicateOffset;
do { do {
duplicateOffset = bplustree_node::FragmentOffset(oldValue); duplicateOffset = bplustree_node::FragmentOffset(oldValue);
duplicate = cachedDuplicate.SetTo(duplicateOffset,false); duplicate = cachedDuplicate.SetTo(duplicateOffset, false);
if (duplicate == NULL) if (duplicate == NULL)
return B_IO_ERROR; return B_IO_ERROR;
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (array->count > NUM_DUPLICATE_VALUES if (array->count > NUM_DUPLICATE_VALUES || array->count < 0) {
|| array->count < 0) { FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == %Ld!\n",
FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == %Ld!\n",duplicateOffset,array->count)); duplicateOffset,array->count));
return B_BAD_DATA; return B_BAD_DATA;
} }
} while (array->count >= NUM_DUPLICATE_VALUES && (oldValue = duplicate->right_link) != BPLUSTREE_NULL); } while (array->count >= NUM_DUPLICATE_VALUES
&& (oldValue = duplicate->right_link) != BPLUSTREE_NULL);
if (array->count < NUM_DUPLICATE_VALUES) { if (array->count < NUM_DUPLICATE_VALUES) {
array->Insert(value); array->Insert(value);
@@ -735,7 +743,7 @@ BPlusTree::InsertDuplicate(Transaction *transaction,CachedNode *cached,bplustree
CachedNode cachedNewDuplicate(this); CachedNode cachedNewDuplicate(this);
bplustree_node *newDuplicate; bplustree_node *newDuplicate;
status = cachedNewDuplicate.Allocate(transaction,&newDuplicate,&offset); status = cachedNewDuplicate.Allocate(transaction, &newDuplicate, &offset);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -761,12 +769,12 @@ BPlusTree::InsertDuplicate(Transaction *transaction,CachedNode *cached,bplustree
uint32 fragmentIndex = 0; uint32 fragmentIndex = 0;
bplustree_node *fragment; bplustree_node *fragment;
if (FindFreeDuplicateFragment(node,&cachedDuplicate,&offset,&fragment,&fragmentIndex) < B_OK) { if (FindFreeDuplicateFragment(node, &cachedDuplicate, &offset, &fragment, &fragmentIndex) < B_OK) {
// allocate a new duplicate fragment node // allocate a new duplicate fragment node
if ((status = cachedDuplicate.Allocate(transaction,&fragment,&offset)) < B_OK) if ((status = cachedDuplicate.Allocate(transaction, &fragment, &offset)) < B_OK)
return status; return status;
memset(fragment,0,fNodeSize); memset(fragment, 0, fNodeSize);
} }
duplicate_array *array = fragment->FragmentAt(fragmentIndex); duplicate_array *array = fragment->FragmentAt(fragmentIndex);
array->Insert(oldValue); array->Insert(oldValue);
@@ -775,14 +783,15 @@ BPlusTree::InsertDuplicate(Transaction *transaction,CachedNode *cached,bplustree
if ((status = cachedDuplicate.WriteBack(transaction)) < B_OK) if ((status = cachedDuplicate.WriteBack(transaction)) < B_OK)
return status; return status;
values[index] = bplustree_node::MakeLink(BPLUSTREE_DUPLICATE_FRAGMENT,offset,fragmentIndex); values[index] = bplustree_node::MakeLink(BPLUSTREE_DUPLICATE_FRAGMENT, offset, fragmentIndex);
return cached->WriteBack(transaction); return cached->WriteBack(transaction);
} }
void void
BPlusTree::InsertKey(bplustree_node *node,uint16 index,uint8 *key,uint16 keyLength,off_t value) BPlusTree::InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyLength,
off_t value)
{ {
// should never happen, but who knows? // should never happen, but who knows?
if (index > node->all_key_count) if (index > node->all_key_count)
@@ -817,12 +826,13 @@ BPlusTree::InsertKey(bplustree_node *node,uint16 index,uint8 *key,uint16 keyLeng
if (size > 0) if (size > 0)
memmove(keys + newKeyLengths[index],keys + newKeyLengths[index] - keyLength,size); memmove(keys + newKeyLengths[index],keys + newKeyLengths[index] - keyLength,size);
memcpy(keys + keyStart,key,keyLength); memcpy(keys + keyStart, key, keyLength);
} }
status_t status_t
BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other,off_t otherOffset,uint16 *_keyIndex,uint8 *key,uint16 *_keyLength,off_t *_value) BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other,
off_t otherOffset, uint16 *_keyIndex, uint8 *key, uint16 *_keyLength, off_t *_value)
{ {
if (*_keyIndex > node->all_key_count + 1) if (*_keyIndex > node->all_key_count + 1)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -840,7 +850,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
// "bytes" is the number of bytes written for the new key, // "bytes" is the number of bytes written for the new key,
// "bytesBefore" are the bytes before that key // "bytesBefore" are the bytes before that key
// "bytesAfter" are the bytes after the new key, if any // "bytesAfter" are the bytes after the new key, if any
int32 bytes = 0,bytesBefore = 0,bytesAfter = 0; int32 bytes = 0, bytesBefore = 0, bytesAfter = 0;
size_t size = fNodeSize >> 1; size_t size = fNodeSize >> 1;
int32 out,in; int32 out,in;
@@ -884,23 +894,23 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
if (bytesBefore) { if (bytesBefore) {
// copy the keys // copy the keys
memcpy(outKeys,inKeys,bytesBefore); memcpy(outKeys, inKeys, bytesBefore);
memcpy(outKeyLengths,inKeyLengths,keys * sizeof(uint16)); memcpy(outKeyLengths, inKeyLengths, keys * sizeof(uint16));
memcpy(outKeyValues,inKeyValues,keys * sizeof(off_t)); memcpy(outKeyValues, inKeyValues, keys * sizeof(off_t));
} }
if (bytes) { if (bytes) {
// copy the newly inserted key // copy the newly inserted key
memcpy(outKeys + bytesBefore,key,bytes); memcpy(outKeys + bytesBefore, key, bytes);
outKeyLengths[keyIndex] = bytes + bytesBefore; outKeyLengths[keyIndex] = bytes + bytesBefore;
outKeyValues[keyIndex] = *_value; outKeyValues[keyIndex] = *_value;
if (bytesAfter) { if (bytesAfter) {
// copy the keys after the new key // copy the keys after the new key
memcpy(outKeys + bytesBefore + bytes,inKeys + bytesBefore,bytesAfter); memcpy(outKeys + bytesBefore + bytes, inKeys + bytesBefore, bytesAfter);
keys = out - keyIndex - 1; keys = out - keyIndex - 1;
for (int32 i = 0;i < keys;i++) for (int32 i = 0;i < keys;i++)
outKeyLengths[keyIndex + i + 1] = inKeyLengths[keyIndex + i] + bytes; outKeyLengths[keyIndex + i + 1] = inKeyLengths[keyIndex + i] + bytes;
memcpy(outKeyValues + keyIndex + 1,inKeyValues + keyIndex,keys * sizeof(off_t)); memcpy(outKeyValues + keyIndex + 1, inKeyValues + keyIndex, keys * sizeof(off_t));
} }
} }
@@ -1002,24 +1012,24 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
keyIndex -= skip; keyIndex -= skip;
if (bytesBefore) if (bytesBefore)
memmove(inKeys,inKeys + total,bytesBefore); memmove(inKeys, inKeys + total, bytesBefore);
if (bytesAfter) if (bytesAfter)
memmove(inKeys + bytesBefore + bytes,inKeys + total + bytesBefore,bytesAfter); memmove(inKeys + bytesBefore + bytes, inKeys + total + bytesBefore, bytesAfter);
if (bytesBefore) if (bytesBefore)
memmove(outKeyLengths,inKeyLengths + skip,keys * sizeof(uint16)); memmove(outKeyLengths, inKeyLengths + skip, keys * sizeof(uint16));
in = out - keyIndex - 1; in = out - keyIndex - 1;
if (bytesAfter) if (bytesAfter)
memmove(outKeyLengths + keyIndex + 1,inKeyLengths + skip + keyIndex,in * sizeof(uint16)); memmove(outKeyLengths + keyIndex + 1, inKeyLengths + skip + keyIndex, in * sizeof(uint16));
if (bytesBefore) if (bytesBefore)
memmove(outKeyValues,inKeyValues + skip,keys * sizeof(off_t)); memmove(outKeyValues, inKeyValues + skip, keys * sizeof(off_t));
if (bytesAfter) if (bytesAfter)
memmove(outKeyValues + keyIndex + 1,inKeyValues + skip + keyIndex,in * sizeof(off_t)); memmove(outKeyValues + keyIndex + 1, inKeyValues + skip + keyIndex, in * sizeof(off_t));
if (bytes) { if (bytes) {
// finally, copy the newly inserted key (don't overwrite anything) // finally, copy the newly inserted key (don't overwrite anything)
memcpy(inKeys + bytesBefore,key,bytes); memcpy(inKeys + bytesBefore, key, bytes);
outKeyLengths[keyIndex] = bytes + bytesBefore; outKeyLengths[keyIndex] = bytes + bytesBefore;
outKeyValues[keyIndex] = *_value; outKeyValues[keyIndex] = *_value;
} }
@@ -1029,7 +1039,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
// If it's the dropped key, "newKey" was already set earlier. // If it's the dropped key, "newKey" was already set earlier.
if (newKey == NULL) if (newKey == NULL)
newKey = other->KeyAt(other->all_key_count - 1,&newLength); newKey = other->KeyAt(other->all_key_count - 1, &newLength);
memcpy(key,newKey,newLength); memcpy(key,newKey,newLength);
*_keyLength = newLength; *_keyLength = newLength;
@@ -1043,7 +1053,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
status_t status_t
BPlusTree::Insert(Transaction *transaction,const uint8 *key,uint16 keyLength,off_t value) BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength, off_t value)
{ {
if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH) if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
@@ -1072,9 +1082,9 @@ BPlusTree::Insert(Transaction *transaction,const uint8 *key,uint16 keyLength,off
// is this a duplicate entry? // is this a duplicate entry?
if (status == B_OK) { if (status == B_OK) {
if (fAllowDuplicates) if (fAllowDuplicates)
return InsertDuplicate(transaction,&cached,node,nodeAndKey.keyIndex,value); return InsertDuplicate(transaction, &cached, node, nodeAndKey.keyIndex, value);
else
RETURN_ERROR(B_NAME_IN_USE); RETURN_ERROR(B_NAME_IN_USE);
} }
} }
@@ -1082,8 +1092,8 @@ BPlusTree::Insert(Transaction *transaction,const uint8 *key,uint16 keyLength,off
if (int32(round_up(sizeof(bplustree_node) + node->all_key_length + keyLength) if (int32(round_up(sizeof(bplustree_node) + node->all_key_length + keyLength)
+ (node->all_key_count + 1) * (sizeof(uint16) + sizeof(off_t))) < fNodeSize) + (node->all_key_count + 1) * (sizeof(uint16) + sizeof(off_t))) < fNodeSize)
{ {
InsertKey(node,nodeAndKey.keyIndex,keyBuffer,keyLength,value); InsertKey(node, nodeAndKey.keyIndex, keyBuffer, keyLength, value);
UpdateIterators(nodeAndKey.nodeOffset,BPLUSTREE_NULL,nodeAndKey.keyIndex,0,1); UpdateIterators(nodeAndKey.nodeOffset, BPLUSTREE_NULL, nodeAndKey.keyIndex, 0, 1);
return cached.WriteBack(transaction); return cached.WriteBack(transaction);
} else { } else {
@@ -1095,7 +1105,7 @@ BPlusTree::Insert(Transaction *transaction,const uint8 *key,uint16 keyLength,off
off_t newRoot = BPLUSTREE_NULL; off_t newRoot = BPLUSTREE_NULL;
if (nodeAndKey.nodeOffset == fHeader->root_node_pointer) { if (nodeAndKey.nodeOffset == fHeader->root_node_pointer) {
bplustree_node *root; bplustree_node *root;
status_t status = cachedNewRoot.Allocate(transaction,&root,&newRoot); status_t status = cachedNewRoot.Allocate(transaction, &root, &newRoot);
if (status < B_OK) { if (status < B_OK) {
// The tree is most likely corrupted! // The tree is most likely corrupted!
// But it's still sane at leaf level - we could set // But it's still sane at leaf level - we could set
@@ -1110,16 +1120,17 @@ BPlusTree::Insert(Transaction *transaction,const uint8 *key,uint16 keyLength,off
// reserve space for the other node // reserve space for the other node
bplustree_node *other; bplustree_node *other;
off_t otherOffset; off_t otherOffset;
status_t status = cachedOther.Allocate(transaction,&other,&otherOffset); status_t status = cachedOther.Allocate(transaction, &other, &otherOffset);
if (status < B_OK) { if (status < B_OK) {
cachedNewRoot.Free(transaction,newRoot); cachedNewRoot.Free(transaction, newRoot);
RETURN_ERROR(status); RETURN_ERROR(status);
} }
if (SplitNode(node,nodeAndKey.nodeOffset,other,otherOffset,&nodeAndKey.keyIndex,keyBuffer,&keyLength,&value) < B_OK) { if (SplitNode(node, nodeAndKey.nodeOffset, other, otherOffset,
&nodeAndKey.keyIndex, keyBuffer, &keyLength, &value) < B_OK) {
// free root node & other node here // free root node & other node here
cachedNewRoot.Free(transaction,newRoot); cachedNewRoot.Free(transaction, newRoot);
cachedOther.Free(transaction,otherOffset); cachedOther.Free(transaction, otherOffset);
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
} }
@@ -1130,7 +1141,8 @@ BPlusTree::Insert(Transaction *transaction,const uint8 *key,uint16 keyLength,off
|| cachedOther.WriteBack(transaction) < B_OK) || cachedOther.WriteBack(transaction) < B_OK)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
UpdateIterators(nodeAndKey.nodeOffset,otherOffset,nodeAndKey.keyIndex,node->all_key_count,1); UpdateIterators(nodeAndKey.nodeOffset, otherOffset, nodeAndKey.keyIndex,
node->all_key_count, 1);
// update the right link of the node in the left of the new node // update the right link of the node in the left of the new node
if ((other = cachedOther.SetTo(other->left_link)) != NULL) { if ((other = cachedOther.SetTo(other->left_link)) != NULL) {
@@ -1143,7 +1155,7 @@ BPlusTree::Insert(Transaction *transaction,const uint8 *key,uint16 keyLength,off
if (newRoot != BPLUSTREE_NULL) { if (newRoot != BPLUSTREE_NULL) {
bplustree_node *root = cachedNewRoot.Node(); bplustree_node *root = cachedNewRoot.Node();
InsertKey(root,0,keyBuffer,keyLength,node->left_link); InsertKey(root, 0, keyBuffer, keyLength, node->left_link);
root->overflow_link = nodeAndKey.nodeOffset; root->overflow_link = nodeAndKey.nodeOffset;
if (cachedNewRoot.WriteBack(transaction) < B_OK) if (cachedNewRoot.WriteBack(transaction) < B_OK)
@@ -1162,7 +1174,8 @@ BPlusTree::Insert(Transaction *transaction,const uint8 *key,uint16 keyLength,off
status_t status_t
BPlusTree::RemoveDuplicate(Transaction *transaction,bplustree_node *node,CachedNode *cached,uint16 index,off_t value) BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, CachedNode *cached,
uint16 index, off_t value)
{ {
CachedNode cachedDuplicate(this); CachedNode cachedDuplicate(this);
off_t *values = node->Values(); off_t *values = node->Values();
@@ -1170,7 +1183,7 @@ BPlusTree::RemoveDuplicate(Transaction *transaction,bplustree_node *node,CachedN
status_t status; status_t status;
off_t duplicateOffset = bplustree_node::FragmentOffset(oldValue); off_t duplicateOffset = bplustree_node::FragmentOffset(oldValue);
bplustree_node *duplicate = cachedDuplicate.SetTo(duplicateOffset,false); bplustree_node *duplicate = cachedDuplicate.SetTo(duplicateOffset, false);
if (duplicate == NULL) if (duplicate == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -1393,7 +1406,7 @@ BPlusTree::RemoveKey(bplustree_node *node,uint16 index)
*/ */
status_t status_t
BPlusTree::Remove(Transaction *transaction,const uint8 *key,uint16 keyLength,off_t value) BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength, off_t value)
{ {
if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH) if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
@@ -1447,8 +1460,13 @@ BPlusTree::Remove(Transaction *transaction,const uint8 *key,uint16 keyLength,off
if (cached.WriteBack(transaction) < B_OK) if (cached.WriteBack(transaction) < B_OK)
return B_IO_ERROR; return B_IO_ERROR;
fHeader->max_number_of_levels = 1; // if we've cleared the root node, reset the maximum
return fCachedHeader.WriteBack(transaction); // number of levels in the header
if (nodeAndKey.nodeOffset == fHeader->root_node_pointer) {
fHeader->max_number_of_levels = 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
@@ -1493,7 +1511,7 @@ BPlusTree::Remove(Transaction *transaction,const uint8 *key,uint16 keyLength,off
*/ */
status_t status_t
BPlusTree::Replace(Transaction *transaction,const uint8 *key,uint16 keyLength,off_t value) BPlusTree::Replace(Transaction *transaction, const uint8 *key, uint16 keyLength, off_t value)
{ {
if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH
|| key == NULL) || key == NULL)
@@ -1512,7 +1530,7 @@ BPlusTree::Replace(Transaction *transaction,const uint8 *key,uint16 keyLength,of
while ((node = cached.SetTo(nodeOffset)) != NULL) { while ((node = cached.SetTo(nodeOffset)) != NULL) {
uint16 keyIndex = 0; uint16 keyIndex = 0;
off_t nextOffset; off_t nextOffset;
status_t status = FindKey(node,key,keyLength,&keyIndex,&nextOffset); status_t status = FindKey(node, key, keyLength, &keyIndex, &nextOffset);
if (node->overflow_link == BPLUSTREE_NULL) { if (node->overflow_link == BPLUSTREE_NULL) {
if (status == B_OK) { if (status == B_OK) {
@@ -1543,7 +1561,7 @@ BPlusTree::Replace(Transaction *transaction,const uint8 *key,uint16 keyLength,of
*/ */
status_t status_t
BPlusTree::Find(const uint8 *key,uint16 keyLength,off_t *_value) BPlusTree::Find(const uint8 *key, uint16 keyLength, off_t *_value)
{ {
if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH if (keyLength < BPLUSTREE_MIN_KEY_LENGTH || keyLength > BPLUSTREE_MAX_KEY_LENGTH
|| key == NULL) || key == NULL)
@@ -1562,7 +1580,7 @@ BPlusTree::Find(const uint8 *key,uint16 keyLength,off_t *_value)
while ((node = cached.SetTo(nodeOffset)) != NULL) { while ((node = cached.SetTo(nodeOffset)) != NULL) {
uint16 keyIndex = 0; uint16 keyIndex = 0;
off_t nextOffset; off_t nextOffset;
status_t status = FindKey(node,key,keyLength,&keyIndex,&nextOffset); status_t status = FindKey(node, key, keyLength, &keyIndex, &nextOffset);
if (node->overflow_link == BPLUSTREE_NULL) { if (node->overflow_link == BPLUSTREE_NULL) {
if (status == B_OK && _value != NULL) if (status == B_OK && _value != NULL)
@@ -1656,7 +1674,8 @@ TreeIterator::Goto(int8 to)
*/ */
status_t status_t
TreeIterator::Traverse(int8 direction,void *key,uint16 *keyLength,uint16 maxLength,off_t *value,uint16 *duplicate) TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxLength,
off_t *value, uint16 *duplicate)
{ {
if (fTree == NULL) if (fTree == NULL)
return B_INTERRUPTED; return B_INTERRUPTED;
@@ -1681,7 +1700,7 @@ TreeIterator::Traverse(int8 direction,void *key,uint16 *keyLength,uint16 maxLeng
// cause any problems // cause any problems
if (!fIsFragment || fDuplicate < fNumDuplicates) if (!fIsFragment || fDuplicate < fNumDuplicates)
node = cached.SetTo(bplustree_node::FragmentOffset(fDuplicateNode),false); node = cached.SetTo(bplustree_node::FragmentOffset(fDuplicateNode), false);
else else
node = NULL; node = NULL;
@@ -1692,15 +1711,15 @@ TreeIterator::Traverse(int8 direction,void *key,uint16 *keyLength,uint16 maxLeng
// if the node is out of duplicates, we go directly to the next one // if the node is out of duplicates, we go directly to the next one
fDuplicateNode = node->right_link; fDuplicateNode = node->right_link;
if (fDuplicateNode != BPLUSTREE_NULL if (fDuplicateNode != BPLUSTREE_NULL
&& (node = cached.SetTo(fDuplicateNode,false)) != NULL) && (node = cached.SetTo(fDuplicateNode, false)) != NULL)
{ {
fNumDuplicates = node->CountDuplicates(fDuplicateNode,false); fNumDuplicates = node->CountDuplicates(fDuplicateNode, false);
fDuplicate = 0; fDuplicate = 0;
} }
} }
if (fDuplicate < fNumDuplicates) if (fDuplicate < fNumDuplicates)
{ {
*value = node->DuplicateAt(fDuplicateNode,fIsFragment,fDuplicate++); *value = node->DuplicateAt(fDuplicateNode, fIsFragment, fDuplicate++);
if (duplicate) if (duplicate)
*duplicate = 2; *duplicate = 2;
return B_OK; return B_OK;
@@ -1780,10 +1799,10 @@ TreeIterator::Traverse(int8 direction,void *key,uint16 *keyLength,uint16 maxLeng
fIsFragment = type == BPLUSTREE_DUPLICATE_FRAGMENT; fIsFragment = type == BPLUSTREE_DUPLICATE_FRAGMENT;
fNumDuplicates = node->CountDuplicates(offset,fIsFragment); fNumDuplicates = node->CountDuplicates(offset, fIsFragment);
if (fNumDuplicates) if (fNumDuplicates)
{ {
offset = node->DuplicateAt(offset,fIsFragment,0); offset = node->DuplicateAt(offset, fIsFragment, 0);
fDuplicate = 1; fDuplicate = 1;
if (duplicate) if (duplicate)
*duplicate = 1; *duplicate = 1;
@@ -1825,7 +1844,7 @@ TreeIterator::Find(const uint8 *key, uint16 keyLength)
while ((node = cached.SetTo(nodeOffset)) != NULL) { while ((node = cached.SetTo(nodeOffset)) != NULL) {
uint16 keyIndex = 0; uint16 keyIndex = 0;
off_t nextOffset; off_t nextOffset;
status_t status = fTree->FindKey(node,key,keyLength,&keyIndex,&nextOffset); status_t status = fTree->FindKey(node, key, keyLength, &keyIndex, &nextOffset);
if (node->overflow_link == BPLUSTREE_NULL) { if (node->overflow_link == BPLUSTREE_NULL) {
fCurrentNodeOffset = nodeOffset; fCurrentNodeOffset = nodeOffset;
@@ -1850,7 +1869,7 @@ TreeIterator::SkipDuplicates()
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)
return; return;
@@ -1909,7 +1928,7 @@ bplustree_node::Initialize()
uint8 * uint8 *
bplustree_node::KeyAt(int32 index,uint16 *keyLength) const bplustree_node::KeyAt(int32 index, uint16 *keyLength) const
{ {
if (index < 0 || index > all_key_count) if (index < 0 || index > all_key_count)
return NULL; return NULL;
@@ -1926,7 +1945,7 @@ bplustree_node::KeyAt(int32 index,uint16 *keyLength) const
uint8 uint8
bplustree_node::CountDuplicates(off_t offset,bool isFragment) const bplustree_node::CountDuplicates(off_t offset, bool isFragment) const
{ {
// the duplicate fragment handling is currently hard-coded to a node size // the duplicate fragment handling is currently hard-coded to a node size
// of 1024 bytes - with future versions of BFS, this may be a problem // of 1024 bytes - with future versions of BFS, this may be a problem
@@ -1941,7 +1960,7 @@ bplustree_node::CountDuplicates(off_t offset,bool isFragment) const
off_t off_t
bplustree_node::DuplicateAt(off_t offset,bool isFragment,int8 index) const bplustree_node::DuplicateAt(off_t offset, bool isFragment, int8 index) const
{ {
uint32 start; uint32 start;
if (isFragment) if (isFragment)