[BACK]Return to BTree.h CVS log [TXT][DIR] Up to [Development] / fam / include

Annotation of fam/include/BTree.h, Revision 1.1.1.1

1.1       trev        1: //  Copyright (C) 1999 Silicon Graphics, Inc.  All Rights Reserved.
                      2: //
                      3: //  This program is free software; you can redistribute it and/or modify it
                      4: //  under the terms of version 2.1 of the GNU Lesser General Public License
                      5: //  as published by the Free Software Foundation.
                      6: //
                      7: //  This program is distributed in the hope that it would be useful, but
                      8: //  WITHOUT ANY WARRANTY; without even the implied warranty of
                      9: //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Further, any
                     10: //  license provided herein, whether implied or otherwise, is limited to
                     11: //  this program in accordance with the express provisions of the GNU Lesser
                     12: //  General Public License.  Patent licenses, if any, provided herein do not
                     13: //  apply to combinations of this program with other product or programs, or
                     14: //  any other product whatsoever. This program is distributed without any
                     15: //  warranty that the program is delivered free of the rightful claim of any
                     16: //  third person by way of infringement or the like.  See the GNU Lesser
                     17: //  General Public License for more details.
                     18: //
                     19: //  You should have received a copy of the GNU General Public License along
                     20: //  with this program; if not, write the Free Software Foundation, Inc., 59
                     21: //  Temple Place - Suite 330, Boston MA 02111-1307, USA.
                     22:
                     23: #ifndef BTree_included
                     24: #define BTree_included
                     25:
                     26: #include "Boolean.h"
                     27:
                     28: //  This is an in-core B-Tree implementation.
                     29: //
                     30: //  The public interface is fairly sparse: find, insert and remove
                     31: //  are the provided functions.  insert() and remove() return true
                     32: //  on success, false on failure.  find() returns 0 on failure.
                     33: //
                     34: //  size() returns the number of key/value pairs in the tree.
                     35: //
                     36: //  sizeofnode() returns the size of a BTree node, in bytes.
                     37: //
                     38: //  BTree is instantiated by
                     39: //
                     40: //      libfam/Client.h:
                     41: //          BTree<int, void *> *userData;
                     42: //          BTree<int, bool>   *endExist;
                     43: //      fam/Listener.c++:
                     44: //          BTree<int, NegotiatingClient *> negotiating_clients;
                     45: //      fam/RequestMap.h:
                     46: //          typedef BTree<Request, ClientInterest *> RequestMap;
                     47: //      fam/Set.h:
                     48: //          template <class T> class Set : public BTree<T, bool>
                     49: //          typedef BTree<T, bool> inherited;
                     50: //
                     51: //  Set (derived from BTree) is instantiated by
                     52: //
                     53: //      fam/TCP_Client.h:
                     54: //          Set<Interest *> to_be_scanned;
                     55: //      fam/Pollster.h:
                     56: //          static Set<Interest *> polled_interests;
                     57: //          static Set<ServerHost *> polled_hosts;
                     58: //      fam/FileSystem.h:
                     59: //          typedef Set<ClientInterest *> Interests;
                     60: //
                     61: template <class Key, class Value> class BTree {
                     62:
                     63: public:
                     64:
                     65:     BTree();
                     66:     virtual ~BTree();
                     67:
                     68:     Value find(const Key& k) const;
                     69:     bool insert(const Key& k, const Value& v);
                     70:     bool remove(const Key& k);
                     71:
                     72:     Key first() const;
                     73:     Key next(const Key& k) const;
                     74:
                     75:     unsigned size() const		{ return npairs; }
                     76:
                     77:     static unsigned sizeofnode()	{ return sizeof (Node); }
                     78:
                     79: private:
                     80:
                     81:     enum { fanout = 32 };
                     82:     enum Status { OK, NO, OVER, UNDER };
                     83:
                     84:     struct Node;
                     85:     struct Closure {
                     86:
                     87: 	Closure(Status s)		    : status(s), key(0),
                     88:                                               value(0), link(0) { }
                     89: 	Closure(Key k, Value v, Node *l)    : status(OVER), key(k), value(v),
                     90: 					      link(l) { }
                     91: 	Closure(Status s, const Closure& i) : status(s), key(i.key),
                     92: 					      value(i.value), link(i.link) { }
                     93: 	Closure(Status s, const Key& k)	    : status(s), key(k),
                     94:                                               value(0), link(0) { }
                     95: 	operator Status ()		    { return status; }
                     96:
                     97: 	Status status;
                     98: 	Key    key;
                     99: 	Value  value;
                    100: 	Node  *link;
                    101:
                    102:     };
                    103:
                    104:     struct Node {
                    105:
                    106: 	Node(Node *, const Closure&);
                    107: 	Node(Node *, unsigned index);
                    108: 	~Node();
                    109:
                    110: 	unsigned find(const Key&) const;
                    111: 	Closure next(const Key&) const;
                    112: 	bool insert(unsigned, const Closure&);
                    113: 	Closure remove(unsigned);
                    114: 	void join(const Closure&, Node *);
                    115:
                    116: 	unsigned n;
                    117: 	Key   key  [fanout];
                    118: 	Node *link [fanout + 1];
                    119: 	Value value[fanout];
                    120:
                    121:     private:
                    122:
                    123: 	Node(const Node&);		// Do not copy
                    124: 	Node& operator = (const Node&);	// or assign.
                    125:
                    126:     };
                    127:
                    128:     // Instance Variables
                    129:
                    130:     Node *root;
                    131:     unsigned npairs;
                    132:
                    133:     Closure insert(Node *, const Key&, const Value&);
                    134:     Status remove(Node *, const Key&);
                    135:     Status underflow(Node *, unsigned);
                    136:     Closure remove_rightmost(Node *);
                    137:
                    138:     BTree(const BTree&);		// Do not copy
                    139:     BTree& operator = (const BTree&);	//  or assign.
                    140:
                    141: };
                    142:
                    143: //  Construct a Node from a Node and a Closure.  New node
                    144: //  has a single key-value pair, its left child
                    145: //  is the other node, and its right child is the link
                    146: //  field of the closure.
                    147:
                    148: template <class K, class V>
                    149: BTree<K, V>::Node::Node(Node *p, const Closure& closure)
                    150: {
                    151:     n = 1;
                    152:     link[0] = p;
                    153:     key[0] = closure.key;
                    154:     value[0] = closure.value;
                    155:     link[1] = closure.link;
                    156: }
                    157:
                    158: //  Construct a Node from a Node and an index.  Steals
                    159: //  the elements index..n of other Node for itself.
                    160: //  When this constructor is done, both this->link[0] and
                    161: //  that->link[that->n] point to the same place.  The caller
                    162: //  must resolve that.
                    163:
                    164: template <class K, class V>
                    165: BTree<K, V>::Node::Node(Node *that, unsigned index)
                    166: {
                    167:     n = that->n - index;
                    168:     for (int i = 0; i < n; i++)
                    169:     {   key[i] = that->key[index + i];
                    170: 	value[i] = that->value[index + i];
                    171: 	link[i] = that->link[index + i];
                    172:     }
                    173:     link[n] = that->link[index + n];
                    174:     that->n = index;
                    175: }
                    176:
                    177: //  Node destructor.  Recursively deletes subnodes.
                    178:
                    179: template <class K, class V>
                    180: BTree<K, V>::Node::~Node()
                    181: {
                    182:     for (int i = 0; i <= n; i++)
                    183: 	delete link[i];
                    184: }
                    185:
                    186: //  Node::find() uses binary search to find the nearest key.
                    187: //  return index of key that matches or of next key to left.
                    188: //
                    189: //  E.g., if find() returns 3 then either key[3] matches or
                    190: //  key passed in is between key[3] and key[4].
                    191:
                    192: template <class Key, class Value>
                    193: unsigned
                    194: BTree<Key, Value>::Node::find(const Key& k) const
                    195: {
                    196:     unsigned l = 0, r = n;
                    197:     while (l < r)
                    198:     {   int m = (l + r) / 2;
                    199: 	if (k == key[m])
                    200: 	    return m;
                    201: 	else if (k < key[m])
                    202: 	    r = m;
                    203: 	else // (k > key[m])
                    204: 	    l = m + 1;
                    205:     }
                    206:     assert(l == n || k < key[l]);
                    207:     return l;
                    208: }
                    209:
                    210: //  Node::insert() inserts key/value into j'th position in node.
                    211: //  Inserts closure's link to the right.  Returns true if successful,
                    212: //  false if node is already full.
                    213:
                    214: template <class K, class V>
                    215: bool
                    216: BTree<K, V>::Node::insert(unsigned j, const Closure& closure)
                    217: {
                    218:     if (n < fanout)
                    219:     {   for (int i = n; i > j; --i)
                    220: 	{   key[i] = key[i - 1];
                    221: 	    value[i] = value[i - 1];
                    222: 	    link[i + 1] = link[i];
                    223: 	}
                    224: 	key[j] = closure.key; value[j] = closure.value;
                    225: 	link[j + 1] = closure.link;
                    226: 	n++;
                    227: 	assert(j == 0     || key[j - 1] < key[j]);
                    228: 	assert(j == n - 1 || key[j] < key[j + 1]);
                    229: 	return true;
                    230:     }
                    231:     else
                    232: 	return false;
                    233: }
                    234:
                    235: //  Node::remove extracts the j'th key/value and the link
                    236: //  to the right and returns them.
                    237:
                    238: template <class Key, class Value>
                    239: BTree<Key, Value>::Closure
                    240: BTree<Key, Value>::Node::remove(unsigned j)
                    241: {
                    242:     Key k = key[j];
                    243:     Value v = value[j];
                    244:     Node *l = link[j + 1];
                    245:     for (unsigned i = j + 1; i < n; i++)
                    246:     {   key[i - 1] = key[i];
                    247: 	value[i - 1] = value[i];
                    248: 	link[i] = link[i + 1];
                    249:     }
                    250:     --n;
                    251:     return Closure(k, v, l);
                    252: }
                    253:
                    254: // Node::join() copies key/value from closure and moves all
                    255: // key/value/links from other Node into this node.
                    256: // Other Node is modified to contain no keys, no values, no links.
                    257:
                    258: template <class K, class V>
                    259: void
                    260: BTree<K, V>::Node::join(const Closure& it, Node *that)
                    261: {
                    262:     assert(that);
                    263:     assert(n + that->n <= fanout - 1);
                    264:     key[n] = it.key;
                    265:     value[n] = it.value;
                    266:     for (int i = 0, j = n + 1; i < that->n; i++, j++)
                    267:     {   key[j] = that->key[i];
                    268: 	value[j] = that->value[i];
                    269: 	link[j] = that->link[i];
                    270:     }
                    271:     n += that->n + 1;
                    272:     link[n] = that->link[that->n];
                    273:     that->n = 0;
                    274:     that->link[0] = NULL;
                    275: }
                    276:
                    277: ///////////////////////////////////////////////////////////////////////////////
                    278:
                    279: //  BTB constructor -- check that fanout is even.
                    280:
                    281: template <class K, class V>
                    282: BTree<K, V>::BTree()
                    283:     : root(NULL), npairs(0)
                    284: {
                    285:     assert(!(fanout % 2));
                    286: }
                    287:
                    288: //  BTB destructor -- delete all Nodes.
                    289:
                    290: template <class K, class V>
                    291: BTree<K, V>::~BTree()
                    292: {
                    293:     delete root;
                    294: }
                    295:
                    296: //  BTB::find() -- search BTB for Key, return matching value.
                    297:
                    298: template <class Key, class Value>
                    299: Value
                    300: BTree<Key, Value>::find(const Key& key) const
                    301: {
                    302:     for (Node *p = root; p; )
                    303:     {   int i = p->find(key);
                    304: 	if (i < p->n && key == p->key[i])
                    305: 	    return p->value[i];
                    306: 	else
                    307: 	    p = p->link[i];
                    308:     }
                    309:     return Value(0);
                    310: }
                    311:
                    312: template <class Key, class Value>
                    313: Key
                    314: BTree<Key, Value>::first() const
                    315: {
                    316:     if (!root)
                    317: 	return 0;
                    318:     assert(root->n);
                    319:
                    320:     Node *p, *q;
                    321:     for (p = root; q = p->link[0]; p = q)
                    322: 	continue;
                    323:     return p->key[0];
                    324: }
                    325:
                    326: template <class Key, class Value>
                    327: Key
                    328: BTree<Key, Value>::next(const Key& pred) const
                    329: {
                    330:     if (!root)
                    331: 	return 0;
                    332:
                    333:     assert(root->n);
                    334:
                    335:     Closure it = root->next(pred);
                    336:     switch (Status(it))
                    337:     {
                    338:     case OK:
                    339: 	return it.key;
                    340:
                    341:     case OVER:
                    342: 	return 0;			// All done.
                    343:
                    344:     default:
                    345: 	assert(0);
                    346: 	return 0;
                    347:     }
                    348: }
                    349:
                    350: template <class Key, class Value>
                    351: BTree<Key, Value>::Closure
                    352: BTree<Key, Value>::Node::next(const Key& pred) const
                    353: {
                    354:     if (!this)
                    355: 	return OVER;
                    356:
                    357:     unsigned i = find(pred);
                    358:     assert(i <= n);
                    359:     if (i < n && key[i] == pred)
                    360: 	i++;
                    361:     Closure it = link[i]->next(pred);
                    362:     if (Status(it) != OVER)
                    363: 	return it;
                    364:     if (i == n)
                    365: 	return OVER;
                    366:     else
                    367: 	return Closure(OK, key[i]);
                    368: }
                    369:
                    370: //  BTB::insert() -- insert a new key/value pair
                    371: //  into the tree.  Fails and returns false if key is already
                    372: //  in tree.
                    373: //
                    374: //  This code is the only place that makes the tree taller.
                    375:
                    376:
                    377: template <class Key, class Value>
                    378: bool
                    379: BTree<Key, Value>::insert(const Key& key, const Value& value)
                    380: {
                    381:     Closure it = insert(root, key, value);
                    382:     switch (Status(it))
                    383:     {
                    384:     case OK:
                    385: 	npairs++;
                    386: 	return true;
                    387:
                    388:     case NO:
                    389: 	return false;
                    390:
                    391:     case OVER:
                    392: 	root = new Node(root, it);
                    393: 	npairs++;
                    394: 	return true;
                    395:
                    396:     default:
                    397: 	assert(0);
                    398: 	return false;
                    399:     }
                    400: }
                    401:
                    402: //  BTB::insert(Node *, ...) -- helper function for
                    403: //  BTB::insert(Key&, ...)  Recurses to the appropriate leaf, splits
                    404: //  nodes as necessary on the way back.
                    405:
                    406: template <class Key, class Value>
                    407: BTree<Key, Value>::Closure
                    408: BTree<Key, Value>::insert(Node *p, const Key& key, const Value& value)
                    409: {
                    410:     if (!p) return Closure(key, value, NULL);
                    411:     //  If you're running Purify on a client linking with libfam, and it says
                    412:     //  that line is causing a 3-byte UMR for BTree<int, bool>::insert() in
                    413:     //  FAMNextEvent() ("Reading 8 bytes from 0x... on the stack (3 bytes at
                    414:     //  0x... uninit)"), and sizeof(bool) == 1, it's actually OK.  Those 3
                    415:     //  bytes are the padding between the bool Value and the Node *link in
                    416:     //  BTree<int, bool>::Closure.
                    417:
                    418:     int i = p->find(key);
                    419:     if (i < p->n && key == p->key[i])
                    420: 	return NO;			// key already exists.
                    421:
                    422:     Closure it = insert(p->link[i], key, value);
                    423:
                    424:     if (Status(it) == OVER)
                    425:     {   if (p->insert(i, it))
                    426: 	    return Closure(OK);
                    427: 	else
                    428: 	{   if (i > fanout / 2)
                    429: 	    {   Node *np = new Node(p, fanout / 2 + 1);
                    430: 		np->insert(i - fanout / 2 - 1, it);
                    431: 		assert(p->n > fanout / 2);
                    432: 		it = p->remove(fanout / 2);
                    433: 		return Closure(it.key, it.value, np);
                    434: 	    }
                    435: 	    else if (i < fanout / 2)
                    436: 	    {
                    437: 		Node *np = new Node(p, fanout / 2);
                    438: 		p->insert(i, it);
                    439: 		assert(p->n > fanout / 2);
                    440: 		it = p->remove(fanout / 2);
                    441: 		return Closure(it.key, it.value, np);
                    442: 	    }
                    443: 	    else // (i == fanout / 2)
                    444: 	    {
                    445: 		Node *np = new Node(p, fanout / 2);
                    446: 		np->link[0] = it.link;
                    447: 		return Closure(it.key, it.value, np);
                    448: 	    }
                    449: 	}
                    450:     }
                    451:
                    452:     return it;
                    453: }
                    454:
                    455: //  BTB::remove() -- remove a key/value from the tree.
                    456: //  This function is the only one that makes the tree shorter.
                    457:
                    458: template <class Key, class Value>
                    459: bool
                    460: BTree<Key, Value>::remove(const Key& key)
                    461: {
                    462:     Status s = remove(root, key);
                    463:     switch (s)
                    464:     {
                    465:     case OK:
                    466: 	assert(npairs);
                    467: 	--npairs;
                    468: 	assert(!root || root->n);
                    469: 	return true;
                    470:
                    471:     case NO:
                    472: 	assert(!root || root->n);
                    473: 	return false;
                    474:
                    475:     case UNDER:
                    476: 	if (root->n == 0)
                    477: 	{   Node *nr = root->link[0];
                    478: 	    root->link[0] = NULL;	// don't delete subtree
                    479: 	    delete root;
                    480: 	    root = nr;
                    481: 	}
                    482: 	assert(npairs);
                    483: 	--npairs;
                    484: 	assert(!root || root->n);
                    485: 	return true;
                    486:
                    487:     default:
                    488: 	assert(0);
                    489: 	return false;
                    490:     }
                    491: }
                    492:
                    493: //  BTB::underflow -- helper function to BTB::remove() When a node
                    494: //  has too few elements (less than fanout / 2), this function is
                    495: //  invoked.  It tries to join i'th child of node p with one of its
                    496: //  adjacent siblings, then tries to move entries from an adjacent
                    497: //  sibling to child node.
                    498: //
                    499: //  Returns UNDER if node p is too small afterward, OK otherwise.
                    500:
                    501: template <class Key, class Value>
                    502: BTree<Key, Value>::Status
                    503: BTree<Key, Value>::underflow(Node *p, unsigned i)
                    504: {
                    505:     assert(p);
                    506:     assert(i <= p->n);
                    507:     Node *cp = p->link[i];
                    508:     assert(cp);
                    509:
                    510:     Node *rp = i < p->n ? p->link[i + 1] : NULL;
                    511:     Node *lp = i > 0    ? p->link[i - 1] : NULL;
                    512:     assert(!rp || rp->n >= fanout / 2);
                    513:     assert(!lp || lp->n >= fanout / 2);
                    514:
                    515:     if (rp && rp->n == fanout / 2)
                    516:     {
                    517: 	// join cp w/ rp;
                    518: 	cp->join(p->remove(i), rp);
                    519: 	delete rp;
                    520:     }
                    521:     else if (lp && lp->n == fanout / 2)
                    522:     {
                    523: 	// join lp w/ cp;
                    524: 	lp->join(p->remove(i - 1), cp);
                    525: 	delete cp;
                    526:     }
                    527:     else if (lp)
                    528:     {
                    529: 	// shuffle from lp to cp;
                    530: 	Closure li = lp->remove(lp->n - 1);
                    531: 	cp->insert(0, Closure(p->key[i - 1], p->value[i - 1], cp->link[0]));
                    532: 	cp->link[0] = li.link;
                    533: 	p->key[i - 1] = li.key;
                    534: 	p->value[i - 1] = li.value;
                    535: 	return OK;
                    536:     }
                    537:     else if (rp)
                    538:     {
                    539: 	// shuffle from rp to cp;
                    540: 	Closure ri = rp->remove(0);
                    541: 	cp->insert(cp->n, Closure(p->key[i], p->value[i], rp->link[0]));
                    542: 	p->key[i] = ri.key;
                    543: 	p->value[i] = ri.value;
                    544: 	rp->link[0] = ri.link;
                    545: 	return OK;
                    546:     }
                    547:
                    548:     return p->n >= fanout / 2 ? OK : UNDER;
                    549: }
                    550:
                    551: //  BTB::remove_rightmost() -- helper to BTB::remove().
                    552: //
                    553: //  Removes rightmost leaf key/value from subtree and returns them.
                    554: //  If Nodes become too small in the process, invokes Node::underflow()
                    555: //  to fix them up.  Return status is either OK or UNDER, indicating
                    556: //  root of subtree is too small.
                    557:
                    558:
                    559: template <class Key, class Value>
                    560: BTree<Key, Value>::Closure
                    561: BTree<Key, Value>::remove_rightmost(Node *p)
                    562: {
                    563:     int i = p->n;
                    564:     Node *cp = p->link[i];
                    565:     if (cp)
                    566:     {   Closure it = remove_rightmost(cp);
                    567: 	if (Status(it) == UNDER)
                    568: 	    return Closure(underflow(p, i), it);
                    569: 	else
                    570: 	    return it;
                    571:     }
                    572:     else
                    573:     {   Closure it = p->remove(p->n - 1);
                    574: 	if (p->n >= fanout / 2)
                    575: 	    return Closure(OK, it);
                    576: 	else
                    577: 	    return Closure(UNDER, it);
                    578:     }
                    579: }
                    580:
                    581: //  BTB::remove(Node *, ...) -- helper to BTB::remove(const Key&).
                    582: //
                    583: //  Recurses into tree to find key/value to delete.  When it finds
                    584: //  them, it pulls the rightmost leaf key/value off the branch to
                    585: //  the left and replaces the removed k/v with them.  Watches for
                    586: //  Node underflows from BTB::remove_rightmost() and propagates them
                    587: //  back up.
                    588:
                    589: template <class Key, class Value>
                    590: BTree<Key, Value>::Status
                    591: BTree<Key, Value>::remove(Node *p, const Key& key)
                    592: {
                    593:     if (!p)
                    594: 	return NO;			// key not found
                    595:     int i = p->find(key);
                    596:     if (i < p->n && key == p->key[i])
                    597:     {
                    598: 	// Delete this one.
                    599:
                    600: 	Closure it = p->remove(i);
                    601: 	if (p->link[i])
                    602: 	{   Closure rm = remove_rightmost(p->link[i]);
                    603: 	    assert(!rm.link);
                    604: 	    p->insert(i, Closure(rm.key, rm.value, it.link));
                    605: 	    if (Status(rm) == UNDER)
                    606: 		return underflow(p, i);
                    607: 	}
                    608: 	return p->n >= fanout / 2 ? OK : UNDER;
                    609:     }
                    610:     else
                    611:     {   Node *cp = p->link[i];
                    612: 	Status s = remove(cp, key);
                    613: 	if (s == UNDER)
                    614: 	    return underflow(p, i);
                    615: 	else
                    616: 	    return s;
                    617:     }
                    618: }
                    619:
                    620:
                    621:
                    622: //#ifndef NDEBUG
                    623: //
                    624: //template <class K, class V>
                    625: //BTree<K, V>::BTree()
                    626: //{
                    627: //    //assert(sizeof K <= sizeof BTB::Key);
                    628: //    //assert(sizeof V <= sizeof BTB::Value);
                    629: //}
                    630: //
                    631: //#endif /* !NDEBUG */
                    632:
                    633:
                    634: #endif /* !BTree_included */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>