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>
|
#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
|
// Node Caching for the BPlusTree class
|
||||||
//
|
//
|
||||||
// With write support, there is the need for a function that allocates new
|
// 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);
|
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
|
||||||
|
NodeChecker checker(node, fNodeSize);
|
||||||
|
#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);
|
||||||
@@ -1424,6 +1448,9 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
|
|||||||
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
|
||||||
|
NodeChecker checker(node, fNodeSize);
|
||||||
|
#endif
|
||||||
if (node->IsLeaf()) // first round, check for duplicate entries
|
if (node->IsLeaf()) // first round, check for duplicate entries
|
||||||
{
|
{
|
||||||
status_t status = FindKey(node,key,keyLength,&nodeAndKey.keyIndex);
|
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);
|
CachedNode cached(this);
|
||||||
bplustree_node *node;
|
bplustree_node *node;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
int32 levels = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
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
|
||||||
|
levels++;
|
||||||
|
#endif
|
||||||
if (node->overflow_link == BPLUSTREE_NULL) {
|
if (node->overflow_link == BPLUSTREE_NULL) {
|
||||||
if (status == B_OK && _value != NULL)
|
if (status == B_OK && _value != NULL)
|
||||||
*_value = node->Values()[keyIndex];
|
*_value = node->Values()[keyIndex];
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (levels != fHeader->max_number_of_levels)
|
||||||
|
DEBUGGER(("levels don't match"));
|
||||||
|
#endif
|
||||||
return status;
|
return status;
|
||||||
} else if (nextOffset == nodeOffset)
|
} else if (nextOffset == nodeOffset)
|
||||||
RETURN_ERROR(B_ERROR);
|
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 -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ struct bplustree_node {
|
|||||||
static inline bool IsDuplicate(off_t link);
|
static inline bool IsDuplicate(off_t link);
|
||||||
static inline off_t FragmentOffset(off_t link);
|
static inline off_t FragmentOffset(off_t link);
|
||||||
static inline uint32 FragmentIndex(off_t link);
|
static inline uint32 FragmentIndex(off_t link);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void CheckIntegrity(uint32 nodeSize);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
//#define BPLUSTREE_NODE 0
|
//#define BPLUSTREE_NODE 0
|
||||||
|
|||||||
Reference in New Issue
Block a user