8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 18:43:03 +01:00

Totally misc.

This commit is contained in:
robocop 2008-03-08 11:32:11 +00:00
parent 21a1eed8a1
commit 812058f940

View File

@ -61,7 +61,8 @@ const int NODE_PAGE_SIZE = 3000;
// should be more than enough. No checks are performed in code against overflow of this value // should be more than enough. No checks are performed in code against overflow of this value
const int MAX_TREE_LEVEL = 30; const int MAX_TREE_LEVEL = 30;
class MallocAllocator { class MallocAllocator
{
public: public:
void *allocate(size_t size) { void *allocate(size_t size) {
return malloc(size); return malloc(size);
@ -103,9 +104,10 @@ template <typename Value, typename Key = Value, typename Allocator = MallocAlloc
typename Cmp = DefaultComparator<Key>, typename Cmp = DefaultComparator<Key>,
int LeafCount = LEAF_PAGE_SIZE / sizeof(Value), int LeafCount = LEAF_PAGE_SIZE / sizeof(Value),
int NodeCount = NODE_PAGE_SIZE / sizeof(void*)> int NodeCount = NODE_PAGE_SIZE / sizeof(void*)>
class BePlusTree { class BePlusTree
{
public: public:
BePlusTree(Allocator *_pool) explicit BePlusTree(Allocator *_pool)
: pool(_pool), level(0), root(NULL), defaultAccessor(this) : pool(_pool), level(0), root(NULL), defaultAccessor(this)
{ } { }
@ -119,13 +121,15 @@ public:
append(from); append(from);
} }
BePlusTree& operator =(BePlusTree& from) { BePlusTree& operator =(BePlusTree& from)
{
clear(); clear();
append(from); append(from);
return *this; return *this;
} }
void clear() { void clear()
{
defaultAccessor.curr = NULL; defaultAccessor.curr = NULL;
// Do not deallocate root page if tree is shallow // Do not deallocate root page if tree is shallow
@ -168,12 +172,14 @@ public:
level = 0; level = 0;
} }
~BePlusTree() { ~BePlusTree()
{
clear(); clear();
pool->deallocate(root); pool->deallocate(root);
} }
bool isEmpty() const { bool isEmpty() const
{
return return
root == NULL || root == NULL ||
(level == 0 && ((ItemList*)root)->getCount() == 0); (level == 0 && ((ItemList*)root)->getCount() == 0);
@ -209,7 +215,8 @@ public:
Value& current() const { return defaultAccessor.current(); } Value& current() const { return defaultAccessor.current(); }
// Returns true if this tree appears to contain more elements than the other // Returns true if this tree appears to contain more elements than the other
bool seemsBiggerThan(const BePlusTree &other) const { bool seemsBiggerThan(const BePlusTree &other) const
{
if (level != other.level) if (level != other.level)
return level > other.level; return level > other.level;
@ -225,11 +232,13 @@ public:
} }
// Compute approximate number of leafs in the tree // Compute approximate number of leafs in the tree
size_t approxCount() const { size_t approxCount() const
{
if (!root) if (!root)
return 0; return 0;
if (level == 0) return ((ItemList*)root)->getCount(); if (level == 0)
return ((ItemList*)root)->getCount();
// Tree is large. Roughtly estimate number of leaf nodes using number of // Tree is large. Roughtly estimate number of leaf nodes using number of
// items in root list and depth of the tree. Theoretically possible fill // items in root list and depth of the tree. Theoretically possible fill
@ -245,7 +254,8 @@ public:
} }
// Compute approximate memory consumption for tree in bytes // Compute approximate memory consumption for tree in bytes
size_t approxSize() const { size_t approxSize() const
{
if (!root) if (!root)
return 0; return 0;
@ -263,7 +273,8 @@ public:
return ((NodeList*)root)->getCount() * bytes_per_node; return ((NodeList*)root)->getCount() * bytes_per_node;
} }
void append(BePlusTree& from) { void append(BePlusTree& from)
{
// This is slow approach especially when used for assignment. // This is slow approach especially when used for assignment.
// Optimize it when need arises. // Optimize it when need arises.
Accessor accessor(&from); Accessor accessor(&from);
@ -285,12 +296,15 @@ public:
#endif #endif
class NodeList; class NodeList;
class ItemList : public SortedVector<Value, LeafCount, Key, KeyOfValue, Cmp> { class ItemList : public SortedVector<Value, LeafCount, Key, KeyOfValue, Cmp>
{
public: public:
NodeList *parent; NodeList *parent;
ItemList *next, *prev; ItemList *next, *prev;
// Adds newly created item to doubly-linked list // Adds newly created item to doubly-linked list
ItemList(ItemList *items) : parent(NULL) { ItemList(ItemList *items)
: parent(NULL)
{
if ((next = items->next)) if ((next = items->next))
next->prev = this; next->prev = this;
prev = items; prev = items;
@ -306,10 +320,13 @@ public:
#endif #endif
}; };
class NodeList : public SortedVector<void*, NodeCount, Key, NodeList, Cmp> { class NodeList : public SortedVector<void*, NodeCount, Key, NodeList, Cmp>
{
public: public:
// Adds newly created item to the doubly-linked list // Adds newly created item to the doubly-linked list
NodeList(NodeList *items) : parent(NULL) { NodeList(NodeList *items)
: parent(NULL)
{
if ((next = items->next)) if ((next = items->next))
next->prev = this; next->prev = this;
prev = items; prev = items;
@ -330,7 +347,8 @@ public:
// add ItemList typedef for you compiler with whichever syntax it likes // add ItemList typedef for you compiler with whichever syntax it likes
return KeyOfValue::generate(item, *((ItemList *)item)->begin()); return KeyOfValue::generate(item, *((ItemList *)item)->begin());
} }
static void setNodeParentAndLevel(void *node, int level, NodeList *parent) { static void setNodeParentAndLevel(void *node, int level, NodeList *parent)
{
if (level) { if (level) {
((NodeList *)node)->parent = parent; ((NodeList *)node)->parent = parent;
((NodeList *)node)->level = level - 1; ((NodeList *)node)->level = level - 1;
@ -338,7 +356,8 @@ public:
else else
((ItemList *)node)->parent = parent; ((ItemList *)node)->parent = parent;
} }
static void setNodeParent(void *node, int level, NodeList *parent) { static void setNodeParent(void *node, int level, NodeList *parent)
{
if (level) if (level)
((NodeList *)node)->parent = parent; ((NodeList *)node)->parent = parent;
else else
@ -347,17 +366,20 @@ public:
}; };
public: public:
class Accessor { class Accessor
{
public: public:
Accessor(BePlusTree* _tree) : curr(NULL), curPos(0), tree(_tree) {} explicit Accessor(BePlusTree* _tree) : curr(NULL), curPos(0), tree(_tree) {}
bool add(const Value& item) { bool add(const Value& item)
{
return tree->add(item, this); return tree->add(item, this);
} }
// Remove item. Current position moves to next item after this call. // Remove item. Current position moves to next item after this call.
// If next item doesn't exist method returns false // If next item doesn't exist method returns false
bool fastRemove() { bool fastRemove()
{
// invalidate current position of defaultAccessor // invalidate current position of defaultAccessor
// if i'm not a defaultAccessor // if i'm not a defaultAccessor
if (this != &tree->defaultAccessor) if (this != &tree->defaultAccessor)
@ -425,17 +447,21 @@ public:
return true; return true;
} }
bool locate(const Key& key) { bool locate(const Key& key)
{
return locate(locEqual, key); return locate(locEqual, key);
} }
// Position accessor on item having LocType relationship with given key // Position accessor on item having LocType relationship with given key
// If method returns false position of accessor is not defined. // If method returns false position of accessor is not defined.
bool locate(LocType lt, const Key& key) { bool locate(LocType lt, const Key& key)
{
// Inlining is efficient here because LocType will be known in most cases // Inlining is efficient here because LocType will be known in most cases
// and compiler will be able to eliminate most of code // and compiler will be able to eliminate most of code
void *list = tree->root; void *list = tree->root;
if (!list) return false; // Uninitalized tree if (!list)
return false; // Uninitalized tree
for (int lev = tree->level; lev; lev--) { for (int lev = tree->level; lev; lev--) {
size_t pos; size_t pos;
if (!((NodeList *)list)->find(key, pos)) if (!((NodeList *)list)->find(key, pos))
@ -483,10 +509,12 @@ public:
} }
// If method returns false it means list is empty and // If method returns false it means list is empty and
// position of accessor is not defined. // position of accessor is not defined.
bool getFirst() { bool getFirst()
{
void *items = tree->root; void *items = tree->root;
if (!items) if (!items)
return false; // Uninitalized tree return false; // Uninitalized tree
for (int i = tree->level; i > 0; i--) for (int i = tree->level; i > 0; i--)
items = (*(NodeList *)items)[0]; items = (*(NodeList *)items)[0];
curr = (ItemList *)items; curr = (ItemList *)items;
@ -495,10 +523,12 @@ public:
} }
// If method returns false it means list is empty and // If method returns false it means list is empty and
// position of accessor is not defined. // position of accessor is not defined.
bool getLast() { bool getLast()
{
void *items = tree->root; void *items = tree->root;
if (!items) if (!items)
return false; // Uninitalized tree return false; // Uninitalized tree
for (int i = tree->level; i > 0; i--) for (int i = tree->level; i > 0; i--)
items = (*(NodeList *)items)[((NodeList *)items)->getCount() - 1]; items = (*(NodeList *)items)[((NodeList *)items)->getCount() - 1];
curr = (ItemList *)items; curr = (ItemList *)items;
@ -510,7 +540,8 @@ public:
} }
// Accessor position must be establised via successful call to getFirst(), // Accessor position must be establised via successful call to getFirst(),
// getLast() or locate() before you can call this method // getLast() or locate() before you can call this method
bool getNext() { bool getNext()
{
curPos++; curPos++;
if (curPos >= curr->getCount()) { if (curPos >= curr->getCount()) {
if (curr->next) { if (curr->next) {
@ -527,7 +558,8 @@ public:
} }
// Accessor position must be establised via successful call to getFirst(), // Accessor position must be establised via successful call to getFirst(),
// getLast() or locate() before you can call this method // getLast() or locate() before you can call this method
bool getPrev() { bool getPrev()
{
if (curPos == 0) { if (curPos == 0) {
if (curr->prev) { if (curr->prev) {
curr = curr->prev; curr = curr->prev;