home *** CD-ROM | disk | FTP | other *** search
- // ------------- tnode.c++
-
- // ===============================
- // B-tree Tnode class
- // ===============================
-
- #include "parody.h"
-
- TNode::TNode(Btree *bt, NodeNbr nd) :
- Node(&(bt->IndexFile()), nd)
- {
- btree = bt;
- currkey = NULL;
- fstream& nf = btree->IndexFile().Nfile();
- // ------- read the header
- long nad = NodeAddress() + Node::NodeHeaderSize();
- nf.seekg(nad);
- nf.read((char *) &header, sizeof(TNodeHeader));
- if (nf.eof() || nf.fail()) {
- nf.clear();
- // ----- appending a new node
- nf.seekp(nad);
- nf.write((char *) &header, sizeof(TNodeHeader));
- }
- else {
- // ---- reading an existing node, read the keys
- for (int i = 0; i < header.keycount; i++) {
- // ---- get memory for and read a key
- Key *thiskey = btree->NullKey()->Make();
- thiskey->Key::operator=(*btree->NullKey());
- thiskey->Read(nf);
-
- // ---- read the key's file address
- NodeNbr fa;
- nf.read((char *)&fa, sizeof(NodeNbr));
- thiskey->fileaddr = fa;
-
- if (!header.isleaf) {
- NodeNbr lnode;
- nf.read((char *)&lnode, sizeof(NodeNbr));
- thiskey->lowernode = lnode;
- }
- thiskey->AppendListEntry(&keys);
- }
- }
- }
-
- // -------- write a key to the node's disk record
- void TNode::WriteKey(Key *thiskey)
- {
- long kl;
- fstream& nf = btree->IndexFile().Nfile();
- if (btree->KeyLength() == 0)
- kl = nf.tellp();
- // -------- write the key value
- thiskey->Write(nf);
- // ---- write the key's file address
- NodeNbr fa = thiskey->fileaddr;
- nf.write((char *)&fa, sizeof(NodeNbr));
- // ------- post the key length in the btree header
- if (btree->KeyLength() == 0) {
- long km = nf.tellp();
- btree->SetKeyLength((int) (km - kl));
- }
- if (!header.isleaf) {
- // --- write the lower node pointer for non-leaf keys
- NodeNbr lnode = thiskey->lowernode;
- nf.write((char *)&lnode, sizeof(NodeNbr));
- }
- }
-
- TNode::~TNode()
- {
- if (header.keycount == 0)
- // ---- this node is to be deleted
- deletenode = pTrue;
- else {
- fstream& nf = btree->IndexFile().Nfile();
- if (nodechanged) {
- long nad = NodeAddress() + Node::NodeHeaderSize();
- nf.seekp(nad);
- // ------- write the node header
- nf.write((char *) &header, sizeof(TNodeHeader));
- nf.sync();
- }
- // ------- write the keys
- Key *thiskey = (Key *) keys.FirstListEntry();
- while (thiskey != NULL) {
- if (nodechanged)
- WriteKey(thiskey);
- Key *nkey = (Key *) (thiskey->NextListEntry());
- delete thiskey;
- thiskey = nkey;
- }
- if (nodechanged) {
- // ------ pad the node
- int em = m();
- for (int i = header.keycount; i < em; i++)
- WriteKey(btree->NullKey());
-
- int nodesize =
- NodeHeaderSize() + em * btree->KeyLength();
- if (!header.isleaf)
- nodesize += em * sizeof(NodeNbr);
- int residual = nodelength - nodesize;
- if (residual > 0) {
- char *fill = new char[residual];
- memset(fill, 0, residual);
- nf.write(fill, residual);
- delete fill;
- }
- }
- }
- }
-
- // ------- assignment operator
- TNode& TNode::operator=(TNode &tnode)
- {
- Key *thiskey;
- // ---- if receiver has any keys, delete them
- while (header.keycount > 0) {
- thiskey = (Key *) keys.FirstListEntry();
- thiskey->DeleteListEntry();
- delete thiskey;
- --header.keycount;
- }
- Node::operator=(tnode);
- header = tnode.header;
- currkey = NULL;
- // ------- copy the keys
- thiskey = (Key *) tnode.keys.FirstListEntry();
- while (thiskey != NULL) {
- Key *newkey = btree->NullKey()->Make();
- *newkey = *thiskey;
- newkey->AppendListEntry(&keys);
- if (thiskey == tnode.currkey)
- currkey = newkey;
- thiskey = (Key *) (thiskey->NextListEntry());
- }
- return *this;
- }
-
- // -------- compute m value of node
- int TNode::m()
- {
- int keyspace = nodelength - NodeHeaderSize();
- int keylen = btree->KeyLength();
- if (!header.isleaf)
- keylen += sizeof(NodeNbr);
- return keyspace / keylen;
- }
-
- // ---------- search a node for a match on a key
- pBool TNode::SearchNode(Key *keyvalue)
- {
- currkey = (Key *) keys.FirstListEntry();
- while (currkey != NULL) {
- if (*currkey > *keyvalue)
- break;
- if (*currkey == *keyvalue) {
- if (keyvalue->indexno == 0)
- return pTrue;
- if (currkey->fileaddr == keyvalue->fileaddr)
- return pTrue;
- if (keyvalue->fileaddr == 0)
- return pTrue;
- if (currkey->fileaddr > keyvalue->fileaddr)
- break;
- }
- currkey = (Key *) (currkey->NextListEntry());
- }
- return pFalse;
- }
-
- void TNode::Insert(Key *keyvalue)
- {
- // -------- insert the new key
- Key *ky = keyvalue->Make();
- *ky = *keyvalue;
- if (currkey == NULL)
- ky->AppendListEntry(&keys);
- else
- ky->InsertListEntry(currkey, &keys);
- header.keycount++;
- nodechanged = pTrue;
- currkey = ky;
- }
-
- // ---- a node "adopts" all its children by telling
- // them to point to it as their parent
- void TNode::Adoption()
- {
- Adopt(header.lowernode);
- Key *thiskey = (Key *) keys.FirstListEntry();
- for (int i = 0; i < header.keycount; i++) {
- Adopt(thiskey->lowernode);
- thiskey = (Key *) (thiskey->NextListEntry());
- }
- }
-
- // --- adopt a child node
- void TNode::Adopt(NodeNbr node)
- {
- if (node) {
- TNode nd(btree, node);
- nd.header.parent = nodenbr;
- nd.nodechanged = pTrue;
- }
- }
-
- // ---- redistribute keys among two sibling nodes
- pBool TNode::Redistribute(NodeNbr sib)
- {
- if (sib == 0)
- return pFalse;
- TNode sibling(btree, sib);
- //Commented out by UMESH
- if (sibling.header.keycount >= sibling.m() ||
- sibling.header.parent != header.parent)
- return pFalse;
- //Modification to the code commented out above by UMESH
- // if(sibling.header.parent != header.parent)
- // return pFalse;
- // ---- assign left and right associations
- TNode *left, *right;
- if (sib == header.leftsibling) {
- right = this;
- left = &sibling;
- }
- else {
- right = &sibling;
- left = this;
- }
- // ------- compute number of keys to be in left node
- int leftct =
- (left->header.keycount + right->header.keycount) / 2;
- // ------- if no redistribution would occur
- if (leftct == left->header.keycount)
- return pFalse;
- // ------- compute number of keys to be in right node
- int rightct =
- (left->header.keycount+right->header.keycount)-leftct;
- // ------- get the parent
- TNode parent(btree, left->header.parent);
- // --- position parent's currkey
- // to one that points to siblings
- parent.SearchNode((Key *)(left->keys.FirstListEntry()));
- // ----- will move keys from left to right or right to
- // left depending on which node has the greater
- // number of keys to start with.
- if (left->header.keycount < right->header.keycount) {
- // ----- moving keys from right to left
- int mvkeys = right->header.keycount - rightct - 1;
- // ----- move key from parent to end of left node
- left->currkey = parent.currkey;
- parent.currkey =
- (Key *) parent.currkey->NextListEntry();
- left->currkey->DeleteListEntry();
- left->currkey->AppendListEntry(&left->keys);
- if (!left->header.isleaf)
- left->currkey->lowernode = right->header.lowernode;
- // --- point to the keys to move
- // (at front of right node)
- Key *movekey = (Key *) right->keys.FirstListEntry();
- // ---- move keys from right to left node
- for (int i = 0; i < mvkeys; i++) {
- Key *nkey = (Key *) movekey->NextListEntry();
- movekey->DeleteListEntry();
- movekey->AppendListEntry(&left->keys);
- movekey = nkey;
- }
- // --- move separating key from right node to parent
- movekey->DeleteListEntry();
- movekey->InsertListEntry(parent.currkey,&parent.keys);
- if (!right->header.isleaf)
- right->header.lowernode = movekey->lowernode;
- movekey->lowernode = right->nodenbr;
- right->header.keycount = rightct;
- left->header.keycount = leftct;
- if (!left->header.isleaf)
- left->Adoption();
- }
- else {
- // -------- moving from left to right
- int mvkeys = left->header.keycount - leftct - 1;
- // ----- move key from parent to right node
- right->currkey = parent.currkey;
- parent.currkey =
- (Key *) parent.currkey->NextListEntry();
- right->currkey->DeleteListEntry();
- right->currkey->InsertListEntry(
- right->keys.FirstListEntry(), &right->keys);
- if (!right->header.isleaf)
- right->currkey->lowernode=right->header.lowernode;
- // ----- locate the first key to move in the left node
- Key *movekey = (Key *) (left->keys.FirstListEntry());
- for (int i = 0; i < leftct; i++)
- movekey = (Key *) movekey->NextListEntry();
- // ----- move key from left node up to parent
- Key *nkey = (Key *) movekey->NextListEntry();
- movekey->DeleteListEntry();
- movekey->InsertListEntry(parent.currkey,&parent.keys);
- right->header.lowernode = movekey->lowernode;
- movekey->lowernode = right->nodenbr;
- movekey = nkey;
- // --- move keys from the left node to the right node
- Key *inskey = (Key *) right->keys.FirstListEntry();
- for (i = 0; i < mvkeys; i++) {
- Key *nkey = (Key *) movekey->NextListEntry();
- movekey->DeleteListEntry();
- movekey->InsertListEntry(inskey, &right->keys);
- movekey = nkey;
- }
- right->header.keycount = rightct;
- left->header.keycount = leftct;
- if (!right->header.isleaf)
- right->Adoption();
- }
- nodechanged =
- sibling.nodechanged =
- parent.nodechanged = pTrue;
- return pTrue;
- }
-
- // ------ implode the keys of two sibling nodes
- pBool TNode::Implode(TNode &right)
- {
- int totkeys = right.header.keycount+header.keycount;
- if (totkeys >= m() ||
- right.header.parent != header.parent)
- return pFalse;
- nodechanged = right.nodechanged = pTrue;
- header.rightsibling = right.header.rightsibling;
- header.keycount += right.header.keycount+1;
- right.header.keycount = 0;
- // ---- get the parent of the imploding nodes
- TNode parent(btree, header.parent);
- parent.nodechanged = pTrue;
- // ---- position parent's currkey to
- // key that points to siblings
- parent.SearchNode((Key *) keys.FirstListEntry());
- // ---- move the parent's key to the left sibling
- parent.currkey->DeleteListEntry();
- parent.currkey->AppendListEntry(&keys);
- parent.currkey->lowernode = right.header.lowernode;
- parent.header.keycount--;
- if (parent.header.keycount == 0)
- // -- combined the last two leaf nodes into a new root
- header.parent = 0;
- // -- move the keys from the right sibling into the left
- Key *movekey = (Key *) right.keys.FirstListEntry();
- while (movekey != NULL) {
- Key *nkey = (Key *) movekey->NextListEntry();
- movekey->DeleteListEntry();
- movekey->AppendListEntry(&keys);
- movekey = nkey;
- }
- if (header.rightsibling) {
- // - point right sibling of old right to imploded node
- TNode farright(btree, header.rightsibling);
- farright.header.leftsibling = GetNodeNbr();
- farright.nodechanged = pTrue;
- }
- Adoption();
- return pTrue;
- }
-
-
-