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:
Axel Dörfler
2002-12-06 04:41:51 +00:00
parent 528a411973
commit 89e64f44be
2 changed files with 60 additions and 0 deletions
@@ -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