UbixOS V2  2.0
btree.cpp
Go to the documentation of this file.
1 // http://www.cs.msstate.edu/~cs2314/global/BTreeAnimation/algorithm.html
2 
3 /*
4 
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <iostream>
10 #include <assert.h>
11 #include "btree.h"
12 #include "ubixfs.h"
13 
14 using namespace std;
15 #define VERIFY(x, y, z, n) if ((x) != (y)) { cout << "verify " << z << " failed" << endl; PrintWholeTree(); }
16 
17 bTree::bTree(UbixFS * filesystem, fileDescriptor * myfd) {
18  size_t result = 0;
19 
20  root = NULL;
21  tag = 0;
22  fs = filesystem;
23  fd = myfd;
24  header = new bTreeHeader;
25  assert(header);
26  memset(header, 0, sizeof(bTreeHeader));
27  assert(fs);
28  result = fs->vfs_read(fd, header, 0, sizeof(bTreeHeader));
29  assert(result == sizeof(bTreeHeader));
30 
31  // If there are any files in this dir, load the first node of the b+tree
32  if (header->treeLeafCount != 0) {
33  assert(header->firstNodeOffset != 0);
34  root = new bNode;
35  assert(root);
36  result = fs->vfs_read(fd, root, header->firstNodeOffset, sizeof(bNode));
37  assert(result == sizeof(bNode));
38  } // if
39 
40 } // bTree::bTree
41 
42 bTree::bTree(const char * key, ubixfsInode * inode) {
43 // once the FS and the bTree are interfaced, this should go away
44  root = NULL;
45  tag = 0;
46  header = new bTreeHeader;
47  assert(header);
48  memset(header, 0, sizeof(bTreeHeader));
49  header->treeDepth = 1;
50  header->treeWidth = 0;
51  header->treeLeafCount = 0;
52  header->firstDeleted = -1;
53  header->firstNodeOffset = sizeof(bTreeHeader);
54 
55  if (inode == NULL) return;
56  root = allocEmptyNode();
57  if (root == NULL) return;
58  root->used = 1;
59  root->parent.bPtr = NULL;
60  root->leaf = true;
61  root->childCount[1] = 1;
62 
63 // cout << "---Creating " << inode->name << "@" << inode << endl;
64  strncpy(root->keys[0], key, B_MAX_NAME_LENGTH);
65  // insert pointer to data page to the right of the data
66  root->head[1].iPtr = inode;
67  root->tail[1].iPtr = inode;
68 
69  root->present[1] = true;
70  if (inode != NULL) {
71  inode->next.bPtr = inode->prev.bPtr = NULL;
72  } // if
73  return;
74 } // bTree:bTree
75 
76 bool
77 bTree::Insert(const char * key, ubixfsInode * inode) {
78  bNode * bnode = root;
79  ubixfsInode * tmpInode = NULL;
80  unsigned int curSlot = 0;
81 
82  if (inode == NULL) return false;
83 
84  // note: this code is right out of the constructor
85  if (root == NULL) {
86  if (header == NULL) header = new bTreeHeader;
87  assert(header);
88  memset(header, 0, sizeof(bTreeHeader));
89  header->treeDepth = 1;
90  header->treeWidth = 0;
91  header->treeLeafCount = 0;
92  header->firstDeleted = -1;
93  header->firstNodeOffset = sizeof(bTreeHeader);
94 
95  root = allocEmptyNode();
96  assert(root);
97  if (root == NULL) return false;
98 
99  root->used = 1;
100  root->parent.bPtr = NULL;
101  root->leaf = true;
102  root->childCount[1] = 1;
103 
104  strncpy(root->keys[0], key, B_MAX_NAME_LENGTH);
105  // insert pointer to data page to the right of the data
106  root->head[1].iPtr = inode;
107  root->tail[1].iPtr = inode;
108 
109  root->present[1] = true;
110  inode->next.iPtr = inode->prev.iPtr = NULL;
111  return true;
112  } // if
113 
114  tmpInode = Find(key);
115  if (tmpInode != NULL) return false;
116 // PrintWholeTree();
117 // cout << "Insert(" << key << ")" << endl;
118 //Info(bnode);
119  ++header->treeLeafCount;
120  //Find the leaf node the inode goes into
121 
122  assert(bnode->used);
123 // cout << "---Inserting " << inode->name << " @ " << inode << endl;
124  while (bnode != NULL && !bnode->leaf) {
125  if (strcmp(key, bnode->keys[0]) < 0) {
126  bnode = bnode->head[0].bPtr;
127  } else {
128  if (strcmp(key, bnode->keys[bnode->used-1]) >= 0) {
129  bnode = bnode->head[bnode->used].bPtr;
130  } else {
131  for (unsigned int i = 1; i < bnode->used; i++) {
132  if (strcmp(key, bnode->keys[i]) < 0) {
133  bnode = bnode->head[i].bPtr;
134  break;
135  } // if
136  } // for i
137  } // else
138  }
139  } // while
140 
141 
142 assert(bnode);
143 if (bnode->leaf != true) cout << "leafnode!=true" << endl;
144 assert(inode);
145 
146  if (strcmp(key, bnode->keys[curSlot = 0]) < 0)
147  tmpInode = bnode->head[curSlot].iPtr;
148  else
149  if (strcmp(key, bnode->keys[(curSlot = bnode->used)-1]) >= 0)
150  tmpInode = bnode->head[bnode->used].iPtr;
151  else {
152  for (curSlot = 1; curSlot < bnode->used; curSlot++) {
153  if (strcmp(key, bnode->keys[curSlot]) < 0) {
154  tmpInode = bnode->head[curSlot].iPtr;
155  break;
156  } // if
157  } // for curSlot
158  tmpInode = bnode->head[curSlot].iPtr;
159  } // else
160 
161 
162  if (tmpInode == NULL) {
163  // This is the first node in this leaf
164  bnode->head[curSlot].iPtr = bnode->tail[curSlot].iPtr = inode;
165  bnode->present[curSlot] = true;
166 
167  if (curSlot == 0) {
168 
169  if (bnode->head[1].iPtr != NULL) {
170  ubixfsInode * iptr = bnode->head[1].iPtr;
171  inode->prev.iPtr = iptr->prev.iPtr;
172  inode->next.iPtr = iptr;
173  iptr->prev.iPtr = inode;
174  if (inode->prev.iPtr != NULL)
175  inode->prev.iPtr->next.iPtr = inode;
176  } else {
177  inode->next.iPtr = inode->prev.iPtr = NULL;
178  } // else
179 
180  } else {
181  ++bnode->used;
182  } // else
183 
184  } else {
185  // Add node to leaf page. Scan through to find where it goes.
186 
187  if (strcmp(key, bnode->head[curSlot].iPtr->name) < 0)
188  {
189 
190  inode->next.iPtr = bnode->head[curSlot].iPtr;
191  inode->prev.iPtr = inode->next.iPtr->prev.iPtr;
192  inode->next.iPtr->prev.iPtr = inode;
193  if (inode->prev.iPtr != NULL) inode->prev.iPtr->next.iPtr = inode;
194  bnode->head[curSlot].iPtr = inode;
195 
196  } else {
197 
198  if (strcmp(key, bnode->tail[curSlot].iPtr->name) > 0) {
199 
200  inode->prev.iPtr = bnode->tail[curSlot].iPtr;
201  inode->next.iPtr = inode->prev.iPtr->next.iPtr;
202  inode->prev.iPtr->next.iPtr = inode;
203 
204  if (inode->next.iPtr != NULL) inode->next.iPtr->prev.iPtr = inode;
205  bnode->tail[curSlot].iPtr = inode;
206 
207  } else {
208 
209 
210  ubixfsInode * tmpInode = bnode->head[curSlot].iPtr;
211  for (unsigned int i = 0; i < bnode->childCount[curSlot]; i++) {
212  if (strcmp(key, tmpInode->name) < 0) {
213  inode->next.iPtr = tmpInode;
214  inode->prev.iPtr = tmpInode->prev.iPtr;
215  inode->next.iPtr->prev.iPtr = inode;
216  inode->prev.iPtr->next.iPtr = inode;
217  break;
218  } // if
219  tmpInode = tmpInode->next.iPtr;
220  } // for i
221 
222  } // else
223 
224  } // else
225 
226  } // else
227 
228 
229 
230  if (++bnode->childCount[curSlot] == B_MAX_CHILD_COUNT) {
231 
232 // cout << "---- before split ----" << endl;
233 // Info(bnode);
234 
235  if (curSlot != bnode->used) {
236  int shift = bnode->used - curSlot +1;
237 
238  memmove(&bnode->head[curSlot+1],
239  &bnode->head[curSlot],
240  sizeof(bnode->head[0]) * shift);
241  memmove(&bnode->tail[curSlot+1],
242  &bnode->tail[curSlot],
243  sizeof(bnode->tail[0]) * shift);
244  memmove(&bnode->present[curSlot+1],
245  &bnode->present[curSlot],
246  sizeof(bnode->present[0]) * shift);
247  memmove(&bnode->childCount[curSlot+1],
248  &bnode->childCount[curSlot],
249  sizeof(bnode->childCount[0]) * shift);
250 
251  memmove(&bnode->keys[curSlot+1],
252  &bnode->keys[curSlot],
253  sizeof(bnode->keys[0]) * (shift-1));
254  memset(bnode->keys[curSlot], 0, B_MAX_NAME_LENGTH);
255  } else {
256  bnode->head[curSlot+1] = bnode->head[curSlot];
257  bnode->tail[curSlot+1] = bnode->tail[curSlot];
258  bnode->childCount[curSlot+1] = bnode->childCount[curSlot];
259  bnode->present[curSlot+1] = bnode->present[curSlot];
260  } // else
261 
262  ubixfsInode * tmpInode = bnode->head[curSlot].iPtr;
263 
264  for (unsigned int i = 0; i < (B_MAX_CHILD_COUNT+1) >> 1; i++) {
265  assert(tmpInode);
266  tmpInode = tmpInode->next.iPtr;
267  } // for i
268 
269  strncpy(bnode->keys[curSlot], tmpInode->name, B_MAX_NAME_LENGTH);
270  bnode->head[curSlot+1].iPtr = tmpInode;
271  bnode->tail[curSlot].iPtr = tmpInode->prev.iPtr;
272  bnode->childCount[curSlot] = (B_MAX_CHILD_COUNT+1) >> 1;
273  bnode->childCount[curSlot+1] -= bnode->childCount[curSlot];
274  bnode->present[curSlot] = true;
275  ++header->treeWidth;
276  if (++bnode->used == B_MAX_KEYS) splitNode(bnode);
277 
278  } // if leaf is full
279 // Info(bnode);
280  return true;
281 } // bTree::Insert
282 
283 void
284 bTree::splitNode(bNode * oldNode) {
285  ubixfsInode * tmpInode = NULL;
286  assert(oldNode);
287  if (oldNode == NULL) return;
288  if (oldNode->used != B_MAX_KEYS) return;
289 
290  bNode * newNode = allocEmptyNode();
291  if (newNode == NULL) return;
292 
293  unsigned int shift = B_MAX_KEYS >> 1;
294  unsigned int splitLoc = B_MAX_KEYS - shift;
295  ++ shift;
296 // cout << "oldNode before split: " << endl;
297 // Info(oldNode);
298 // cout << "splitLoc: " << splitLoc << endl;
299 // cout << "shift: " << shift << endl;
300 
301  newNode->used = oldNode->used = B_MAX_KEYS >> 1;
302  newNode->parent.bPtr = oldNode->parent.bPtr;
303  newNode->leaf = oldNode->leaf;
304 
305 // cout << "newNode->used: " << newNode->used << endl;
306 // cout << "oldNode->used: " << oldNode->used << endl;
307 
308  memcpy(&newNode->keys[0],
309  &oldNode->keys[splitLoc],
310  sizeof(newNode->keys[0]) * (shift-1));
311 
312  memset(&oldNode->keys[splitLoc], 0, sizeof(newNode->keys[0]) * (shift-1));
313 
314  memcpy(&newNode->present[0],
315  &oldNode->present[splitLoc],
316  sizeof(newNode->present[0]) * shift);
317 
318  memset(&oldNode->present[splitLoc], 0, sizeof(newNode->present[0]) * shift);
319 
320  memcpy(&newNode->head[0],
321  &oldNode->head[splitLoc],
322  sizeof(newNode->head[0]) * shift);
323 
324  memset(&oldNode->head[splitLoc], 0,
325  sizeof(newNode->head[0]) * shift);
326 
327  memcpy(&newNode->tail[0],
328  &oldNode->tail[splitLoc],
329  sizeof(newNode->tail[0]) * shift);
330 
331  memset(&oldNode->tail[splitLoc], 0,
332  sizeof(newNode->tail[0]) * shift);
333 
334  memcpy(&newNode->childCount[0],
335  &oldNode->childCount[splitLoc],
336  sizeof(newNode->childCount[0]) * shift);
337 
338  memset(&oldNode->childCount[splitLoc], 0,
339  sizeof(newNode->childCount[0]) * shift);
340 
341  if (!newNode->leaf) {
342  for (unsigned int i = 0; i <= newNode->used; i++) {
343  newNode->head[i].bPtr->parent.bPtr = newNode;
344  } // for i
345  } // if newNode isn't a leaf
346 
347  tmpInode = GetFirstNode(newNode);
348  assert(tmpInode);
349 
350  if (oldNode == root) {
351  // allocate a new root node
352  ++header->treeDepth;
353  root = allocEmptyNode();
354  oldNode->parent.bPtr = root;
355  newNode->parent.bPtr = root;
356  // strncpy(root->keys[0], newNode->keys[0], B_MAX_NAME_LENGTH);
357  strncpy(root->keys[0], tmpInode->name, B_MAX_NAME_LENGTH);
358  root->head[0].bPtr = oldNode;
359  root->tail[0].bPtr = root->tail[1].bPtr = NULL;
360  root->head[1].bPtr = newNode;
361  root->used = 1;
362  root->leaf = false;
363  root->present[0] = root->present[1] = true;
364  root->childCount[0] = root->childCount[1] = 0;
365 // root->childCount[0] = oldNode->used;
366 // root->childCount[1] = newNode->used;
367 
368 // cout << "parent" << endl;
369 // Info(newNode->parent);
370 // cout << "oldNode" << endl;
371 // Info(oldNode);
372 // cout << "-----" << endl;
373 // cout << "newNode" << endl;
374 // Info(newNode);
375 // cout << "-----" << endl;
376 
377  } else {
378  insertNode(newNode->parent.bPtr, tmpInode->name, newNode);
379  // if (oldNode->parent->used == B_MAX_KEYS) splitNode(oldNode->parent);
380  } // else
381  return;
382 } // bTree::splitNode
383 
384 void
385 bTree::insertNode(bNode * node, const char * key, bNode * headPtr) {
386  unsigned int curSlot = 0;
387  if (node == NULL || key == NULL) return;
388 
389  if (strcmp(key, node->keys[node->used-1]) >= 0){
390  curSlot = node->used;
391  memset(node->keys[curSlot], 0, B_MAX_NAME_LENGTH);
392  strncpy(node->keys[curSlot], key, B_MAX_NAME_LENGTH);
393  node->head[curSlot+1].bPtr = headPtr;
394  node->tail[curSlot+1].bPtr = NULL;
395  node->present[curSlot+1] = true;
396  node->childCount[node->used] = 0; // maybe?
397 
398  } else {
399 
400  for (curSlot = 0; curSlot < node->used; curSlot++) {
401  if (strcmp(key, node->keys[curSlot]) < 0) break;
402  } // for
403 
404 
405  *//*
406  * note that there is one more item for everything but keys
407  * So, make the shift count +1 and just subtract it from the key shift
408  * later
409  *//*
410  int shift = node->used - curSlot +1;
411 
412  memmove(&node->head[curSlot+1],
413  &node->head[curSlot],
414  sizeof(node->head[0]) * shift);
415  memmove(&node->tail[curSlot+1],
416  &node->tail[curSlot],
417  sizeof(node->tail[0]) * shift);
418  memmove(&node->present[curSlot+1],
419  &node->present[curSlot],
420  sizeof(node->present[0]) * shift);
421  memmove(&node->childCount[curSlot+1],
422  &node->childCount[curSlot],
423  sizeof(node->childCount[0]) * shift);
424 
425  memmove(&node->keys[curSlot+1],
426  &node->keys[curSlot],
427  sizeof(node->keys[0]) * (shift-1));
428 
429  memset(node->keys[curSlot], 0, B_MAX_NAME_LENGTH);
430  strncpy(node->keys[curSlot], key, B_MAX_NAME_LENGTH);
431  node->head[curSlot+1].bPtr = headPtr;
432  node->tail[curSlot+1].bPtr = NULL;
433  node->present[curSlot+1] = true;
434 // node->childCount[node->used] = ?;
435  } // else
436  if (++node->used == B_MAX_KEYS) splitNode(node);
437  return;
438 } // bTree::insertNode
439 
440 bNode *
441 bTree::allocEmptyNode(void) {
442  bNode * newNode = new bNode;
443 
444  memset(newNode, 0, sizeof(bNode));
445  newNode->magic1 = B_NODE_MAGIC_1;
446  newNode->magic2 = B_NODE_MAGIC_2;
447  newNode->parent.bPtr = NULL;
448  newNode->tag = ++tag; // this will start at 1 (0 is the header node)
449  return newNode;
450 } // bTree::allocEmptyNode
451 
452 void
453 bTree::Info(const bNode * node) {
454  ubixfsInode * inode = NULL;
455  if (node == NULL || root == NULL) return;
456  cout << node << " | " << node->parent.bPtr << endl;
457  for (unsigned int i = 0; i <= node->used; i++) {
458  inode = node->head[i].iPtr;
459 // cout << "(" << node->childCount[i] << ")";
460  for (unsigned int k = 0; k < node->childCount[i]; k++) {
461  cout << "[" << inode->name << "]";
462  inode = inode->next.iPtr;
463  } // for k
464  if (i != node->used) cout << " {" << node->keys[i] << "} ";
465  } // for i
466  cout << endl;
467  return;
468 #if 0
469  for (unsigned int i = 0; i < node->used; i++) {
470  cout << "keys[" << i << "]: " << node->keys[i] << " ";
471  } // for i
472  cout << endl;
473  cout << "node->used: " << node->used << endl;
474  cout << "leaf: " << node->leaf << endl;
475  for (unsigned int i = 0; i <= node->used; i++) {
476  inode = (ubixfsInode *)node->head[i];
477 cout << "node->childCount["<<i<<"]: " << node->childCount[i] << endl;
478  for (unsigned int j = 0; j < node->childCount[i]; j++) {
479  assert(inode);
480  cout << "[" << i << "].[" << j << "]->" << inode->name << endl;
481  inode = inode->next;
482  } // for j
483  } // for i
484 #endif
485 } // bTree::Info
486 
487 void
488 bTree::Info(void) {
489  ubixfsInode * inode = NULL;
490 
491  cout << "tree depth: " << header->treeDepth << endl;
492  cout << "tree width: " << header->treeWidth << endl;
493  cout << "tree leaf count: " << header->treeLeafCount << endl;
494  cout << "tag: " << tag << endl;
495 
496  if (root == NULL) return;
497 
498  for (unsigned int i = 0; i <= root->used; i++) {
499  cout << "CC[" << i << "]: " << root->childCount[i] << " ";
500  } // for i
501 
502  cout << endl;
503  for (unsigned int i = 0; i <= root->used; i++) {
504  cout << "CH[" << i << "]: " << root->head[i].bPtr << " ";
505  } // for i
506 
507  cout << endl;
508  for (unsigned int i = 0; i <=root->used; i++) {
509  cout << "CT[" << i << "]: " << root->tail[i].bPtr << " ";
510  } // for i
511  cout << endl;
512  for (unsigned int i = 0; i < root->used; i++) {
513  cout << "keys[" << i << "]: " << root->keys[i] << " ";
514  } // for i
515  cout << endl;
516 
517 cout << "root->used: " << root->used << endl;
518  for (unsigned int i = 0; i <= root->used; i++) {
519  inode = root->head[i].iPtr;
520 cout << "root->childCount["<<i<<"]: " << root->childCount[i] << endl;
521  if (root->leaf) {
522 cout << "root contains leaf node" << endl;
523  for (unsigned int j = 0; j < root->childCount[i]; j++) {
524  assert(inode);
525  cout << "[" << i << "].[" << j << "]->" << inode->name << endl;
526  inode = inode->next.iPtr;
527  } // for j
528  } // if root->leaf
529  } // for i
530 } // bTree::Info
531 
532 void
533 bTree::Print(void) {
534  ubixfsInode * node = GetFirstNode();
535  while (node != NULL) {
536  cout << node->name << endl;
537  node = node->next.iPtr;
538  }
539 } // bTree::Print
540 
541 ubixfsInode *
542 bTree::Find(const char * key) {
543 
544 *//*
545  ubixfsInode * tmp = GetFirstNode();
546  while (tmp!=NULL) {
547  if (strcmp(tmp->name, key) == 0) return tmp;
548  tmp = tmp->next.iPtr;
549  }
550  return NULL;
551 *//*
552  return treeSearch(root, key);
553 } // bTree::Find
554 
555 ubixfsInode *
556 bTree::inodeSearch(ubixfsInode * inode, const char * key) {
557  if (inode == NULL || key == NULL) return NULL;
558  int result = strcmp(inode->name, key);
559  if (result == 0) return inode;
560 
561  if (result < 0) {
562  inode = inode->next.iPtr;
563  while (inode != NULL && ((result = strcmp(inode->name, key)) < 0)) {
564  inode = inode->next.iPtr;
565  } // while
566  } else {
567  inode = inode->prev.iPtr;
568  while (inode != NULL && ((result = strcmp(inode->name, key)) > 0)) {
569  inode = inode->prev.iPtr;
570  } // while
571  } // else
572  return (result == 0 ? inode : NULL);
573 } // bTree::inodeSearch
574 
575 ubixfsInode *
576 bTree::treeSearch(bNode * bnode, const char * key) {
577 
578  if (bnode == NULL || key == NULL || bnode->used == 0) return NULL;
579 
580  if (bnode->leaf)
581  return inodeSearch(GetFirstNode(bnode), key);
582 
583  if (strcmp(key, bnode->keys[0]) < 0) {
584  return treeSearch(bnode->head[0].bPtr, key);
585  } // if
586 
587  if (strcmp(key, bnode->keys[bnode->used-1]) >= 0) {
588  return treeSearch(bnode->head[bnode->used].bPtr, key);
589  } // if
590 
591  for (unsigned int i = 1; i < bnode->used; i++) {
592  if (strcmp(key, bnode->keys[i]) < 0) {
593  return treeSearch(bnode->head[i].bPtr, key);
594  } // if
595  } // for i
596 
597  return NULL;
598 } // bTree::treeSearch
599 
600 ubixfsInode *
601 bTree::GetFirstNode(void) {
602  return GetFirstNode(root);
603 } // bTree::GetFirstNode
604 
605 ubixfsInode *
606 bTree::GetFirstNode(bNode * node) {
607  bNode * tmpNode = node;
608 
609  if (tmpNode == NULL) return NULL;
610 
611  while (!tmpNode->leaf) {
612  for (unsigned int i = 0; i < tmpNode->used; i++) {
613  if (tmpNode->head[i].bPtr != NULL) {
614  tmpNode = tmpNode->head[i].bPtr;
615  break;
616  } // if
617  } // for i
618  } // while
619 
620  for (unsigned int i = 0; i < tmpNode->used; i++) {
621  if (tmpNode->head[i].iPtr != NULL) return tmpNode->head[i].iPtr;
622  } // for i
623  return NULL;
624 } // bTree::GetFirstNode
625 
626 bNode *
627 bTree::findLeafNode(bNode * node, const char * key) {
628  assert(node);
629  assert(key);
630  if (node == NULL || key == NULL) return NULL;
631  assert(node->used);
632  if (node->leaf) return node;
633 
634  if (strcmp(key, node->keys[0]) < 0)
635  return findLeafNode(node->head[0].bPtr, key);
636 
637  if (strcmp(key, node->keys[node->used-1]) >= 0)
638  return findLeafNode(node->head[node->used].bPtr, key);
639 
640  for (unsigned int i = 1; i < node->used; i++) {
641  if (strcmp(key, node->keys[i]) < 0)
642  return findLeafNode(node->head[i].bPtr, key);
643  } // for i
644 
645  return NULL;
646 } // bTree::findLeafNode
647 
648 void
649 bTree::saveNode(FILE * fd, bNode * node, void * tmpPtr) {
650 
651  bNode * ptr = (bNode *)tmpPtr;
652  assert(tmpPtr);
653  assert(fd);
654  assert(node);
655  cout << "writing tag: " << node->tag << endl;
656 
657  memcpy(tmpPtr, node, sizeof(bNode));
658 
659  if (node->parent.bPtr != NULL)
660  ptr->parent.offset = node->parent.bPtr->tag * sizeof(bNode);
661  else
662  ptr->parent.offset = 0;
663 
664  for (unsigned int i = 0; i <= node->used; i++) {
665  bNode * bPtr = node->head[i].bPtr;
666 
667  if (bPtr != NULL)
668  ptr->head[i].offset = bPtr->tag * sizeof(bNode);
669  else
670  ptr->head[i].offset = ~0;
671  ptr->present[i] = false;
672  } // for i
673 
674  if (node->leaf) {
675 
676  for (unsigned int i = 0; i <= node->used; i++) {
677  // ubixfsInode * inode = node->head[i].iPtr;
678  // mji if (inode != NULL) tmp->head[i] = inode->
679  } // for i
680  } else {
681 
682  for (unsigned int i = 0; i <= node->used; i++) {
683 
684  if (node->head[i].bPtr != NULL) saveNode(fd, node->head[i].bPtr, tmpPtr);
685 
686  } // for i
687 
688  } // else
689 
690  return;
691 } // bTree::saveNode
692 
693 bool
694 bTree::Save(const char * filename) {
695  ubixfsInode * uPtr = NULL;
696  if (filename == NULL) return false;
697  FILE * fd = NULL;
698  if ((fd = fopen(filename, "wb+")) == NULL) return false;
699 
700 cout << "tags: " << tag << endl;
701  lseek(fileno(fd), tag * sizeof(bNode), SEEK_END);
702 
703  header->firstNodeOffset = sizeof(bNode);
704  header->firstDeleted = -1;
705  void * tmpPtr = malloc(sizeof(bNode));
706  assert(tmpPtr);
707  uPtr = (ubixfsInode *)tmpPtr;
708  memset(tmpPtr, 0, sizeof(bNode));
709  fwrite(header, sizeof(bTreeHeader), 1, fd);
710  saveNode(fd, root, tmpPtr);
711 
712  fclose(fd);
713  free(tmpPtr);
714  return true;
715 } // bTree::Save
716 
717 bool
718 bTree::Load(const char * filename) {
719  if (filename == NULL) return false;
720  return true;
721 } // bTree::Load
722 
723 bool
724 bTree::Delete(const char * key) {
725 
726  if (key == NULL) return false;
727  return true;
728 } // bTree::Delete
729 
730 bool
731 bTree::Verify(void) {
732  ubixfsInode * node = GetFirstNode();
733  if (node == NULL) return true;
734 
735  while (node != NULL) {
736  ubixfsInode * next = node->next.iPtr;
737  if (next != NULL) {
738  // cout << node->name << "::" << node->next->name << ":::" << strcmp(node->name, node->next->name) << endl;
739  if (strcmp(node->name, next->name) > 0) return false;
740  }
741  node = next;
742  } // while
743  return true;
744 } // bTree::Verify
745 
746 void
747 bTree::Print(bNode * node) {
748  if (node == NULL) return;
749  Info(node);
750  if (!node->leaf)
751  for (unsigned int i = 0; i <= node->used; i++) {
752  Print(node->head[i].bPtr);
753  } // for i
754 } // bTree::Print
755 
756 void
757 bTree::PrintWholeTree(void) {
758  Print(root);
759 } // bTree::PrintWholeTree;
760 
761 bTree::~bTree(void) {
762  cout << "tree depth: " << header->treeDepth << endl;
763  cout << "tree width: " << header->treeWidth << endl;
764  cout << "tree leaf count: " << header->treeLeafCount << endl;
765 } // bTree::~bTree
766 
767 */