* Removed unused code when USER is defined - the fs_shell no longer does this, but

provides a kernel emulation layer.
* Renamed all private BPlusTree methods to have the '_' prefix.
* Removed useless set_sem_owner() from Lock.h - all semaphores created in the kernel
  always belong to the system team automatically.
* Some cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21054 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-05-07 12:26:21 +00:00
parent 68f08f67f5
commit 3bef51f0ae
6 changed files with 345 additions and 293 deletions
+259 -198
View File
@@ -1,12 +1,13 @@
/* BPlusTree - BFS B+Tree implementation /*
* Copyright 2001-2007, Axel Dörfler, [email protected].
* This file may be used under the terms of the MIT License.
* *
* Roughly based on 'btlib' written by Marcus J. Ranum - it shares * Roughly based on 'btlib' written by Marcus J. Ranum - it shares
* no code but achieves binary compatibility with the on disk format. * no code but achieves binary compatibility with the on disk format.
*
* Copyright 2001-2006, Axel Dörfler, [email protected].
* This file may be used under the terms of the MIT License.
*/ */
//! B+Tree implementation
#include "Debug.h" #include "Debug.h"
#include "BPlusTree.h" #include "BPlusTree.h"
@@ -215,7 +216,8 @@ CachedNode::InternalSetTo(Transaction *transaction, off_t offset)
uint8 *block; uint8 *block;
if (transaction != NULL) { if (transaction != NULL) {
block = (uint8 *)block_cache_get_writable(volume->BlockCache(), fBlockNumber, transaction->ID()); block = (uint8 *)block_cache_get_writable(volume->BlockCache(),
fBlockNumber, transaction->ID());
fWritable = true; fWritable = true;
} else { } else {
block = (uint8 *)block_cache_get(volume->BlockCache(), fBlockNumber); block = (uint8 *)block_cache_get(volume->BlockCache(), fBlockNumber);
@@ -270,7 +272,8 @@ CachedNode::Free(Transaction &transaction, off_t offset)
status_t status_t
CachedNode::Allocate(Transaction &transaction, bplustree_node **_node, off_t *_offset) CachedNode::Allocate(Transaction &transaction, bplustree_node **_node,
off_t *_offset)
{ {
if (fTree == NULL || fTree->fHeader == NULL || fTree->fStream == NULL) if (fTree == NULL || fTree->fHeader == NULL || fTree->fStream == NULL)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
@@ -307,7 +310,8 @@ CachedNode::Allocate(Transaction &transaction, bplustree_node **_node, off_t *_o
// the maximum_size has to be changed before the call to SetTo() - or // the maximum_size has to be changed before the call to SetTo() - or
// else it will fail because the requested node is out of bounds // else it will fail because the requested node is out of bounds
off_t offset = header->MaximumSize(); off_t offset = header->MaximumSize();
header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(header->MaximumSize() + fTree->fNodeSize); header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(header->MaximumSize()
+ fTree->fNodeSize);
if (SetToWritable(transaction, offset, false) != NULL) { if (SetToWritable(transaction, offset, false) != NULL) {
fNode->Initialize(); fNode->Initialize();
@@ -318,7 +322,8 @@ CachedNode::Allocate(Transaction &transaction, bplustree_node **_node, off_t *_o
} }
// revert header size to old value // revert header size to old value
header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(header->MaximumSize() - fTree->fNodeSize); header->maximum_size = HOST_ENDIAN_TO_BFS_INT64(header->MaximumSize()
- fTree->fNodeSize);
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
} }
@@ -374,8 +379,7 @@ BPlusTree::~BPlusTree()
} }
/** Create a new B+Tree on the specified stream */ /*! 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)
{ {
@@ -397,8 +401,8 @@ BPlusTree::SetTo(Transaction &transaction, Inode *stream, int32 nodeSize)
fHeader = header; fHeader = header;
fAllowDuplicates = ((stream->Mode() & S_INDEX_DIR) == S_INDEX_DIR fAllowDuplicates = ((stream->Mode() & S_INDEX_DIR) == S_INDEX_DIR
&& stream->BlockRun() != stream->Parent()) && stream->BlockRun() != stream->Parent())
|| (stream->Mode() & S_ALLOW_DUPS) != 0; || (stream->Mode() & S_ALLOW_DUPS) != 0;
fNodeSize = nodeSize; fNodeSize = nodeSize;
@@ -460,13 +464,16 @@ BPlusTree::SetTo(Inode *stream)
fNodeSize = fHeader->NodeSize(); fNodeSize = fHeader->NodeSize();
{ {
uint32 toMode[] = {S_STR_INDEX, S_INT_INDEX, S_UINT_INDEX, S_LONG_LONG_INDEX, uint32 toMode[] = {S_STR_INDEX, S_INT_INDEX, S_UINT_INDEX,
S_ULONG_LONG_INDEX, S_FLOAT_INDEX, S_DOUBLE_INDEX}; S_LONG_LONG_INDEX, S_ULONG_LONG_INDEX, S_FLOAT_INDEX,
uint32 mode = stream->Mode() & (S_STR_INDEX | S_INT_INDEX | S_UINT_INDEX | S_LONG_LONG_INDEX S_DOUBLE_INDEX};
| S_ULONG_LONG_INDEX | S_FLOAT_INDEX | S_DOUBLE_INDEX); uint32 mode = stream->Mode() & (S_STR_INDEX | S_INT_INDEX
| S_UINT_INDEX | S_LONG_LONG_INDEX | S_ULONG_LONG_INDEX
| S_FLOAT_INDEX | S_DOUBLE_INDEX);
if (fHeader->DataType() > BPLUSTREE_DOUBLE_TYPE if (fHeader->DataType() > BPLUSTREE_DOUBLE_TYPE
|| (stream->Mode() & S_INDEX_DIR) && toMode[fHeader->DataType()] != mode || (stream->Mode() & S_INDEX_DIR)
&& toMode[fHeader->DataType()] != mode
|| !stream->IsContainer()) { || !stream->IsContainer()) {
D( dump_bplustree_header(fHeader); D( dump_bplustree_header(fHeader);
dump_inode(&stream->Node()); dump_inode(&stream->Node());
@@ -477,8 +484,8 @@ BPlusTree::SetTo(Inode *stream)
// although it's in stat.h, the S_ALLOW_DUPS flag is obviously unused // although it's in stat.h, the S_ALLOW_DUPS flag is obviously unused
// in the original BFS code - we will honour it nevertheless // in the original BFS code - we will honour it nevertheless
fAllowDuplicates = ((stream->Mode() & S_INDEX_DIR) == S_INDEX_DIR fAllowDuplicates = ((stream->Mode() & S_INDEX_DIR) == S_INDEX_DIR
&& stream->BlockRun() != stream->Parent()) && stream->BlockRun() != stream->Parent())
|| (stream->Mode() & S_ALLOW_DUPS) != 0; || (stream->Mode() & S_ALLOW_DUPS) != 0;
} }
CachedNode cached(this, fHeader->RootNode()); CachedNode cached(this, fHeader->RootNode());
@@ -548,8 +555,8 @@ BPlusTree::ModeToKeyType(mode_t mode)
void void
BPlusTree::UpdateIterators(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 splitAt, BPlusTree::_UpdateIterators(off_t offset, off_t nextOffset, uint16 keyIndex,
int8 change) 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
@@ -566,7 +573,7 @@ BPlusTree::UpdateIterators(off_t offset, off_t nextOffset, uint16 keyIndex, uint
void void
BPlusTree::AddIterator(TreeIterator *iterator) BPlusTree::_AddIterator(TreeIterator *iterator)
{ {
if (fIteratorLock.Lock() < B_OK) if (fIteratorLock.Lock() < B_OK)
return; return;
@@ -578,7 +585,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)
return; return;
@@ -590,7 +597,8 @@ BPlusTree::RemoveIterator(TreeIterator *iterator)
int32 int32
BPlusTree::CompareKeys(const void *key1, int keyLength1, const void *key2, int keyLength2) BPlusTree::_CompareKeys(const void *key1, int keyLength1, const void *key2,
int keyLength2)
{ {
type_code type = 0; type_code type = 0;
switch (fHeader->data_type) { switch (fHeader->data_type) {
@@ -621,8 +629,8 @@ BPlusTree::CompareKeys(const void *key1, int keyLength1, const void *key2, int k
status_t status_t
BPlusTree::FindKey(const bplustree_node *node, const uint8 *key, uint16 keyLength, BPlusTree::_FindKey(const bplustree_node *node, const uint8 *key,
uint16 *_index, off_t *_next) uint16 keyLength, uint16 *_index, off_t *_next)
{ {
#ifdef DEBUG #ifdef DEBUG
NodeChecker checker(node, fNodeSize, "find"); NodeChecker checker(node, fNodeSize, "find");
@@ -645,13 +653,14 @@ BPlusTree::FindKey(const bplustree_node *node, const uint8 *key, uint16 keyLengt
uint16 searchLength; uint16 searchLength;
uint8 *searchKey = node->KeyAt(i, &searchLength); uint8 *searchKey = node->KeyAt(i, &searchLength);
if (searchKey + searchLength + sizeof(off_t) + sizeof(uint16) > (uint8 *)node + fNodeSize if (searchKey + searchLength + sizeof(off_t) + sizeof(uint16)
> (uint8 *)node + fNodeSize
|| searchLength > BPLUSTREE_MAX_KEY_LENGTH) { || searchLength > BPLUSTREE_MAX_KEY_LENGTH) {
fStream->GetVolume()->Panic(); fStream->GetVolume()->Panic();
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;
saveIndex = i; saveIndex = i;
@@ -678,13 +687,14 @@ BPlusTree::FindKey(const bplustree_node *node, const uint8 *key, uint16 keyLengt
} }
/** Prepares the stack to contain all nodes that were passed while /*!
* following the key, from the root node to the leaf node that could Prepares the stack to contain all nodes that were passed while
* or should contain that key. following the key, from the root node to the leaf node that could
*/ or should contain that key.
*/
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;
@@ -703,7 +713,8 @@ BPlusTree::SeekDown(Stack<node_and_key> &stack, const uint8 *key, uint16 keyLeng
} }
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);
@@ -714,17 +725,18 @@ BPlusTree::SeekDown(Stack<node_and_key> &stack, const uint8 *key, uint16 keyLeng
nodeAndKey.nodeOffset = nextOffset; nodeAndKey.nodeOffset = nextOffset;
} }
FATAL(("BPlusTree::SeekDown() could not open node %Ld\n", nodeAndKey.nodeOffset)); FATAL(("BPlusTree::SeekDown() could not open node %Ld\n",
nodeAndKey.nodeOffset));
return B_ERROR; return B_ERROR;
} }
/** This will find a free duplicate fragment in the given bplustree_node. /*!
* The CachedNode will be set to the writable fragment on success. This will find a free duplicate fragment in the given bplustree_node.
*/ The CachedNode will be set to the writable fragment on success.
*/
status_t status_t
BPlusTree::FindFreeDuplicateFragment(Transaction &transaction, BPlusTree::_FindFreeDuplicateFragment(Transaction &transaction,
const bplustree_node *node, CachedNode &cached, const bplustree_node *node, CachedNode &cached,
off_t *_offset, bplustree_node **_fragment, uint32 *_index) off_t *_offset, bplustree_node **_fragment, uint32 *_index)
{ {
@@ -765,7 +777,7 @@ BPlusTree::FindFreeDuplicateFragment(Transaction &transaction,
status_t status_t
BPlusTree::InsertDuplicate(Transaction &transaction, CachedNode &cached, BPlusTree::_InsertDuplicate(Transaction &transaction, CachedNode &cached,
const bplustree_node *node, uint16 index, off_t value) const bplustree_node *node, uint16 index, off_t value)
{ {
CachedNode cachedDuplicate(this); CachedNode cachedDuplicate(this);
@@ -784,7 +796,8 @@ BPlusTree::InsertDuplicate(Transaction &transaction, CachedNode &cached,
if (duplicate == NULL) if (duplicate == NULL)
return B_IO_ERROR; return B_IO_ERROR;
duplicate_array *array = duplicate->FragmentAt(bplustree_node::FragmentIndex(oldValue)); duplicate_array *array = duplicate->FragmentAt(
bplustree_node::FragmentIndex(oldValue));
if (array->count > NUM_FRAGMENT_VALUES if (array->count > NUM_FRAGMENT_VALUES
|| array->count < 1) { || array->count < 1) {
FATAL(("insertDuplicate: Invalid array[%d] size in fragment %Ld == %Ld!\n", FATAL(("insertDuplicate: Invalid array[%d] size in fragment %Ld == %Ld!\n",
@@ -803,9 +816,10 @@ BPlusTree::InsertDuplicate(Transaction &transaction, CachedNode &cached,
// reuse it as a duplicate node // reuse it as a duplicate node
offset = bplustree_node::FragmentOffset(oldValue); offset = bplustree_node::FragmentOffset(oldValue);
memmove(duplicate->DuplicateArray(), array, (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); memmove(duplicate->DuplicateArray(), array,
duplicate->left_link = duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64( (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
(uint64)BPLUSTREE_NULL); duplicate->left_link = duplicate->right_link
= HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
array->Insert(value); array->Insert(value);
@@ -816,13 +830,15 @@ BPlusTree::InsertDuplicate(Transaction &transaction, CachedNode &cached,
// the old duplicate has not been touched, so we can reuse it // the old duplicate has not been touched, so we can reuse it
bplustree_node *newDuplicate; bplustree_node *newDuplicate;
status = cachedDuplicate.Allocate(transaction, &newDuplicate, &offset); status = cachedDuplicate.Allocate(transaction,
&newDuplicate, &offset);
if (status < B_OK) if (status < B_OK)
RETURN_ERROR(status); RETURN_ERROR(status);
// 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 = HOST_ENDIAN_TO_BFS_INT64(array->count); newDuplicate->overflow_link = HOST_ENDIAN_TO_BFS_INT64(
array->count);
memcpy(&newDuplicate->all_key_count, &array->values[0], memcpy(&newDuplicate->all_key_count, &array->values[0],
array->count * sizeof(off_t)); 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));
@@ -894,10 +910,11 @@ BPlusTree::InsertDuplicate(Transaction &transaction, CachedNode &cached,
uint32 fragmentIndex = 0; uint32 fragmentIndex = 0;
bplustree_node *fragment; bplustree_node *fragment;
if (FindFreeDuplicateFragment(transaction, node, cachedDuplicate, if (_FindFreeDuplicateFragment(transaction, node, cachedDuplicate,
&offset, &fragment, &fragmentIndex) != B_OK) { &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_ERROR(status); RETURN_ERROR(status);
memset(fragment, 0, fNodeSize); memset(fragment, 0, fNodeSize);
@@ -918,8 +935,8 @@ BPlusTree::InsertDuplicate(Transaction &transaction, CachedNode &cached,
void void
BPlusTree::InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyLength, BPlusTree::_InsertKey(bplustree_node *node, uint16 index, uint8 *key,
off_t value) uint16 keyLength, off_t value)
{ {
// should never happen, but who knows? // should never happen, but who knows?
if (index > node->NumKeys()) if (index > node->NumKeys())
@@ -930,13 +947,15 @@ BPlusTree::InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyL
uint8 *keys = node->Keys(); uint8 *keys = node->Keys();
node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() + 1); node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() + 1);
node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(node->AllKeyLength() + keyLength); node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(node->AllKeyLength()
+ keyLength);
off_t *newValues = node->Values(); off_t *newValues = node->Values();
uint16 *newKeyLengths = node->KeyLengths(); uint16 *newKeyLengths = node->KeyLengths();
// move values and copy new value into them // move values and copy new value into them
memmove(newValues + index + 1, values + index, sizeof(off_t) * (node->NumKeys() - 1 - index)); memmove(newValues + index + 1, values + index,
sizeof(off_t) * (node->NumKeys() - 1 - index));
memmove(newValues, values, sizeof(off_t) * index); memmove(newValues, values, sizeof(off_t) * index);
newValues[index] = HOST_ENDIAN_TO_BFS_INT64(value); newValues[index] = HOST_ENDIAN_TO_BFS_INT64(value);
@@ -950,7 +969,8 @@ BPlusTree::InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyL
int32 keyStart; int32 keyStart;
newKeyLengths[index] = HOST_ENDIAN_TO_BFS_INT16(keyLength newKeyLengths[index] = HOST_ENDIAN_TO_BFS_INT16(keyLength
+ (keyStart = index > 0 ? BFS_ENDIAN_TO_HOST_INT16(newKeyLengths[index - 1]) : 0)); + (keyStart = index > 0
? BFS_ENDIAN_TO_HOST_INT16(newKeyLengths[index - 1]) : 0));
// move keys and copy new key into them // move keys and copy new key into them
uint16 length = BFS_ENDIAN_TO_HOST_INT16(newKeyLengths[index]); uint16 length = BFS_ENDIAN_TO_HOST_INT16(newKeyLengths[index]);
@@ -962,14 +982,15 @@ BPlusTree::InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyL
} }
/** Splits the \a node into two halves - the other half will be put into \a other. /*!
* It also takes care to create a new overflow link if the node to split is an Splits the \a node into two halves - the other half will be put into \a other.
* index node. It also takes care to create a new overflow link if the node to split is an
*/ index node.
*/
status_t status_t
BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *other, BPlusTree::_SplitNode(bplustree_node *node, off_t nodeOffset,
off_t otherOffset, uint16 *_keyIndex, uint8 *key, uint16 *_keyLength, off_t *_value) bplustree_node *other, off_t otherOffset, uint16 *_keyIndex, uint8 *key,
uint16 *_keyLength, off_t *_value)
{ {
if (*_keyIndex > node->NumKeys() + 1) if (*_keyIndex > node->NumKeys() + 1)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -992,14 +1013,18 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
size_t size = fNodeSize >> 1; size_t size = fNodeSize >> 1;
int32 out, in; int32 out, in;
for (in = out = 0; in < node->NumKeys() + 1;) { for (in = out = 0; in < node->NumKeys() + 1;) {
if (!bytes) if (!bytes) {
bytesBefore = in > 0 ? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0; bytesBefore = in > 0
? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0;
}
if (in == keyIndex && !bytes) { if (in == keyIndex && !bytes) {
bytes = *_keyLength; bytes = *_keyLength;
} else { } else {
if (keyIndex < out) if (keyIndex < out) {
bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in]) - bytesBefore; bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in])
- bytesBefore;
}
in++; in++;
} }
@@ -1022,7 +1047,8 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
other->left_link = node->left_link; other->left_link = node->left_link;
other->right_link = HOST_ENDIAN_TO_BFS_INT64(nodeOffset); other->right_link = HOST_ENDIAN_TO_BFS_INT64(nodeOffset);
other->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore + bytesAfter); other->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore
+ bytesAfter);
other->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out); other->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out);
uint16 *outKeyLengths = other->KeyLengths(); uint16 *outKeyLengths = other->KeyLengths();
@@ -1043,13 +1069,15 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
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] = HOST_ENDIAN_TO_BFS_INT16( outKeyLengths[keyIndex + i + 1] = HOST_ENDIAN_TO_BFS_INT16(
BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[keyIndex + i]) + bytes); BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[keyIndex + i]) + bytes);
} }
memcpy(outKeyValues + keyIndex + 1, inKeyValues + keyIndex, keys * sizeof(off_t)); memcpy(outKeyValues + keyIndex + 1, inKeyValues + keyIndex,
keys * sizeof(off_t));
} }
} }
@@ -1080,7 +1108,8 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
// If a key is dropped (is not the new key), we have to copy // If a key is dropped (is not the new key), we have to copy
// it, because it would be lost if not. // it, because it would be lost if not.
uint8 *droppedKey = node->KeyAt(in, &newLength); uint8 *droppedKey = node->KeyAt(in, &newLength);
if (droppedKey + newLength + sizeof(off_t) + sizeof(uint16) > (uint8 *)node + fNodeSize if (droppedKey + newLength + sizeof(off_t) + sizeof(uint16)
> (uint8 *)node + fNodeSize
|| newLength > BPLUSTREE_MAX_KEY_LENGTH) { || newLength > BPLUSTREE_MAX_KEY_LENGTH) {
fStream->GetVolume()->Panic(); fStream->GetVolume()->Panic();
RETURN_ERROR(B_BAD_DATA); RETURN_ERROR(B_BAD_DATA);
@@ -1106,7 +1135,8 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
// it's enough to set bytesBefore once here, because we do // it's enough to set bytesBefore once here, because we do
// not need to know the exact length of all keys in this // not need to know the exact length of all keys in this
// loop // loop
bytesBefore = in > skip ? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0; bytesBefore = in > skip
? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0;
bytes = *_keyLength; bytes = *_keyLength;
} else { } else {
if (in < node->NumKeys()) { if (in < node->NumKeys()) {
@@ -1132,9 +1162,10 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
} }
// adjust the byte counts (since we were a bit lazy in the loop) // adjust the byte counts (since we were a bit lazy in the loop)
if (keyIndex >= in && keyIndex - skip < out) if (keyIndex >= in && keyIndex - skip < out) {
bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in]) - bytesBefore - total; bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in])
else if (keyIndex < skip) - bytesBefore - total;
} else if (keyIndex < skip)
bytesBefore = node->AllKeyLength() - total; bytesBefore = node->AllKeyLength() - total;
if (bytesBefore < 0 || bytesAfter < 0) if (bytesBefore < 0 || bytesAfter < 0)
@@ -1142,7 +1173,8 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
node->left_link = HOST_ENDIAN_TO_BFS_INT64(otherOffset); node->left_link = HOST_ENDIAN_TO_BFS_INT64(otherOffset);
// right link, and overflow link can stay the same // right link, and overflow link can stay the same
node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore + bytesAfter); node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore
+ bytesAfter);
node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out - 1); node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out - 1);
// array positions have changed // array positions have changed
@@ -1157,19 +1189,25 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
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)
@@ -1196,14 +1234,16 @@ BPlusTree::SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *oth
} }
/** This inserts a key into the tree. The changes made to the tree will /*!
* all be part of the \a transaction. This inserts a key into the tree. The changes made to the tree will
*/ all be part of the \a transaction.
*/
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);
#ifdef DEBUG #ifdef DEBUG
if (value < 0) if (value < 0)
@@ -1214,7 +1254,7 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
WriteLocked locked(fStream->Lock()); WriteLocked locked(fStream->Lock());
Stack<node_and_key> stack; Stack<node_and_key> stack;
if (SeekDown(stack, key, keyLength) != B_OK) if (_SeekDown(stack, key, keyLength) != B_OK)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
uint8 keyBuffer[BPLUSTREE_MAX_KEY_LENGTH + 1]; uint8 keyBuffer[BPLUSTREE_MAX_KEY_LENGTH + 1];
@@ -1226,23 +1266,26 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
const bplustree_node *node; const bplustree_node *node;
CachedNode cached(this); CachedNode cached(this);
while (stack.Pop(&nodeAndKey) && (node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL) { while (stack.Pop(&nodeAndKey)
&& (node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL) {
#ifdef DEBUG #ifdef DEBUG
NodeChecker checker(node, fNodeSize, "insert"); NodeChecker checker(node, fNodeSize, "insert");
#endif #endif
if (node->IsLeaf()) { if (node->IsLeaf()) {
// first round, check for duplicate entries // first round, check for duplicate entries
status_t status = FindKey(node, key, keyLength, &nodeAndKey.keyIndex); status_t status = _FindKey(node, key, keyLength,
&nodeAndKey.keyIndex);
// is this a duplicate entry? // is this a duplicate entry?
if (status == B_OK) { if (status == B_OK) {
if (fAllowDuplicates) { if (fAllowDuplicates) {
status = InsertDuplicate(transaction, cached, node, nodeAndKey.keyIndex, value); status = _InsertDuplicate(transaction, cached, node,
nodeAndKey.keyIndex, value);
if (status != B_OK) if (status != B_OK)
RETURN_ERROR(status); RETURN_ERROR(status);
return B_OK; return B_OK;
} }
RETURN_ERROR(B_NAME_IN_USE); RETURN_ERROR(B_NAME_IN_USE);
} }
} }
@@ -1252,11 +1295,14 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
return B_IO_ERROR; return B_IO_ERROR;
// is the node big enough to hold the pair? // is the node big enough to hold the pair?
if (int32(round_up(sizeof(bplustree_node) + writableNode->AllKeyLength() + keyLength) if (int32(round_up(sizeof(bplustree_node)
+ (writableNode->NumKeys() + 1) * (sizeof(uint16) + sizeof(off_t))) < fNodeSize) + writableNode->AllKeyLength() + keyLength)
{ + (writableNode->NumKeys() + 1) * (sizeof(uint16)
InsertKey(writableNode, nodeAndKey.keyIndex, keyBuffer, keyLength, value); + sizeof(off_t))) < fNodeSize) {
UpdateIterators(nodeAndKey.nodeOffset, BPLUSTREE_NULL, nodeAndKey.keyIndex, 0, 1); _InsertKey(writableNode, nodeAndKey.keyIndex,
keyBuffer, keyLength, value);
_UpdateIterators(nodeAndKey.nodeOffset, BPLUSTREE_NULL,
nodeAndKey.keyIndex, 0, 1);
return B_OK; return B_OK;
} else { } else {
@@ -1268,7 +1314,8 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
off_t newRoot = BPLUSTREE_NULL; off_t newRoot = BPLUSTREE_NULL;
if (nodeAndKey.nodeOffset == fHeader->RootNode()) { if (nodeAndKey.nodeOffset == fHeader->RootNode()) {
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
@@ -1283,14 +1330,16 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
// 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(writableNode, nodeAndKey.nodeOffset, other, otherOffset, if (_SplitNode(writableNode, nodeAndKey.nodeOffset, other,
&nodeAndKey.keyIndex, keyBuffer, &keyLength, &value) < B_OK) { otherOffset, &nodeAndKey.keyIndex, keyBuffer, &keyLength,
&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);
@@ -1302,11 +1351,12 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
NodeChecker otherChecker(other, fNodeSize, "insert split other"); NodeChecker otherChecker(other, fNodeSize, "insert split other");
#endif #endif
UpdateIterators(nodeAndKey.nodeOffset, otherOffset, nodeAndKey.keyIndex, _UpdateIterators(nodeAndKey.nodeOffset, otherOffset,
writableNode->NumKeys(), 1); nodeAndKey.keyIndex, writableNode->NumKeys(), 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.SetToWritable(transaction, other->LeftLink())) != NULL) { if ((other = cachedOther.SetToWritable(transaction,
other->LeftLink())) != NULL) {
other->right_link = HOST_ENDIAN_TO_BFS_INT64(otherOffset); other->right_link = HOST_ENDIAN_TO_BFS_INT64(otherOffset);
} }
@@ -1314,16 +1364,20 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
if (newRoot != BPLUSTREE_NULL) { if (newRoot != BPLUSTREE_NULL) {
bplustree_node *root = cachedNewRoot.Node(); bplustree_node *root = cachedNewRoot.Node();
InsertKey(root, 0, keyBuffer, keyLength, writableNode->LeftLink()); _InsertKey(root, 0, keyBuffer, keyLength,
root->overflow_link = HOST_ENDIAN_TO_BFS_INT64(nodeAndKey.nodeOffset); writableNode->LeftLink());
root->overflow_link = HOST_ENDIAN_TO_BFS_INT64(
nodeAndKey.nodeOffset);
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;
// finally, update header to point to the new root // finally, update header to point to the new root
header->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(newRoot); header->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(newRoot);
header->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(header->MaxNumberOfLevels() + 1); header->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(
header->MaxNumberOfLevels() + 1);
return B_OK; return B_OK;
} }
@@ -1333,13 +1387,14 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
} }
/** Removes the duplicate index/value pair from the tree. /*!
* It's part of the private tree interface. Removes the duplicate index/value pair from the tree.
*/ It's part of the private tree interface.
*/
status_t status_t
BPlusTree::RemoveDuplicate(Transaction &transaction, const bplustree_node *node, BPlusTree::_RemoveDuplicate(Transaction &transaction,
CachedNode &cached, uint16 index, off_t value) const bplustree_node *node, CachedNode &cached, uint16 index,
off_t value)
{ {
off_t *values = node->Values(); off_t *values = node->Values();
off_t oldValue = BFS_ENDIAN_TO_HOST_INT64(values[index]); off_t oldValue = BFS_ENDIAN_TO_HOST_INT64(values[index]);
@@ -1353,7 +1408,8 @@ BPlusTree::RemoveDuplicate(Transaction &transaction, const bplustree_node *node,
// if it's a duplicate fragment, remove the entry from there // if it's a duplicate fragment, remove the entry from there
if (bplustree_node::LinkType(oldValue) == BPLUSTREE_DUPLICATE_FRAGMENT) { if (bplustree_node::LinkType(oldValue) == BPLUSTREE_DUPLICATE_FRAGMENT) {
duplicate_array *array = duplicate->FragmentAt(bplustree_node::FragmentIndex(oldValue)); duplicate_array *array = duplicate->FragmentAt(
bplustree_node::FragmentIndex(oldValue));
if (array->count > NUM_FRAGMENT_VALUES if (array->count > NUM_FRAGMENT_VALUES
|| array->count < 1) { || array->count < 1) {
@@ -1488,7 +1544,7 @@ BPlusTree::RemoveDuplicate(Transaction &transaction, const bplustree_node *node,
bplustree_node *fragment = NULL; bplustree_node *fragment = NULL;
uint32 fragmentIndex = 0; uint32 fragmentIndex = 0;
off_t offset; off_t offset;
if (FindFreeDuplicateFragment(transaction, node, cachedOther, if (_FindFreeDuplicateFragment(transaction, node, cachedOther,
&offset, &fragment, &fragmentIndex) == B_OK) { &offset, &fragment, &fragmentIndex) == B_OK) {
// move to other node // move to other node
duplicate_array *target = fragment->FragmentAt(fragmentIndex); duplicate_array *target = fragment->FragmentAt(fragmentIndex);
@@ -1514,14 +1570,14 @@ BPlusTree::RemoveDuplicate(Transaction &transaction, const bplustree_node *node,
} }
/** Removes the key with the given index from the specified node. /*!
* Since it has to get the key from the node anyway (to obtain it's Removes the key with the given index from the specified node.
* pointer), it's not needed to pass the key & its length, although Since it has to get the key from the node anyway (to obtain it's
* the calling method (BPlusTree::Remove()) have this data. pointer), it's not needed to pass the key & its length, although
*/ the calling method (BPlusTree::Remove()) have this data.
*/
void void
BPlusTree::RemoveKey(bplustree_node *node, uint16 index) BPlusTree::_RemoveKey(bplustree_node *node, uint16 index)
{ {
// should never happen, but who knows? // should never happen, but who knows?
if (index > node->NumKeys() && node->NumKeys() > 0) { if (index > node->NumKeys() && node->NumKeys() > 0) {
@@ -1575,35 +1631,38 @@ BPlusTree::RemoveKey(bplustree_node *node, uint16 index)
} }
/** Removes the specified key from the tree. The "value" parameter is only used /*!
* for trees which allow duplicates, so you may safely ignore it. Removes the specified key from the tree. The "value" parameter is only used
* It's not an optional parameter, so at least you have to think about it. for trees which allow duplicates, so you may safely ignore it.
*/ It's not an optional parameter, so at least you have to think about it.
*/
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);
// lock access to stream // lock access to stream
WriteLocked locked(fStream->Lock()); WriteLocked locked(fStream->Lock());
Stack<node_and_key> stack; Stack<node_and_key> stack;
if (SeekDown(stack, key, keyLength) != B_OK) if (_SeekDown(stack, key, keyLength) != B_OK)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
node_and_key nodeAndKey; node_and_key nodeAndKey;
const bplustree_node *node; const bplustree_node *node;
CachedNode cached(this); CachedNode cached(this);
while (stack.Pop(&nodeAndKey) && (node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL) { while (stack.Pop(&nodeAndKey)
&& (node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL) {
#ifdef DEBUG #ifdef DEBUG
NodeChecker checker(node, fNodeSize, "remove"); NodeChecker checker(node, fNodeSize, "remove");
#endif #endif
if (node->IsLeaf()) { if (node->IsLeaf()) {
// first round, check for duplicate entries // first round, check for duplicate entries
status_t status = FindKey(node, key, keyLength, &nodeAndKey.keyIndex); status_t status = _FindKey(node, key, keyLength, &nodeAndKey.keyIndex);
if (status < B_OK) if (status < B_OK)
RETURN_ERROR(status); RETURN_ERROR(status);
@@ -1611,15 +1670,16 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
// to the next node after the current - if there aren't any // to the next node after the current - if there aren't any
// more nodes, we need a way to prevent the TreeIterators to // more nodes, we need a way to prevent the TreeIterators to
// touch the old node again, we use BPLUSTREE_FREE for this // touch the old node again, we use BPLUSTREE_FREE for this
off_t next = node->RightLink() == BPLUSTREE_NULL ? BPLUSTREE_FREE : node->RightLink(); off_t next = node->RightLink() == BPLUSTREE_NULL
UpdateIterators(nodeAndKey.nodeOffset, node->NumKeys() == 1 ? ? BPLUSTREE_FREE : node->RightLink();
next : BPLUSTREE_NULL, nodeAndKey.keyIndex, 0 , -1); _UpdateIterators(nodeAndKey.nodeOffset, node->NumKeys() == 1
? next : BPLUSTREE_NULL, nodeAndKey.keyIndex, 0 , -1);
// is this a duplicate entry? // is this a duplicate entry?
if (bplustree_node::IsDuplicate(BFS_ENDIAN_TO_HOST_INT64( if (bplustree_node::IsDuplicate(BFS_ENDIAN_TO_HOST_INT64(
node->Values()[nodeAndKey.keyIndex]))) { node->Values()[nodeAndKey.keyIndex]))) {
if (fAllowDuplicates) { if (fAllowDuplicates) {
return RemoveDuplicate(transaction, node, cached, return _RemoveDuplicate(transaction, node, cached,
nodeAndKey.keyIndex, value); nodeAndKey.keyIndex, value);
} else { } else {
FATAL(("dupliate node found where no duplicates are allowed!\n")); FATAL(("dupliate node found where no duplicates are allowed!\n"));
@@ -1658,7 +1718,7 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
// the overflow link, so we have to drop the last key) // the overflow link, so we have to drop the last key)
if (writableNode->NumKeys() > 1 if (writableNode->NumKeys() > 1
|| !writableNode->IsLeaf() && writableNode->NumKeys() == 1) { || !writableNode->IsLeaf() && writableNode->NumKeys() == 1) {
RemoveKey(writableNode, nodeAndKey.keyIndex); _RemoveKey(writableNode, nodeAndKey.keyIndex);
return B_OK; return B_OK;
} }
@@ -1680,19 +1740,21 @@ BPlusTree::Remove(Transaction &transaction, const uint8 *key, uint16 keyLength,
} }
/** Replaces the value for the key in the tree. /*!
* Returns B_OK if the key could be found and its value replaced, Replaces the value for the key in the tree.
* B_ENTRY_NOT_FOUND if the key couldn't be found, and other errors Returns B_OK if the key could be found and its value replaced,
* to indicate that something went terribly wrong. B_ENTRY_NOT_FOUND if the key couldn't be found, and other errors
* Note that this doesn't work with duplicates - it will just to indicate that something went terribly wrong.
* return B_BAD_TYPE if you call this function on a tree where Note that this doesn't work with duplicates - it will just
* duplicates are allowed. return B_BAD_TYPE if you call this function on a tree where
*/ duplicates are allowed.
*/
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)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
@@ -1709,7 +1771,7 @@ BPlusTree::Replace(Transaction &transaction, 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 = FindKey(node, key, keyLength, &keyIndex, &nextOffset); status_t status = _FindKey(node, key, keyLength, &keyIndex, &nextOffset);
if (node->OverflowLink() == BPLUSTREE_NULL) { if (node->OverflowLink() == BPLUSTREE_NULL) {
if (status == B_OK) { if (status == B_OK) {
@@ -1730,22 +1792,23 @@ BPlusTree::Replace(Transaction &transaction, const uint8 *key, uint16 keyLength,
} }
/** Searches the key in the tree, and stores the offset found in /*!
* _value, if successful. Searches the key in the tree, and stores the offset found in
* It's very similar to BPlusTree::SeekDown(), but doesn't fill _value, if successful.
* a stack while it descends the tree. It's very similar to BPlusTree::SeekDown(), but doesn't fill
* Returns B_OK when the key could be found, B_ENTRY_NOT_FOUND a stack while it descends the tree.
* if not. It can also return other errors to indicate that Returns B_OK when the key could be found, B_ENTRY_NOT_FOUND
* something went wrong. if not. It can also return other errors to indicate that
* Note that this doesn't work with duplicates - it will just something went wrong.
* return B_BAD_TYPE if you call this function on a tree where Note that this doesn't work with duplicates - it will just
* duplicates are allowed. return B_BAD_TYPE if you call this function on a tree where
*/ duplicates are allowed.
*/
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)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
@@ -1766,7 +1829,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);
#ifdef DEBUG #ifdef DEBUG
levels++; levels++;
@@ -1799,14 +1862,14 @@ TreeIterator::TreeIterator(BPlusTree *tree)
fCurrentNodeOffset(BPLUSTREE_NULL), fCurrentNodeOffset(BPLUSTREE_NULL),
fNext(NULL) fNext(NULL)
{ {
tree->AddIterator(this); tree->_AddIterator(this);
} }
TreeIterator::~TreeIterator() TreeIterator::~TreeIterator()
{ {
if (fTree) if (fTree)
fTree->RemoveIterator(this); fTree->_RemoveIterator(this);
} }
@@ -1840,7 +1903,8 @@ TreeIterator::Goto(int8 to)
nextOffset = node->OverflowLink(); nextOffset = node->OverflowLink();
else { else {
if (node->AllKeyLength() > fTree->fNodeSize if (node->AllKeyLength() > fTree->fNodeSize
|| (uint32)node->Values() > (uint32)node + fTree->fNodeSize - 8 * node->NumKeys()) || (uint32)node->Values() > (uint32)node + fTree->fNodeSize
- 8 * node->NumKeys())
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
nextOffset = BFS_ENDIAN_TO_HOST_INT64(node->Values()[0]); nextOffset = BFS_ENDIAN_TO_HOST_INT64(node->Values()[0]);
@@ -1856,21 +1920,21 @@ TreeIterator::Goto(int8 to)
} }
/** Iterates through the tree in the specified direction. /*!
* When it iterates through duplicates, the "key" is only updated for the Iterates through the tree in the specified direction.
* first entry - if you need to know when this happens, use the "duplicate" When it iterates through duplicates, the "key" is only updated for the
* parameter which is 0 for no duplicate, 1 for the first, and 2 for all first entry - if you need to know when this happens, use the "duplicate"
* the other duplicates. parameter which is 0 for no duplicate, 1 for the first, and 2 for all
* That's not too nice, but saves the 256 bytes that would be needed to the other duplicates.
* store the last key - if this will ever become an issue, it will be That's not too nice, but saves the 256 bytes that would be needed to
* easy to change. store the last key - if this will ever become an issue, it will be
* The other advantage of this is, that the queries can skip all duplicates easy to change.
* at once when they are not relevant to them. The other advantage of this is, that the queries can skip all duplicates
*/ at once when they are not relevant to them.
*/
status_t status_t
TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxLength, TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength,
off_t *value, uint16 *duplicate) uint16 maxLength, off_t *value, uint16 *duplicate)
{ {
if (fTree == NULL) if (fTree == NULL)
return B_INTERRUPTED; return B_INTERRUPTED;
@@ -2007,11 +2071,11 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
} }
/** This is more or less a copy of BPlusTree::Find() - but it just /*!
* sets the current position in the iterator, regardless of if the This is more or less a copy of BPlusTree::Find() - but it just
* key could be found or not. sets the current position in the iterator, regardless of if the
*/ key could be found or not.
*/
status_t status_t
TreeIterator::Find(const uint8 *key, uint16 keyLength) TreeIterator::Find(const uint8 *key, uint16 keyLength)
{ {
@@ -2031,7 +2095,8 @@ 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->OverflowLink() == BPLUSTREE_NULL) { if (node->OverflowLink() == BPLUSTREE_NULL) {
fCurrentNodeOffset = nodeOffset; fCurrentNodeOffset = nodeOffset;
@@ -2160,12 +2225,11 @@ bplustree_node::DuplicateAt(off_t offset, bool isFragment, int8 index) const
} }
/** Although the name suggests it, this function doesn't return the real /*! Although the name suggests it, this function doesn't return the real
* used fragment count; at least, it can only count to two: it returns used fragment count; at least, it can only count to two: it returns
* 0, if there is no fragment used, 1 if there is only one fragment 0, if there is no fragment used, 1 if there is only one fragment
* used, and 2 if there are at least 2 fragments used. used, and 2 if there are at least 2 fragments used.
*/ */
uint32 uint32
bplustree_node::FragmentsUsed(uint32 nodeSize) const bplustree_node::FragmentsUsed(uint32 nodeSize) const
{ {
@@ -2210,14 +2274,11 @@ bplustree_node::CheckIntegrity(uint32 nodeSize) const
int32 int32
compareKeys(type_code type, const void *key1, int keyLength1, const void *key2, int keyLength2) compareKeys(type_code type, const void *key1, int keyLength1,
const void *key2, int keyLength2)
{ {
// if one of the keys is NULL, bail out gracefully // if one of the keys is NULL, bail out gracefully
if (key1 == NULL || key2 == NULL) { if (key1 == NULL || key2 == NULL) {
//#if USER
// // that's here to see if it's reasonable to handle this case nicely at all
// DEBUGGER(("compareKeys() got NULL key!"));
//#endif
// even if it's most probably a bug in the calling code, we try to // even if it's most probably a bug in the calling code, we try to
// give a meaningful result // give a meaningful result
if (key1 == NULL && key2 != NULL) if (key1 == NULL && key2 != NULL)
+79 -60
View File
@@ -1,9 +1,5 @@
/* BPlusTree - BFS B+Tree implementation /*
* * Copyright 2001-2007, Axel Dörfler, axeld@pinc-software.de.
* Roughly based on 'btlib' written by Marcus J. Ranum - it shares
* no code but achieves binary compatibility with the on disk format.
*
* Copyright 2001-2005, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
#ifndef B_PLUS_TREE_H #ifndef B_PLUS_TREE_H
@@ -15,7 +11,7 @@
#include "Chain.h" #include "Chain.h"
//****************** on-disk structures ******************** // #pragma mark - on-disk structures
struct bplustree_node; struct bplustree_node;
@@ -37,7 +33,8 @@ struct bplustree_header {
off_t RootNode() const { return BFS_ENDIAN_TO_HOST_INT64(root_node_pointer); } off_t RootNode() const { return BFS_ENDIAN_TO_HOST_INT64(root_node_pointer); }
off_t FreeNode() const { return BFS_ENDIAN_TO_HOST_INT64(free_node_pointer); } off_t FreeNode() const { return BFS_ENDIAN_TO_HOST_INT64(free_node_pointer); }
off_t MaximumSize() const { return BFS_ENDIAN_TO_HOST_INT64(maximum_size); } off_t MaximumSize() const { return BFS_ENDIAN_TO_HOST_INT64(maximum_size); }
uint32 MaxNumberOfLevels() const { return BFS_ENDIAN_TO_HOST_INT32(max_number_of_levels); } uint32 MaxNumberOfLevels() const
{ return BFS_ENDIAN_TO_HOST_INT32(max_number_of_levels); }
inline bool CheckNode(bplustree_node *node) const; inline bool CheckNode(bplustree_node *node) const;
inline bool IsValidLink(off_t link) const; inline bool IsValidLink(off_t link) const;
@@ -119,7 +116,7 @@ enum bplustree_traversing {
}; };
//****************** in-memory structures ******************** // #pragma mark - in-memory structures
template<class T> class Stack; template<class T> class Stack;
class BPlusTree; class BPlusTree;
@@ -134,8 +131,6 @@ struct node_and_key {
}; };
//***** Cache handling *****
class CachedNode { class CachedNode {
public: public:
CachedNode(BPlusTree *tree) CachedNode(BPlusTree *tree)
@@ -159,7 +154,8 @@ class CachedNode {
} }
const bplustree_node *SetTo(off_t offset, bool check = true); const bplustree_node *SetTo(off_t offset, bool check = true);
bplustree_node *SetToWritable(Transaction &transaction, off_t offset, bool check = true); bplustree_node *SetToWritable(Transaction &transaction, off_t offset,
bool check = true);
bplustree_node *MakeWritable(Transaction &transaction); bplustree_node *MakeWritable(Transaction &transaction);
const bplustree_header *SetToHeader(); const bplustree_header *SetToHeader();
bplustree_header *SetToWritableHeader(Transaction &transaction); bplustree_header *SetToWritableHeader(Transaction &transaction);
@@ -169,7 +165,8 @@ class CachedNode {
void Unset(); void Unset();
status_t Free(Transaction &transaction, off_t offset); status_t Free(Transaction &transaction, off_t offset);
status_t Allocate(Transaction &transaction, bplustree_node **node, off_t *offset); status_t Allocate(Transaction &transaction, bplustree_node **node,
off_t *offset);
bool IsWritable() const { return fWritable; } bool IsWritable() const { return fWritable; }
bplustree_node *Node() const { return fNode; } bplustree_node *Node() const { return fNode; }
@@ -185,27 +182,31 @@ class CachedNode {
}; };
//******** B+tree class *********
class BPlusTree { class BPlusTree {
public: public:
BPlusTree(Transaction &transaction, Inode *stream, int32 nodeSize = BPLUSTREE_NODE_SIZE); BPlusTree(Transaction &transaction, Inode *stream,
int32 nodeSize = BPLUSTREE_NODE_SIZE);
BPlusTree(Inode *stream); BPlusTree(Inode *stream);
BPlusTree(); BPlusTree();
~BPlusTree(); ~BPlusTree();
status_t SetTo(Transaction &transaction, Inode *stream, int32 nodeSize = BPLUSTREE_NODE_SIZE); status_t SetTo(Transaction &transaction, Inode *stream,
int32 nodeSize = BPLUSTREE_NODE_SIZE);
status_t SetTo(Inode *stream); status_t SetTo(Inode *stream);
status_t SetStream(Inode *stream); status_t SetStream(Inode *stream);
status_t InitCheck(); status_t InitCheck();
status_t Validate(); status_t Validate();
status_t Remove(Transaction &transaction, const uint8 *key, uint16 keyLength, off_t value); status_t Remove(Transaction &transaction, const uint8 *key,
status_t Insert(Transaction &transaction, const uint8 *key, uint16 keyLength, off_t value); uint16 keyLength, off_t value);
status_t Insert(Transaction &transaction, const uint8 *key,
uint16 keyLength, off_t value);
status_t Remove(Transaction &transaction, const char *key, off_t value); status_t Remove(Transaction &transaction, const char *key,
status_t Insert(Transaction &transaction, const char *key, off_t value); off_t value);
status_t Insert(Transaction &transaction, const char *key,
off_t value);
status_t Insert(Transaction &transaction, int32 key, off_t value); status_t Insert(Transaction &transaction, int32 key, off_t value);
status_t Insert(Transaction &transaction, uint32 key, off_t value); status_t Insert(Transaction &transaction, uint32 key, off_t value);
status_t Insert(Transaction &transaction, int64 key, off_t value); status_t Insert(Transaction &transaction, int64 key, off_t value);
@@ -213,7 +214,8 @@ class BPlusTree {
status_t Insert(Transaction &transaction, float key, off_t value); status_t Insert(Transaction &transaction, float key, off_t value);
status_t Insert(Transaction &transaction, double key, off_t value); status_t Insert(Transaction &transaction, double key, off_t value);
status_t Replace(Transaction &transaction, const uint8 *key, uint16 keyLength, off_t value); status_t Replace(Transaction &transaction, const uint8 *key,
uint16 keyLength, off_t value);
status_t Find(const uint8 *key, uint16 keyLength, off_t *value); status_t Find(const uint8 *key, uint16 keyLength, off_t *value);
static int32 TypeCodeToKeyType(type_code code); static int32 TypeCodeToKeyType(type_code code);
@@ -224,30 +226,37 @@ class BPlusTree {
BPlusTree &operator=(const BPlusTree &); BPlusTree &operator=(const BPlusTree &);
// no implementation // no implementation
int32 CompareKeys(const void *key1, int keylength1, const void *key2, int keylength2); int32 _CompareKeys(const void *key1, int keylength1,
status_t FindKey(const bplustree_node *node, const uint8 *key, uint16 keyLength, const void *key2, int keylength2);
uint16 *index = NULL, off_t *next = NULL); status_t _FindKey(const bplustree_node *node, const uint8 *key,
status_t SeekDown(Stack<node_and_key> &stack, const uint8 *key, uint16 keyLength); uint16 keyLength, uint16 *index = NULL,
off_t *next = NULL);
status_t _SeekDown(Stack<node_and_key> &stack, const uint8 *key,
uint16 keyLength);
status_t FindFreeDuplicateFragment(Transaction &transaction, status_t _FindFreeDuplicateFragment(Transaction &transaction,
const bplustree_node *node, CachedNode &cached, const bplustree_node *node, CachedNode &cached,
off_t *_offset, bplustree_node **_fragment, uint32 *_index); off_t *_offset, bplustree_node **_fragment,
status_t InsertDuplicate(Transaction &transaction, CachedNode &cached, uint32 *_index);
const bplustree_node *node, uint16 index, off_t value); status_t _InsertDuplicate(Transaction &transaction,
void InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyLength, CachedNode &cached, const bplustree_node *node,
off_t value); uint16 index, off_t value);
status_t SplitNode(bplustree_node *node, off_t nodeOffset, bplustree_node *other, void _InsertKey(bplustree_node *node, uint16 index, uint8 *key,
off_t otherOffset, uint16 *_keyIndex, uint8 *key, uint16 *_keyLength, uint16 keyLength, off_t value);
status_t _SplitNode(bplustree_node *node, off_t nodeOffset,
bplustree_node *other, off_t otherOffset,
uint16 *_keyIndex, uint8 *key, uint16 *_keyLength,
off_t *_value); off_t *_value);
status_t RemoveDuplicate(Transaction &transaction, const bplustree_node *node, status_t _RemoveDuplicate(Transaction &transaction,
CachedNode &cached, uint16 keyIndex, off_t value); const bplustree_node *node, CachedNode &cached,
void RemoveKey(bplustree_node *node, uint16 index); uint16 keyIndex, off_t value);
void _RemoveKey(bplustree_node *node, uint16 index);
void UpdateIterators(off_t offset, off_t nextOffset, uint16 keyIndex, void _UpdateIterators(off_t offset, off_t nextOffset,
uint16 splitAt, int8 change); uint16 keyIndex, uint16 splitAt, int8 change);
void AddIterator(TreeIterator *iterator); void _AddIterator(TreeIterator *iterator);
void RemoveIterator(TreeIterator *iterator); void _RemoveIterator(TreeIterator *iterator);
private: private:
friend class TreeIterator; friend class TreeIterator;
@@ -264,7 +273,7 @@ class BPlusTree {
}; };
//***** helper classes/functions ***** // #pragma mark - helper classes/functions
extern int32 compareKeys(type_code type, const void *key1, int keyLength1, extern int32 compareKeys(type_code type, const void *key1, int keyLength1,
const void *key2, int keyLength2); const void *key2, int keyLength2);
@@ -275,15 +284,17 @@ class TreeIterator {
~TreeIterator(); ~TreeIterator();
status_t Goto(int8 to); status_t Goto(int8 to);
status_t Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxLength, status_t Traverse(int8 direction, void *key, uint16 *keyLength,
off_t *value, uint16 *duplicate = NULL); uint16 maxLength, off_t *value,
uint16 *duplicate = NULL);
status_t Find(const uint8 *key, uint16 keyLength); status_t Find(const uint8 *key, uint16 keyLength);
status_t Rewind(); status_t Rewind();
status_t GetNextEntry(void *key, uint16 *keyLength, uint16 maxLength, status_t GetNextEntry(void *key, uint16 *keyLength, uint16 maxLength,
off_t *value, uint16 *duplicate = NULL); off_t *value, uint16 *duplicate = NULL);
status_t GetPreviousEntry(void *key, uint16 *keyLength, uint16 maxLength, status_t GetPreviousEntry(void *key, uint16 *keyLength,
off_t *value, uint16 *duplicate = NULL); uint16 maxLength, off_t *value,
uint16 *duplicate = NULL);
void SkipDuplicates(); void SkipDuplicates();
#ifdef DEBUG #ifdef DEBUG
@@ -303,12 +314,16 @@ class TreeIterator {
friend class Chain<TreeIterator>; friend class Chain<TreeIterator>;
friend class BPlusTree; friend class BPlusTree;
void Update(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 splitAt, int8 change); void Update(off_t offset, off_t nextOffset, uint16 keyIndex,
uint16 splitAt, int8 change);
void Stop(); void Stop();
TreeIterator *fNext; TreeIterator *fNext;
}; };
// BPlusTree's inline functions (most of them may not be needed)
// #pragma mark - BPlusTree's inline functions
// (most of them may not be needed)
inline status_t inline status_t
BPlusTree::Remove(Transaction &transaction, const char *key, off_t value) BPlusTree::Remove(Transaction &transaction, const char *key, off_t value)
@@ -375,8 +390,8 @@ BPlusTree::Insert(Transaction &transaction, double key, off_t value)
} }
/************************ TreeIterator inline functions ************************/ // #pragma mark - TreeIterator inline functions
// #pragma mark -
inline status_t inline status_t
TreeIterator::Rewind() TreeIterator::Rewind()
@@ -398,8 +413,8 @@ TreeIterator::GetPreviousEntry(void *key, uint16 *keyLength, uint16 maxLength,
return Traverse(BPLUSTREE_BACKWARD, key, keyLength, maxLength, value, duplicate); return Traverse(BPLUSTREE_BACKWARD, key, keyLength, maxLength, value, duplicate);
} }
/************************ bplustree_header inline functions ************************/
// #pragma mark - // #pragma mark - bplustree_header inline functions
inline bool inline bool
@@ -420,14 +435,14 @@ bplustree_header::IsValidLink(off_t link) const
} }
/************************ bplustree_node inline functions ************************/ // #pragma mark - bplustree_node inline functions
// #pragma mark -
inline uint16 * inline uint16 *
bplustree_node::KeyLengths() const bplustree_node::KeyLengths() const
{ {
return (uint16 *)(((char *)this) + round_up(sizeof(bplustree_node) + AllKeyLength())); return (uint16 *)(((char *)this) + round_up(sizeof(bplustree_node)
+ AllKeyLength()));
} }
@@ -448,7 +463,8 @@ bplustree_node::Keys() const
inline int32 inline int32
bplustree_node::Used() const bplustree_node::Used() const
{ {
return round_up(sizeof(bplustree_node) + AllKeyLength()) + NumKeys() * (sizeof(uint16) + sizeof(off_t)); return round_up(sizeof(bplustree_node) + AllKeyLength()) + NumKeys()
* (sizeof(uint16) + sizeof(off_t));
} }
@@ -462,7 +478,8 @@ bplustree_node::IsLeaf() const
inline duplicate_array * inline duplicate_array *
bplustree_node::FragmentAt(int8 index) const bplustree_node::FragmentAt(int8 index) const
{ {
return (duplicate_array *)((off_t *)this + index * (NUM_FRAGMENT_VALUES + 1)); return (duplicate_array *)((off_t *)this
+ index * (NUM_FRAGMENT_VALUES + 1));
} }
@@ -483,14 +500,16 @@ bplustree_node::LinkType(off_t link)
inline off_t inline off_t
bplustree_node::MakeLink(uint8 type, off_t link, uint32 fragmentIndex) bplustree_node::MakeLink(uint8 type, off_t link, uint32 fragmentIndex)
{ {
return ((off_t)type << 62) | (link & 0x3ffffffffffffc00LL) | (fragmentIndex & 0x3ff); return ((off_t)type << 62) | (link & 0x3ffffffffffffc00LL)
| (fragmentIndex & 0x3ff);
} }
inline bool inline bool
bplustree_node::IsDuplicate(off_t link) bplustree_node::IsDuplicate(off_t link)
{ {
return (LinkType(link) & (BPLUSTREE_DUPLICATE_NODE | BPLUSTREE_DUPLICATE_FRAGMENT)) > 0; return (LinkType(link)
& (BPLUSTREE_DUPLICATE_NODE | BPLUSTREE_DUPLICATE_FRAGMENT)) > 0;
} }
@@ -514,4 +533,4 @@ bplustree_node::MaxFragments(uint32 nodeSize)
return nodeSize / ((NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); return nodeSize / ((NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
} }
#endif /* B_PLUS_TREE_H */ #endif // B_PLUS_TREE_H
@@ -15,10 +15,6 @@
#include "system_dependencies.h" #include "system_dependencies.h"
#ifdef USER
# define spawn_kernel_thread spawn_thread
#endif
// Things the BlockAllocator should do: // Things the BlockAllocator should do:
+6 -14
View File
@@ -1,6 +1,5 @@
/* Debug - debug stuff /*
* * Copyright 2001-2007, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2001-2006, Axel Dörfler, axeld@pinc-software.de.
* Some code is based on work previously done by Marcus Overhagen. * Some code is based on work previously done by Marcus Overhagen.
* *
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
@@ -242,13 +241,11 @@ dump_bplustree_node(const bplustree_node *node, const bplustree_header *header,
// #pragma mark - // #pragma mark -
#ifndef USER
static int static int
dbg_inode(int argc, char **argv) debug_inode(int argc, char **argv)
{ {
if (argc < 2) { if (argc < 2) {
kprintf("usage: bfsinode ptr-to-inode\n"); kprintf("usage: bfsinode <ptr-to-inode>\n");
return 0; return 0;
} }
@@ -258,22 +255,17 @@ dbg_inode(int argc, char **argv)
return B_OK; return B_OK;
} }
#endif
void void
remove_debugger_commands() remove_debugger_commands()
{ {
#ifndef USER remove_debugger_command("bfsinode", debug_inode);
remove_debugger_command("bfsinode", dbg_inode);
#endif
} }
void void
add_debugger_commands() add_debugger_commands()
{ {
#ifndef USER add_debugger_command("bfsinode", debug_inode, "dump an Inode object");
add_debugger_command("bfsinode", dbg_inode, "dump an Inode object");
#endif
} }
@@ -16,12 +16,10 @@
// Configure here if and when real benaphores should be used // Configure here if and when real benaphores should be used
#define USE_BENAPHORE #define USE_BENAPHORE
// if defined, benaphores are used for the Semaphore/RecursiveLock classes // if defined, benaphores are used for the Semaphore/RecursiveLock classes
#ifdef USER
//# define FAST_LOCK //# define FAST_LOCK
// the ReadWriteLock class uses a second Semaphore to // the ReadWriteLock class uses a second Semaphore to
// speed up locking - only makes sense if USE_BENAPHORE // speed up locking - only makes sense if USE_BENAPHORE
// is defined, too. // is defined, too.
#endif
#ifdef FAST_LOCK #ifdef FAST_LOCK
# error implement recursive write locking first # error implement recursive write locking first
#endif #endif
@@ -37,9 +35,6 @@ class Semaphore {
fSemaphore(create_sem(1, name)) fSemaphore(create_sem(1, name))
#endif #endif
{ {
#ifndef USER
set_sem_owner(fSemaphore, B_SYSTEM_TEAM);
#endif
} }
~Semaphore() ~Semaphore()
@@ -126,9 +121,6 @@ class RecursiveLock {
#endif #endif
fOwner(-1) fOwner(-1)
{ {
#ifndef USER
set_sem_owner(fSemaphore, B_SYSTEM_TEAM);
#endif
} }
status_t LockWithTimeout(bigtime_t timeout) status_t LockWithTimeout(bigtime_t timeout)
@@ -276,9 +268,6 @@ class ReadWriteLock {
{ {
fSemaphore = create_sem(0, name); fSemaphore = create_sem(0, name);
fCount = MAX_READERS; fCount = MAX_READERS;
#ifndef USER
set_sem_owner(fSemaphore, B_SYSTEM_TEAM);
#endif
return fSemaphore; return fSemaphore;
} }
@@ -360,9 +349,6 @@ class ReadWriteLock {
status_t Initialize(const char *name = "bfs r/w lock") status_t Initialize(const char *name = "bfs r/w lock")
{ {
fSemaphore = create_sem(MAX_READERS, name); fSemaphore = create_sem(MAX_READERS, name);
#ifndef USER
set_sem_owner(fSemaphore, B_SYSTEM_TEAM);
#endif
return fSemaphore; return fSemaphore;
} }
@@ -273,9 +273,7 @@ Volume::Panic()
{ {
FATAL(("we have to panic... switch to read-only mode!\n")); FATAL(("we have to panic... switch to read-only mode!\n"));
fFlags |= VOLUME_READ_ONLY; fFlags |= VOLUME_READ_ONLY;
#ifdef USER #ifdef DEBUG
debugger("BFS panics!");
#elif defined(DEBUG)
kernel_debugger("BFS panics!"); kernel_debugger("BFS panics!");
#endif #endif
} }