Added more checks in the BPlusTree implementation if DEBUG is defined.
The correctness of max_number_of_levels is now checked in Find(). Added a class NodeChecker which checks the integrity of the specified node when the object is destructed (via new method bplustree_node::CheckIntegrity()); now used in Remove() and Insert(). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2169 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -22,6 +22,27 @@
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
class NodeChecker {
|
||||
public:
|
||||
NodeChecker(bplustree_node *node, int32 nodeSize)
|
||||
:
|
||||
fNode(node),
|
||||
fSize(nodeSize)
|
||||
{
|
||||
}
|
||||
|
||||
~NodeChecker()
|
||||
{
|
||||
fNode->CheckIntegrity(fSize);
|
||||
}
|
||||
|
||||
private:
|
||||
bplustree_node *fNode;
|
||||
int32 fSize;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Node Caching for the BPlusTree class
|
||||
//
|
||||
// With write support, there is the need for a function that allocates new
|
||||
@@ -1075,6 +1096,9 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
|
||||
|
||||
CachedNode cached(this);
|
||||
while (stack.Pop(&nodeAndKey) && (node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL) {
|
||||
#ifdef DEBUG
|
||||
NodeChecker checker(node, fNodeSize);
|
||||
#endif
|
||||
if (node->IsLeaf()) {
|
||||
// first round, check for duplicate entries
|
||||
status_t status = FindKey(node,key,keyLength,&nodeAndKey.keyIndex);
|
||||
@@ -1424,6 +1448,9 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
|
||||
CachedNode cached(this);
|
||||
while (stack.Pop(&nodeAndKey) && (node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NodeChecker checker(node, fNodeSize);
|
||||
#endif
|
||||
if (node->IsLeaf()) // first round, check for duplicate entries
|
||||
{
|
||||
status_t status = FindKey(node,key,keyLength,&nodeAndKey.keyIndex);
|
||||
@@ -1577,15 +1604,26 @@ BPlusTree::Find(const uint8 *key, uint16 keyLength, off_t *_value)
|
||||
CachedNode cached(this);
|
||||
bplustree_node *node;
|
||||
|
||||
#ifdef DEBUG
|
||||
int32 levels = 0;
|
||||
#endif
|
||||
|
||||
while ((node = cached.SetTo(nodeOffset)) != NULL) {
|
||||
uint16 keyIndex = 0;
|
||||
off_t nextOffset;
|
||||
status_t status = FindKey(node, key, keyLength, &keyIndex, &nextOffset);
|
||||
|
||||
#ifdef DEBUG
|
||||
levels++;
|
||||
#endif
|
||||
if (node->overflow_link == BPLUSTREE_NULL) {
|
||||
if (status == B_OK && _value != NULL)
|
||||
*_value = node->Values()[keyIndex];
|
||||
|
||||
#ifdef DEBUG
|
||||
if (levels != fHeader->max_number_of_levels)
|
||||
DEBUGGER(("levels don't match"));
|
||||
#endif
|
||||
return status;
|
||||
} else if (nextOffset == nodeOffset)
|
||||
RETURN_ERROR(B_ERROR);
|
||||
@@ -1991,6 +2029,24 @@ bplustree_node::FragmentsUsed(uint32 nodeSize)
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
bplustree_node::CheckIntegrity(uint32 nodeSize)
|
||||
{
|
||||
if (all_key_count > nodeSize || all_key_length > nodeSize)
|
||||
DEBUGGER(("invalid node: key/length count"));
|
||||
|
||||
for (int32 i = 0; i < all_key_count; i++) {
|
||||
uint16 length;
|
||||
uint8 *key = KeyAt(i, &length);
|
||||
if (key + length + sizeof(off_t) + sizeof(uint16) > (uint8 *)this + nodeSize
|
||||
|| length > BPLUSTREE_MAX_KEY_LENGTH)
|
||||
DEBUGGER(("invalid node: keys corrupted"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
||||
@@ -77,6 +77,10 @@ struct bplustree_node {
|
||||
static inline bool IsDuplicate(off_t link);
|
||||
static inline off_t FragmentOffset(off_t link);
|
||||
static inline uint32 FragmentIndex(off_t link);
|
||||
|
||||
#ifdef DEBUG
|
||||
void CheckIntegrity(uint32 nodeSize);
|
||||
#endif
|
||||
};
|
||||
|
||||
//#define BPLUSTREE_NODE 0
|
||||
|
||||
Reference in New Issue
Block a user