Orbiter 2022
Combinatorial Objects
btree.cpp
Go to the documentation of this file.
1// btree.cpp
2//
3// Anton Betten
4// 28.11.2000
5// moved from D2 to ORBI Nov 15, 2007
6
8#include "discreta.h"
9
10using namespace std;
11
12
13
14namespace orbiter {
15namespace layer2_discreta {
16
17//int bt_debug = FALSE;
18
19#undef USE_TABLE
20#define WRITE_INFO_ONLY_AT_END
21
22#define MAX_ROOT_BUF 20
23
24
25
26
27
28
29
30
32Buffer *RootBF = NULL;
33Buffer *tmpBF = NULL;
34 // used in: bt_open(), WriteInfo(), AllocateRec(), ReleaseRec()
35
36
37
40
41
42
43
44
45static void bt_item_copy(ItemTyp *a, ItemTyp *b);
46
47// #############################################################################
48// global stuff
49// #############################################################################
50
51
52
53void database_init(int verbose_level)
54{
55 int f_v = (verbose_level >= 1);
56 int f_vv = (verbose_level >= 2);
57 int i;
58
59 if (f_v) {
60 cout << "database_init()" << endl;
61 }
62
63 if (f_vv) {
64 cout << "BTREEMAXKEYLEN=" << BTREEMAXKEYLEN << endl;
65 cout << "BTREEHALFPAGESIZE=" << BTREEHALFPAGESIZE << endl;
66 cout << "BTREE_PAGE_LENGTH_LOG=" << BTREE_PAGE_LENGTH_LOG << endl;
67 cout << "database_init() sizeof(ItemTyp)=" << sizeof(ItemTyp) << endl;
68 cout << "database_init() sizeof(PageTyp)=" << sizeof(PageTyp) << endl;
69 cout << "database_init() sizeof(Buffer)=" << sizeof(Buffer) << endl;
70 cout << "database_init() sizeof(int_4)=" << sizeof(int_4) << endl;
71 }
72
74 if (RootBF == NULL) {
75 cout << "database_init() no memory for RootBF" << endl;
76 exit(1);
77 }
78 for (i = 0; i < MAX_ROOT_BUF; i++) {
80 }
82
83
84
85 tmpBF = RootBF;
86
87 for (i = 0; i < MAX_FSTREAM_TABLE; i++) {
89 }
90
91 page_table_init(verbose_level - 1);
92
93 if (f_v) {
94 cout << "database_init() done" << endl;
95 }
96}
97
98void database_exit(void)
99{
100 int verbose_level = 0;
101
102 if (RootBF) {
103 delete [] RootBF;
104 RootBF = NULL;
105 }
106 page_table_exit(verbose_level - 1);
107}
108
110// never gives out handle 0, as it stands for file not open
111// that is, the zeroth-entry is never used
112{
113 for (int i = 1; i < MAX_FSTREAM_TABLE; i++) {
114 if (!fstream_table_used[i])
115 return i;
116 }
117 cout << "fstream_table_get_free_entry() table full, "
118 "too many open files" << endl;
119 exit(1);
120}
121
122
124// error if there is no free buffer
125{
126 int i;
127
128 for (i = 0; i < MAX_ROOT_BUF; i++) {
129 if (f_RootBF_free[i]) {
130 f_RootBF_free[i] = FALSE;
131 return i;
132 }
133 }
134 cout << "root_buf_alloc() no free root buffer" << endl;
135 exit(1);
136}
137
138void root_buf_free(int i)
139{
140 if (i < 0 || i >= MAX_ROOT_BUF) {
141 cout << "root_buf_free()|i illegal" << endl;
142 exit(1);
143 }
144 f_RootBF_free[i] = TRUE;
145}
146
147
148
149// #############################################################################
150// class btree
151// #############################################################################
152
154{
155 k = BTREE;
156}
157
159 // copy constructor: this := x
160{
161 cout << "btree::copy constructor for object: "
162 << const_cast<discreta_base &>(x) << "\n";
163 const_cast<discreta_base &>(x).copyobject_to(*this);
164}
165
167 // copy assignment
168{
169 cout << "btree::operator = (copy assignment)" << endl;
170 copyobject(const_cast<discreta_base &>(x));
171 return *this;
172}
173
175{
176 OBJECTSELF s;
177
178 s = self;
179 new(this) btree;
180 self = s;
181 k = BTREE;
182}
183
185{
187}
188
190{
191 // cout << "group_selection::freeself_btree()\n";
193}
194
196{
197 return BTREE;
198}
199
201{
202#ifdef COPY_VERBOSE
203 cout << "btree::copyobject_to()\n";
204 print_as_vector(cout);
205#endif
208#ifdef COPY_VERBOSE
209 x.as_btree().print_as_vector(cout);
210#endif
211}
212
213ostream& btree::print(ostream& ost)
214{
215
216 ost << "BTREE: Root = " << Root() << " FreeRec = " << FreeRec()
217 << " AllocRec = " << AllocRec() << endl;
218 return ost;
219}
220
221void btree::init(const char *file_name, int f_duplicatekeys,
222 int btree_idx)
223{
224 m_l_n(11);
225 c_kind(BTREE);
228 key().m_l(0);
230 filename().init(file_name);
231 f_open() = FALSE;
232 stream() = 0;
233 buf_idx() = 0;
234 Root() = 0;
235 FreeRec() = 0;
236 AllocRec() = 0;
238 page_table_idx() = -1;
239}
240
241void btree::add_key_int4(int field1, int field2)
242{
243 bt_key bk;
244
245 bk.init_int4(field1, field2);
246 key().append(bk);
247}
248
249void btree::add_key_int2(int field1, int field2)
250{
251 bt_key bk;
252
253 bk.init_int2(field1, field2);
254 key().append(bk);
255}
256
257void btree::add_key_string(int output_size, int field1, int field2)
258{
259 bt_key bk;
260
261 bk.init_string(output_size, field1, field2);
262 key().append(bk);
263}
264
265void btree::key_fill_in(char *the_key, Vector& the_object)
266{
267 bt_key_fill_in(the_key, key(), the_object);
268}
269
270void btree::key_print(char *the_key, ostream& ost)
271{
272 bt_key_print(the_key, key(), ost);
273}
274
275void btree::create(int verbose_level)
276{
277 int f_v = (verbose_level >= 1);
278 int f_vv = (verbose_level >= 2);
279 Buffer *Root_BF;
280
281 if (f_v) {
282 cout << "btree::create" << endl;
283 }
284 if (f_open() == TRUE) {
285 cout << "btree::create() already open" << endl;
286 exit(1);
287 }
288 file_create();
289
291 Root_BF = RootBF + buf_idx();
292 fill_char(Root_BF, (int)sizeof(Buffer), 0);
293
294 FreeRec() = 0;
295 AllocRec() = 0;
296 Root() = 0;
297
298 f_open() = TRUE;
299
301
302 if (f_vv) {
303 cout << "before page_table_alloc" << endl;
304 }
305 page_table_idx() = page_table_alloc(verbose_level - 2);
306 if (f_vv) {
307 cout << "page_table_idx = " << page_table_idx() << endl;
308 }
309}
310
311void btree::open(int verbose_level)
312{
313 int f_v = (verbose_level >= 1);
314 int f_vv = (verbose_level >= 2);
315 Buffer *Root_BF;
316
317 if (f_v) {
318 cout << "btree::open verbose_level=" << verbose_level << endl;
319 }
320 if (f_open() == TRUE) {
321 cout << "btree::open() already open" << endl;
322 exit(1);
323 }
324 file_open();
325
327 Root_BF = RootBF + buf_idx();
328 fill_char(Root_BF, (int)sizeof(Buffer), 0);
329
330
331
332 if (f_vv) {
333 cout << "before page_table_alloc" << endl;
334 }
335 page_table_idx() = page_table_alloc(verbose_level - 2);
336 if (f_vv) {
337 cout << "page_table_idx = " << page_table_idx() << endl;
338 }
339
340
341 ReadInfo(verbose_level);
342
343 if (Root() != 0) {
344 if (f_vv) {
345 cout << "reading root page " << Root() << endl;
346 }
347 file_seek(Root());
348 file_read(&Root_BF->Page, "btree::open");
349 Root_BF->PageNum = (int_4) Root();
350 }
351 else {
352 Root_BF->PageNum = 0;
353 }
354}
355
356void btree::close(int verbose_level)
357{
358 int f_v = (verbose_level >= 1);
359
360 if (f_v) {
361 cout << "btree::close" << endl;
362 }
363
364#if 0
365 // write root:
366 Buffer *BF;
367 BF = RootBF + buf_idx();
368
369 file_seek(Root());
370 file_write(&BF->Page, "SavePage");
371#endif
372
373#ifdef USE_TABLE
374 page_table *T;
375
377 T->write_pages_to_file(this, buf_idx(), verbose_level);
378#endif
379#ifdef WRITE_INFO_ONLY_AT_END
380 WriteInfo(verbose_level);
381#endif
382 file_close();
384 page_table_free(page_table_idx(), verbose_level - 2);
385 page_table_idx() = -1;
386}
387
388void btree::ReadInfo(int verbose_level)
389{
390 int f_v = (verbose_level >= 1);
391 int f_vv = (verbose_level >= 2);
392
393 if (f_v) {
394 cout << "btree::ReadInfo" << endl;
395 }
396
397 if (f_vv) {
398 cout << "reading page 0" << endl;
399 }
400 Buffer *BF;
401 BF = new Buffer;
402 file_seek(0);
403 file_read(&BF->Page, "btree::open");
404
405 FreeRec() = BF->Page.NextFreeRec;
406 AllocRec() = BF->Page.AllocRec;
407 Root() = BF->Page.RootRec;
408
409 if (f_vv) {
410 cout << "FreeRec()" << FreeRec() << endl;
411 cout << "AllocRec()" << AllocRec() << endl;
412 cout << "Root()" << Root() << endl;
413 }
414 delete BF;
415}
416
417void btree::WriteInfo(int verbose_level)
418/* Schreibt die Variablen 'AllocRec', 'FreeRec' und 'Root'
419 * als 'AllocRec', 'NextFreeRec' und 'RootRec'
420 * in die 0-te Seite der Datenbank. */
421{
422 int f_v = (verbose_level >= 1);
423 int f_vv = (verbose_level >= 2);
424 int size;
425 Buffer *BF = tmpBF;
426
427 if (f_v) {
428 cout << "btree::WriteInfo" << endl;
429 }
430 if (!f_open()) {
431 cout << "btree::WriteInfo() file not open" << endl;
432 exit(1);
433 }
434 size = sizeof(Buffer);
435 fill_char((char *)BF, size, 0);
436 BF->Page.AllocRec = (int_4) AllocRec();
437 BF->Page.NextFreeRec = (int_4) FreeRec();
438 BF->Page.RootRec = (int_4) Root();
439
440 if (f_vv) {
441 cout << "btree::WriteInfo writing page 0" << endl;
442 cout << "FreeRec()" << FreeRec() << endl;
443 cout << "AllocRec()" << AllocRec() << endl;
444 cout << "Root()" << Root() << endl;
445 }
446
447 file_seek(0);
448 file_write(&BF->Page, "WriteInfo");
449}
450
451int btree::AllocateRec(int verbose_level)
452/* Ein freier Record der Datanbank wird ermittelt
453 * --
454 * rueckgabe: Gibt Nummer eines freien Records an */
455{
456 int f_v = (verbose_level >= 1);
457 int f_vv = (verbose_level >= 2);
458 Buffer *BF = tmpBF;
459 int x;
460
461 if (f_vv) {
462 cout << "btree::AllocateRec" << endl;
463 }
464 if (!f_open()) {
465 cout << "btree::AllocateRec() not open\n";
466 exit(1);
467 }
468 if (FreeRec() == 0) {
469 AllocRec()++;
470#ifdef WRITE_INFO_ONLY_AT_END
471#else
473#endif
474 x = AllocRec();
475#ifdef USE_TABLE
476 page_table *T;
477
479 T->allocate_rec(BF, buf_idx(), x, verbose_level - 1);
480#else
481#endif
482 }
483 else {
484#ifdef USE_TABLE
485 cout << "btree::AllocateRec FreeRec() > 0 not yet implemented" << endl;
486 exit(1);
487#endif
488 fill_char((char *)BF, sizeof(Buffer), 0);
489 x = FreeRec();
490 file_seek(x);
491 file_read(&BF->Page, "AllocateRec");
492 FreeRec() = BF->Page.NextFreeRec;
493#ifdef WRITE_INFO_ONLY_AT_END
494#else
495 WriteInfo(f_v);
496#endif
497 }
498 if (f_v) {
499 cout << "btree::AllocateRec() x = " << x << endl;
500 }
501 return x;
502}
503
505/* Gibt einen Record wieder frei
506 * Der Block wird an den Anfang der Frei-Liste eingefuegt.
507 * --
508 * int x - Nummer des freizugebenden Records */
509{
510 int size;
511 Buffer *BF = tmpBF;
512
513 if (!f_open()) {
514 cout << "btree::ReleaseRec() not open\n";
515 exit(1);
516 }
517 size = (int)sizeof(Buffer);
518 fill_char((char *)BF, size, 0);
519 BF->Page.NextFreeRec = (int_4) FreeRec();
520 file_seek(x);
521 file_write(&BF->Page, "ReleaseRec");
522 FreeRec() = x;
523#ifdef WRITE_INFO_ONLY_AT_END
524#else
526#endif
527#ifdef USE_TABLE
528 cout << "btree::ReleaseRec not yet implemented" << endl;
529 exit(1);
530#endif
531}
532
533void btree::LoadPage(Buffer *BF, int x, int verbose_level)
534/* Laedt eine Seite in den Speicher. Soll die Wurzel ge-
535 * laden werden, so wird nur der Puffer kopiert
536 * --
537 * Buffer *BF - Puffer enthaelt nach Aufruf die Seite
538 * int x - zu ladende Seite */
539{
540 int f_v = (verbose_level >= 1);
541 //int f_vv = (verbose_level >= 2);
542 //int f_vvv = (verbose_level >= 3);
543
544 if (f_v) {
545 cout << "btree::LoadPage x=" << x << endl;
546 }
547 if (!f_open()) {
548 cout << "btree::LoadPage() not open" << endl;
549 exit(1);
550 }
551 if (FALSE /* x == Root() */) {
552 Buffer *Root_BF;
553 Root_BF = RootBF + buf_idx();
554 *BF = *Root_BF;
555 }
556 else {
557 BF->PageNum = (int_4) x;
558#ifdef USE_TABLE
559 page_table *T;
560
562 if (!T->load_page(BF, x, buf_idx(), verbose_level)) {
563 if (f_vv) {
564 cout << "btree::LoadPage loading page " << x <<" from file" << endl;
565 }
566 file_seek(x);
567 BF->PageNum = x;
568 file_read(&BF->Page, "LoadPage");
569 if (f_vvv) {
570 page_print(BF, cout);
571 }
572 if (f_vv) {
573 cout << "saving page " << x << " to page tables" << endl;
574 }
575 T->save_page(BF, buf_idx(), verbose_level);
576 //page_print(BF, cout);
577 }
578#else
579 file_seek(x);
580 file_read(&BF->Page, "LoadPage");
581#endif
582 }
583}
584
585void btree::SavePage(Buffer *BF, int verbose_level)
586/* Eine Seite wird auf den Hintergrundspeicher geschrieben
587 * --
588 * Buffer *BF - Zu speichernde Seite */
589{
590 int f_v = (verbose_level >= 1);
591
592 if (f_v) {
593 cout << "btree::SavePage" << endl;
594 }
595 if (!f_open()) {
596 cout << "btree::SavePage() not open" << endl;
597 exit(1);
598 }
599 if (FALSE /*BF->PageNum == Root()*/) {
600 Buffer *Root_BF;
601 Root_BF = RootBF + buf_idx();
602 *Root_BF = *BF;
603 file_seek(Root_BF->PageNum);
604 file_write(&Root_BF->Page, "SavePage, root");
605 }
606 else {
607#ifdef USE_TABLE
608 page_table *T;
609
611 T->save_page(BF, buf_idx(), verbose_level);
612#else
613 file_seek(BF->PageNum);
614 file_write(&BF->Page, "SavePage");
615#endif
616
617 }
618}
619
620int btree::search_string(discreta_base& key_op, int& pos, int verbose_level)
621{
622 KEYTYPE the_key;
623 char *p_key = the_key.c;
624
625 bt_key &the_bt_key = key()[0].as_bt_key();
626
627 if (the_bt_key.type() != bt_key_string) {
628 cout << "btree::search_string() bt_key not of type string" << endl;
629 exit(1);
630 }
631
632 bt_key_fill_in_string(&p_key, the_bt_key.output_size(), key_op);
633
634 return search(&the_key, NULL, &pos, 1, verbose_level);
635}
636
637void btree::search_interval_int4(int i_min, int i_max,
638 int& first, int &len, int verbose_level)
639{
640 int f_v = (verbose_level >= 1);
641 KEYTYPE key_min, key_max;
642 char *p_key_min = key_min.c;
643 char *p_key_max = key_max.c;
644 integer I_min, I_max;
645 I_min.m_i(i_min - 1);
646 I_max.m_i(i_max);
647 int idx_min, idx_max;
648 int f_found_min, f_found_max;
649
650 bt_key_fill_in_int4(&p_key_min, I_min);
651 bt_key_fill_in_int4(&p_key_max, I_max);
652 if (f_v) {
653 cout << "search_interval_int4 I_min=" << I_min << " I_max=" << I_max << endl;
654 }
655
656 f_found_min = search(&key_min, NULL, &idx_min, 1, verbose_level);
657 f_found_max = search(&key_max, NULL, &idx_max, 1, verbose_level);
658 if (f_v) {
659 cout << "search_interval_int4 f_found_min=" << f_found_min << " idx_min=" << idx_min << endl;
660 cout << "search_interval_int4 f_found_max=" << f_found_max << " idx_max=" << idx_max << endl;
661 }
662 first = idx_min + 1;
663 len = idx_max - idx_min;
664}
665
667 int l1, int u1, int& first, int &len, int verbose_level)
668{
669 int f_v = (verbose_level >= 1);
670
671 if (f_v) {
672 cout << "btree::search_interval_int4_int4 low=(" << l0 << "," << l1 << ") high=(" << u0 << "," << u1 << ")" << endl;
673 }
674 KEYTYPE key_min, key_max;
675 char *p_key_min = key_min.c;
676 char *p_key_max = key_max.c;
677 integer I_min, I_max;
678 int idx_min, idx_max;
679 int f_found_min, f_found_max;
680
681 I_min.m_i(l0);
682 I_max.m_i(u0);
683 bt_key_fill_in_int4(&p_key_min, I_min);
684 bt_key_fill_in_int4(&p_key_max, I_max);
685
686 I_min.m_i(l1 - 1);
687 I_max.m_i(u1);
688 bt_key_fill_in_int4(&p_key_min, I_min);
689 bt_key_fill_in_int4(&p_key_max, I_max);
690
691
692 f_found_min = search(&key_min, NULL, &idx_min, 2, verbose_level);
693 f_found_max = search(&key_max, NULL, &idx_max, 2, verbose_level);
694 if (f_v) {
695 cout << "search_interval_int4_int4() f_found_min=" << f_found_min << " idx_min=" << idx_min << endl;
696 cout << "search_interval_int4_int4() f_found_max=" << f_found_max << " idx_max=" << idx_max << endl;
697 }
698 first = idx_min + 1;
699 len = idx_max - idx_min;
700}
701
703 int l1, int u1, int l2, int u2,
704 int& first, int &len, int verbose_level)
705{
706 int f_v = (verbose_level >= 1);
707 KEYTYPE key_min, key_max;
708 char *p_key_min = key_min.c;
709 char *p_key_max = key_max.c;
710 integer I_min, I_max;
711 int idx_min, idx_max;
712 int f_found_min, f_found_max;
713
714 I_min.m_i(l0);
715 I_max.m_i(u0);
716 bt_key_fill_in_int4(&p_key_min, I_min);
717 bt_key_fill_in_int4(&p_key_max, I_max);
718
719 I_min.m_i(l1);
720 I_max.m_i(u1);
721 bt_key_fill_in_int4(&p_key_min, I_min);
722 bt_key_fill_in_int4(&p_key_max, I_max);
723
724 I_min.m_i(l2 - 1);
725 I_max.m_i(u2);
726 bt_key_fill_in_int4(&p_key_min, I_min);
727 bt_key_fill_in_int4(&p_key_max, I_max);
728
729
730 f_found_min = search(&key_min, NULL, &idx_min, 3, verbose_level);
731 f_found_max = search(&key_max, NULL, &idx_max, 3, verbose_level);
732 if (f_v) {
733 cout << "search_interval_int4_int4_int4() f_found_min=" << f_found_min << " idx_min=" << idx_min << endl;
734 cout << "search_interval_int4_int4_int4() f_found_max=" << f_found_max << " idx_max=" << idx_max << endl;
735 }
736 first = idx_min + 1;
737 len = idx_max - idx_min;
738}
739
741 int l1, int u1, int l2, int u2,
742 int l3, int u3, int& first, int &len, int verbose_level)
743{
744 int f_v = (verbose_level >= 1);
745 KEYTYPE key_min, key_max;
746 char *p_key_min = key_min.c;
747 char *p_key_max = key_max.c;
748 integer I_min, I_max;
749 int idx_min, idx_max;
750 int f_found_min, f_found_max;
751
752 I_min.m_i(l0);
753 I_max.m_i(u0);
754 bt_key_fill_in_int4(&p_key_min, I_min);
755 bt_key_fill_in_int4(&p_key_max, I_max);
756
757 I_min.m_i(l1);
758 I_max.m_i(u1);
759 bt_key_fill_in_int4(&p_key_min, I_min);
760 bt_key_fill_in_int4(&p_key_max, I_max);
761
762 I_min.m_i(l2);
763 I_max.m_i(u2);
764 bt_key_fill_in_int4(&p_key_min, I_min);
765 bt_key_fill_in_int4(&p_key_max, I_max);
766
767 I_min.m_i(l3 - 1);
768 I_max.m_i(u3);
769 bt_key_fill_in_int4(&p_key_min, I_min);
770 bt_key_fill_in_int4(&p_key_max, I_max);
771
772
773 f_found_min = search(&key_min, NULL, &idx_min, 4, verbose_level);
774 f_found_max = search(&key_max, NULL, &idx_max, 4, verbose_level);
775 if (f_v) {
776 cout << "search_interval_int4_int4_int4_int4() f_found_min=" << f_found_min << " idx_min=" << idx_min << endl;
777 cout << "search_interval_int4_int4_int4_int4() f_found_max=" << f_found_max << " idx_max=" << idx_max << endl;
778 }
779 first = idx_min + 1;
780 len = idx_max - idx_min;
781}
782
783int btree::search_int4_int4(int data1, int data2, int& idx, int verbose_level)
784{
785 int f_v = (verbose_level >= 1);
786
787 if (f_v) {
788 cout << "btree::search_int4_int4 data=(" << data1 << "," << data2 << ")" << endl;
789 }
790 KEYTYPE key;
791 char *p_key = key.c;
792 integer I1, I2;
793 int f_found;
794
795 I1.m_i(data1);
796 I2.m_i(data2);
797 bt_key_fill_in_int4(&p_key, I1);
798 bt_key_fill_in_int4(&p_key, I2);
799
800
801
802 f_found = search(&key, NULL, &idx, 2, verbose_level);
803 if (f_v) {
804 cout << "search_int4_int4() f_found=" << f_found << " idx=" << idx << endl;
805 }
806 return f_found;
807}
808
809int btree::search_unique_int4(int i, int verbose_level)
810// returns -1 if the element could not be found or is not unique.
811// otherwise, the idx of the element is returned
812{
813 int first, len;
814
815 search_interval_int4(i, i, first, len, verbose_level);
816 if (len > 1) {
817 cout << "btree::search_unique_int4() WARNING: element is not unique, returning -1" << endl;
818 return -1;
819 }
820 if (len == 0) {
821 return -1;
822 }
823 return first;
824}
825
827 int i2, int i3, int verbose_level)
828// returns -1 if an element whose key starts with [i0,i1,i2,i3] could not be found or is not unique.
829// otherwise, the idx of that element is returned
830{
831 int f_v = (verbose_level >= 1);
832 int first, len;
833
835 i0, i0,
836 i1, i1,
837 i2, i2,
838 i3, i3,
839 first, len, verbose_level);
840
841 if (f_v) {
842 print_range(first - 10, len + 20, cout);
843 cout << "key=[" << i0 << ", " << i1 << ", " << i2 << ", " << i3 << "]" << endl;
844 cout << "first=" << first << " len=" << len << endl;
845 }
846
847 if (len > 1) {
848 print_all(cout);
849 cout << "btree::search_unique_int4_int4_int4_int4() WARNING: element is not unique, returning -1" << endl;
850 cout << "key=[" << i0 << ", " << i1 << ", " << i2 << ", " << i3 << "]" << endl;
851 cout << "first=" << first << " len=" << len << endl;
852 exit(1);
853 }
854 if (len == 0) {
855 return -1;
856 }
857 return first;
858}
859
860int btree::search_datref_of_unique_int4(int i, int verbose_level)
861{
862 int no = search_unique_int4(i, verbose_level);
863 if (no == -1) {
864 cout << "btree::search_unique_int4() no == -1, cannot determine element" << endl;
865 exit(1);
866 }
867 KEYTYPE key;
868 DATATYPE data;
869
870 ith(no, &key, &data, verbose_level - 1);
871 return data.datref;
872}
873
875{
876 int no = search_unique_int4(i, verbose_level);
877 if (no == -1) {
878 return -1;
879 }
880 KEYTYPE key;
881 DATATYPE data;
882
883 ith(no, &key, &data, verbose_level - 1);
884 return data.datref;
885}
886
888// returns -1 if the btree is empty,
889// otherwise the int4 value of the key
890// of the last (highest) element in the btree.
891{
892 int len;
893 KEYTYPE key;
894 DATATYPE data;
895 int verbose_level = 0;
896
897 len = length(verbose_level);
898 if (len == 0) {
899 return -1;
900 }
901 ith(len - 1, &key, &data, verbose_level);
902 // cout << i << " : ";
903 // key_print(key.c, ost);
904 // cout << endl;
905 char *p_key = key.c;
906 int_4 i;
907 bt_key_get_int4(&p_key, i);
908 return i;
909}
910
911void btree::get_datrefs(int first, int len, Vector& datrefs)
912{
913 KEYTYPE key;
914 DATATYPE data;
915 int verbose_level = 0;
916
917 datrefs.m_l_n(len);
918 for (int i = 0; i < len; i++) {
919 ith(first + i, &key, &data, verbose_level);
920 datrefs.m_ii(i, data.datref);
921 }
922}
923
924int btree::search(void *pSearchKey,
925 DATATYPE *pData, int *idx,
926 int key_depth,
927 int verbose_level)
928// returns true iff searchKey has been found.
929
930/* void pointer pSearchKey hier.
931 * pSearchKey wird nicht benutzt, nur an (*cmp_func)()
932 * durchgeschleift. Insbesondere kann pSearchKey
933 * auf laengere Daten als KEYTYPE zeigen.
934 * Anwendung: ein evtl. langer Suchstring,
935 * der nicht in einen KEYTYPE passen wuerde.
936 * Es wird zusatzlich mit pData->datref
937 * gesucht, sofern pData != NIL.
938 * idx enthaelt Nummer des gefundenen bzw des naechst
939 * kleineren Datensatzes.
940 * idx kann also auch -1 werden (nicht gefunden -
941 * vor dem 0-ten Datensatz) */
942{
943 int f_v = (verbose_level >= 1);
944 Buffer Buf;
945 int f_found;
946
947 if (f_v) {
948 cout << "btree::search Root()=" << Root() << endl;
949 }
950 if (!f_open()) {
951 cout << "btree::search() not open" << endl;
952 exit(1);
953 }
954 *idx = -1;
955 f_found = SearchBtree(Root(),
956 pSearchKey,
957 pData,
958 &Buf,
959 idx,
960 key_depth,
961 verbose_level);
962 if (f_v) {
963 cout << "btree::search done, f_found=" << f_found << endl;
964 }
965 return f_found;
966}
967
968int btree::SearchBtree(int page,
969 void *pSearchKey, DATATYPE *pData,
970 Buffer *Buf, int *idx, int key_depth,
971 int verbose_level)
972// returns true iff searchKey has been found.
973
974/* Sucht einen Schluessel in der Datenbank
975 * --
976 * KEYTYPE pSearchKey - Zu suchender Schluessel
977 * DATATYPE *pData - Zum Schluessel gehoerende Daten
978 * int *idx - Enthaelt Nummer des gefundenen bzw des naechst
979 * kleineren Datensatzes
980 * int *f_found - Gibt an, ob Daten gefunden wurden */
981{
982 int f_v = (verbose_level >= 1);
983 int f_vv = (verbose_level >= 2);
984 int x, f_found, f_found1, idx1;
985
986 if (f_v) {
987 cout << "btree::SearchBtree page=" << page << endl;
988 }
989 if (page == 0) {
990 f_found = FALSE;
991 }
992 else {
993 LoadPage(Buf, page, verbose_level - 1);
994 if (f_vv) {
995 cout << "calling SearchPage" << endl;
996 }
997 f_found = SearchPage(Buf,
998 pSearchKey, NULL,
999 idx, &x,
1000 key_depth,
1001 verbose_level);
1002 if (f_v) {
1003 cout << "SearchPage returns " << f_found << " with x=" << x << endl;
1004 }
1005 idx1 = *idx;
1006 f_found1 = f_found;
1007 if (f_found) {
1008 if (pData) {
1009 *pData = Buf->Page.Item[x].Data;
1010 }
1011 }
1012 f_found = SearchBtree(Buf->Page.Item[x].Ref,
1013 pSearchKey, pData,
1014 Buf, idx, key_depth,
1015 verbose_level);
1016 if (!f_found && f_found1) {
1017 if (pData) {
1018 LoadPage(Buf, page, verbose_level - 1);
1019 *pData = Buf->Page.Item[x].Data;
1020 }
1021 f_found = TRUE;
1022 *idx = idx1;
1023 }
1024#if 0
1025 if (*f_found) {
1026 if (FKpData) {
1027 *FKpData = FKBF->Page.Item[x].Data;
1028 }
1029 }
1030 else {
1031 if (SearchBtree(p,
1032 FKBF->Page.Item[x].Ref,
1033 idx, f_found) != OK) {
1034 return error("SearchBtree() error in SearchBtree()");
1035 }
1036 }
1037#endif
1038 }
1039 if (f_v) {
1040 cout << "btree::SearchBtree page=" << page << " done, f_found=" << f_found << endl;
1041 }
1042 return f_found;
1043}
1044
1046 void *pSearchKey, DATATYPE *pSearchData,
1047 int *cur, int *x, int key_depth,
1048 int verbose_level)
1049// binary search within one page.
1050// returns true if the key searched for has been found, false otherwise
1051// in case that the key has been found,
1052// x contains the position of that element.
1053// Otherwise, x contains the position of the next smaller element
1054
1055
1056
1057/* Fuehrt binaere Suche innerhalb einer Seite aus.
1058 * --
1059 * Buffer *BF - zu untersuchende Seite.
1060 * KEYTYPE *SearchKey - Zu suchender Schluessel.
1061 * DATATYPE *pSearchData - optional, nur datref verwendet.
1062 * Bei gleichen Schluesseln werden
1063 * zusaetzlich die datref's verglichen.
1064 * int *x - Gibt Position an, falls Suche
1065 * erfolgreich. Ansonsten naechst
1066 * kleinerers Element.
1067 * x kann also auch null werden.
1068 * int *Found - Gibt an, ob Schluessel gefunden.
1069 *
1070 * Es wird aufgerufen:
1071 * WORD (*cmp_func)(void *key1, void *key2, int *res);
1072 * Key1 stammt aus der Datenbank, key2 ist der durchgeschleifte,
1073 * zu suchende Schluessel.
1074 * Ergebnis:
1075 * res < 0: key1 < key2
1076 * res == 0: key1 == key2
1077 * res > 0: key1 > key2
1078 * Bei gleichen Schluesseln werden intern noch die datref's
1079 * verglichen, sofern pSearchData gesetzt ist.
1080 * Bei gleichen Schluesseln (und evtl. gleichen datref's)
1081 * wird der letzte Eintrag gesucht und zurueckgegeben.
1082 * *cur wird erhoeht um die Childs Zaehler auf dieser Seite
1083 * (incl. 0-tem Eintrag) bis unmittelbar vor dem gefundenen
1084 * Datensatz, und dann + 1, so dass cur die aktuelle
1085 * Datensatznummer enthaelt, wenn es vorher im Suchbaum
1086 * schon mitgefuehrt wurde. */
1087{
1088 int f_v = (verbose_level >= 1);
1089 int f_vv = (verbose_level >= 2);
1090 ItemTyp *item = NULL;
1091 uint_4 searchdatref = 0;
1092 int childs;
1093 int r, l, i;
1094 int res;
1095 int f_found = FALSE;
1096
1097 if (f_v) {
1098 cout << "btree::SearchPage" << endl;
1099 }
1100 if (f_vv) {
1101 cout << "page:" << endl;
1102 page_print(buffer, cout);
1103 }
1104 if (pSearchData != NULL) {
1105 searchdatref = pSearchData->datref;
1106 }
1107 l = 0;
1108 r = buffer->Page.NumItems + 1;
1109 while (l + 1 < r) {
1110 *x = ((l + r) >> 1);
1111 item = &buffer->Page.Item[*x];
1112
1113 if (f_vv) {
1114 cout << "btree::SearchPage()|l = " << l << " *x = " << *x << " r = " << r << endl;
1115 item_print(item, *x, cout);
1116 }
1117 res = bt_key_compare(
1118 item->Key.c,
1119 (char *) pSearchKey,
1120 key(),
1121 key_depth);
1122 if (res == 0) {
1123 /* wenn pSearchData gesetzt,
1124 * dann bei gleichen Schluesseln
1125 * Suche nach datref */
1126 if (pSearchData != NULL) {
1127 if (item->Data.datref > searchdatref) {
1128 res = 1;
1129 }
1130 else if (item->Data.datref < searchdatref) {
1131 res = -1;
1132 }
1133 }
1134 }
1135 if (res == 0) {
1136 f_found = TRUE;
1137 l = *x;
1138 }
1139 else {
1140 if (res > 0) { /* Page.Item[].Key > *pSearchKey */
1141 r = *x;
1142 }
1143 else {
1144 if (f_found) {
1145 cout << "SearchPage() not ascending" << endl;
1146 exit(1);
1147 }
1148 l = *x;
1149 }
1150 }
1151 }
1152 *x = l;
1153 item = buffer->Page.Item;
1154 for (i = 0; i < *x; i++) {
1155 childs = item[i].Childs;
1156 *cur += childs;
1157 *cur += 1;
1158 }
1159 if (f_v) {
1160 cout << "btree::SearchPage done, f_found=" << f_found << endl;
1161 }
1162 return f_found;
1163}
1164
1165int btree::length(int verbose_level)
1166{
1167 int f_v = (verbose_level >= 1);
1168 int l;
1169 int j, pagelen;
1170 //Buffer *Root_BF;
1171 Buffer *BF;
1172
1173 if (f_v) {
1174 cout << "btree::length" << endl;
1175 }
1176 if (!f_open()) {
1177 cout << "btree::length() not open" << endl;
1178 exit(1);
1179 }
1180#if 0
1181 Root_BF = RootBF + buf_idx();
1182 l = 0;
1183 pagelen = Root_BF->Page.NumItems;
1184 // cout << "root page length = " << pagelen << endl;
1185 for (j = 0; j <= pagelen; j++) { /* mit nulltem Index ! */
1186 l += Root_BF->Page.Item[j].Childs;
1187 }
1188 l += pagelen;
1189#else
1190 BF = new Buffer;
1191
1192 if (f_v) {
1193 cout << "loading root page " << Root() << endl;
1194 }
1195 LoadPage(BF, Root(), verbose_level - 1);
1196 l = 0;
1197 pagelen = BF->Page.NumItems;
1198 // cout << "root page length = " << pagelen << endl;
1199 for (j = 0; j <= pagelen; j++) { /* mit nulltem Index ! */
1200 l += BF->Page.Item[j].Childs;
1201 }
1202 l += pagelen;
1203
1204 delete BF;
1205#endif
1206 return l;
1207}
1208
1209void btree::ith(int l,
1210 KEYTYPE *key, DATATYPE *data, int verbose_level)
1211/* key muss auf einen ganzen KEYTYPE zeigen,
1212 * da der gesamte keycarrier mittels struct-
1213 * zuweisung kopiert wird. */
1214{
1215 int f_v = (verbose_level >= 1);
1216 int cur, page, ref;
1217 int i, f_found;
1218 Buffer *buffer;
1219
1220 if (f_v) {
1221 cout << "btree::ith searching for entry " << l << endl;
1222 }
1223 if (!f_open()) {
1224 cout << "btree::ith() not open" << endl;
1225 exit(1);
1226 }
1227
1228 buffer = new Buffer;
1229
1230 page = Root();
1231 cur = 0;
1232 while (TRUE) {
1233 LoadPage(buffer, page, verbose_level - 1);
1234 if (f_v) {
1235 cout << "btree::ith loaded page = " << page << endl;
1236 page_print(buffer, cout);
1237 }
1238
1239 f_found = page_i_th(l, buffer, &cur, &i, verbose_level);
1240
1241 if (f_found) {
1242 if (f_v) {
1243 cout << "found in " << i << endl;
1244 }
1245 *key = buffer->Page.Item[i].Key;
1246 *data = buffer->Page.Item[i].Data;
1247 break;
1248 }
1249 if (f_v) {
1250 cout << "not found" << endl;
1251 }
1252 ref = buffer->Page.Item[i].Ref;
1253 if (ref == 0) {
1254 cout << "btree::ith ref == 0" << endl;
1255 exit(1);
1256 }
1257 page = ref;
1258 }
1259 delete buffer;
1260 if (f_v) {
1261 cout << "btree::ith() done" << endl;
1262 }
1263}
1264
1266 Buffer *buffer,
1267 int *cur, int *i,
1268 int verbose_level)
1269// returns true iff element could be found
1270{
1271 int f_v = (verbose_level >= 1);
1272 int childs;
1273 int page_len, j;
1274
1275 if (f_v) {
1276 cout << "btree::page_i_th looking for entry " << l << endl;
1277 }
1278 page_len = buffer->Page.NumItems;
1279 for (j = 0; j <= page_len; j++) {
1280 childs = buffer->Page.Item[j].Childs;
1281 if (*cur + childs > l) {
1282 *i = j;
1283 return FALSE;
1284 }
1285 if (*cur + childs == l) {
1286 if (j == page_len) {
1287 cout << "btree::page_i_th() j == page_len" << endl;
1288 page_print(buffer, cout);
1289 exit(1);
1290 }
1291 /* gefunden: (in j + 1) */
1292 *i = j + 1;
1293 return TRUE;
1294 }
1295 /* naechster Zweig: */
1296 *cur += childs + 1;
1297 }
1298 cout << "btree::page_i_th() not found" << endl;
1299 exit(1);
1300}
1301
1302
1303static KEYTYPE *IKpKey;
1304static DATATYPE *IKpData;
1305static Buffer *IKBF;
1306static int IKFound;
1307static int IKRisen;
1308static int f_keyadded;
1309
1311 DATATYPE *pData, int verbose_level)
1312/* Fuegt einen Schluessel in die Datenbank ein. Wenn
1313 * der Schluessel schon existiert, werden nur die Daten
1314 * ('Data') aktualisiert
1315 * --
1316 * KEYTYPE Key - Einzufuegender Schluessel
1317 * DATATYPE Data - Die zum Schluessel gehoerenden Daten */
1318{
1319 int f_v = (verbose_level >= 1);
1320 int RootSplit;
1321 ItemTyp RootItem;
1322 Buffer *NewRoot = NULL;
1323 Buffer *BF1 = NULL;
1324 int NewNeighbourChilds, new_page_num;
1325
1326 if (f_v) {
1327 cout << "btree::insert_key key=";
1328 key_print(pKey->c, cout);
1329 cout << endl;
1330 }
1331 if (!f_open()) {
1332 cout << "btree::insert_key() file not open" << endl;
1333 exit(1);
1334 }
1335 NewRoot = new Buffer;
1336 BF1 = new Buffer;
1337 fill_char((char *)NewRoot, sizeof(Buffer), 0);
1338 fill_char((char *)BF1, sizeof(Buffer), 0);
1339 f_keyadded = FALSE;
1340 IKpKey = pKey;
1341 IKpData = pData;
1342 RootSplit = FALSE;
1343 IKBF = BF1;
1344 if (f_v) {
1345 cout << "btree::insert_key: calling Update() Root=" << Root() << endl;
1346 }
1347
1348 Update(Root(),
1349 &RootSplit,
1350 &RootItem,
1351 &NewNeighbourChilds,
1352 verbose_level);
1353
1354 if (f_v) {
1355 if (RootSplit) {
1356 cout << "btree::insert_key RootSplit" << endl;
1357 }
1358 else {
1359 cout << "btree::insert_key not RootSplit" << endl;
1360 }
1361 }
1362 if (RootSplit) {
1363 if (f_v) {
1364 cout << "btree::insert_key RootSplit Item[1]=";
1365 key_print(RootItem.Key.c, cout);
1366 cout << endl;
1367 }
1368 new_page_num = AllocateRec(verbose_level);
1369 NewRoot->PageNum = (int_4) new_page_num;
1370 if (f_v) {
1371 cout << "btree::insert_key: RootSplit, NewRoot->PageNum = " << NewRoot->PageNum << endl;
1372 }
1373
1374 NewRoot->Page.NumItems = 1;
1375 NewRoot->Page.Item[0].Ref = (int_4) Root();
1376 NewRoot->Page.Item[0].Childs = (int_4) NewNeighbourChilds;
1377 NewRoot->Page.Item[1] = RootItem;
1378
1379 Root() = NewRoot->PageNum;
1380 if (f_v) {
1381 cout << "btree::insert_key Root=" << Root() << endl;
1382 page_print(NewRoot, cout);
1383 }
1384
1385
1386 if (f_v) {
1387 cout << "saving the new root" << endl;
1388 }
1389 SavePage(NewRoot, verbose_level - 1);
1390 //Root_BF = RootBF + buf_idx();
1391 //*Root_BF = *NewRoot;
1392#ifdef WRITE_INFO_ONLY_AT_END
1393#else
1394 WriteInfo(verbose_level);
1395#endif
1396 }
1397 delete NewRoot;
1398 delete BF1;
1399 IKBF = NULL;
1400 if (f_v) {
1401 cout << "btree::insert_key done" << endl;
1402 }
1403}
1404
1405void btree::Update(int Node, int *Rise,
1406 ItemTyp *RisenItem, int *RisenNeighbourChilds,
1407 int verbose_level)
1408/* Einfuegen in den Zweig Node.
1409 * RisenNeighbourChilds nur gesetzt, wenn Rise TRUE ist. */
1410{
1411 int f_v = (verbose_level >= 1);
1412 int x, idx, z;
1413
1414 if (f_v) {
1415 cout << "Update() in page " << Node << endl;
1416 }
1417 if (Node == 0) {
1418 /* Auf Blattebene angekommen wird von update()
1419 * eingefuegt als wenn ein RisenItem eingefuegt
1420 * werden muesste. Deswegen wird hier diese
1421 * Situation vorbereitet. */
1422 *Rise = TRUE;
1423 *RisenNeighbourChilds = 0;
1424 /* Nachbar darf ebenfalls keine Nachfolger haben */
1425 RisenItem->Key = *IKpKey;
1426 RisenItem->Data = *IKpData;
1427 RisenItem->Ref = 0;
1428 RisenItem->Childs = 0;
1429 f_keyadded = TRUE;
1430 return;
1431 }
1432 if (f_v) {
1433 cout << "Update() loading page " << Node << endl;
1434 }
1435 LoadPage(IKBF, Node, verbose_level);
1436
1437 if (f_v) {
1438 cout << "Update() searching in page " << Node << endl;
1439 }
1440 IKFound = SearchPage(IKBF,
1441 (void *)IKpKey, IKpData,
1442 &idx, &x, 0,
1443 verbose_level - 1);
1444 if (f_v) {
1445 if (IKFound) {
1446 cout << "key found at x=" << x << endl;
1447 }
1448 else {
1449 cout << "key not found, x=" << x << endl;
1450 }
1451 }
1452 if (IKFound && !f_duplicatekeys()) {
1453 if (f_v) {
1454 cout << "duplicate keys not allowed, we simply overwrite the Data" << endl;
1455 }
1456 IKBF->Page.Item[x].Data = *IKpData;
1457 SavePage(IKBF, verbose_level - 1);
1458 /* keine doppelten Schluessel erlaubt */
1459 /* Rise bleibt unveraendert FALSE */
1460 return;
1461 }
1462 /* Einfuegen in den Zweig von x: */
1463 IKRisen = FALSE;
1464 if (f_v) {
1465 cout << "Update() in page " << Node << " calling update in branch x=" << x << endl;
1466 }
1467 Update(IKBF->Page.Item[x].Ref,
1468 &IKRisen,
1469 RisenItem, RisenNeighbourChilds,
1470 verbose_level);
1471 if (f_v) {
1472 cout << "Update() loading page " << Node << endl;
1473 }
1474 /* Neuladen der Seite, da der Buffer in der Rekursion
1475 * benutzt wird. */
1476 LoadPage(IKBF, Node, verbose_level - 1);
1477 if (f_v) {
1478 page_print(IKBF, cout);
1479 }
1480 if (IKRisen) {
1481 if (f_v) {
1482 cout << "Update() in page " << Node << " IKRisen Item[" << x << "]=";
1483 key_print(RisenItem->Key.c, cout);
1484 cout << endl;
1485 }
1486 /* RisenItem muss nach x eingefuegt werden: */
1487 IKBF->Page.Item[x].Childs = (int_4) *RisenNeighbourChilds;
1488 /* Nach Seiten-Split hat der linke Nachbar weniger
1489 * Nachfolger */
1490 if (IKBF->Page.NumItems < BTREEMAXPAGESIZE) {
1491 // insert on this page:
1492 IKBF->Page.NumItems++;
1493 for (z = IKBF->Page.NumItems - 1; z >= x + 1; z--) {
1494 /* IKBF->Page.Item[z + 1] = IKBF->Page.Item[z]; */
1495 bt_item_copy(&IKBF->Page.Item[z], &IKBF->Page.Item[z + 1]);
1496 }
1497 /* IKBF->Page.Item[x + 1] = *RisenItem; */
1498 bt_item_copy(RisenItem, &IKBF->Page.Item[x + 1]);
1499 *Rise = FALSE;
1500 }
1501 else {
1502 // page full, split:
1503 if (f_v) {
1504 cout << "btree::Update() page is full, calling Split(), x = " << x << endl;
1505 }
1506 *RisenNeighbourChilds = 0; /* redundant */
1507
1508 Split(IKBF,
1509 RisenItem, x,
1510 RisenNeighbourChilds,
1511 verbose_level);
1512
1513 *Rise = TRUE;
1514 }
1515 }
1516 else { /* IKRisen == FALSE */
1517 if (f_keyadded) {
1518 IKBF->Page.Item[x].Childs++;
1519 }
1520 }
1521 if (f_v) {
1522 cout << "btree::Update() saving old page " << IKBF->PageNum << endl;
1523 }
1524 SavePage(IKBF, verbose_level - 1);
1525}
1526
1527
1528void btree::Split(Buffer *BF, ItemTyp *Item,
1529 int x, int *RisenNeighbourChilds,
1530 int verbose_level)
1531/* Fuegt Item in volle Seite BF nach position x ein.
1532 * Die uebervolle Seite wird zerlegt, die 2. Haelfte in
1533 * eine neue Seite kopiert. Das mittlere Element wird
1534 * angehoben und bekommt die neue Seite als Nachfolger.
1535 * Der alte Nachfolger des mittleren Elements wird in die
1536 * neue Seite an 0ter Position eingehaengt.
1537 * RisenNeighbourChilds wird als Summe der Datensatze der
1538 * verkleinerten Seite berechnet und muss von der auf-
1539 * rufenden Funktion links neben Item eingetragen werden.
1540 * Die neu generierte Seite wird abgespeichert; die ver-
1541 * kleinerte muss von der rufenden Funktion gesichert
1542 * werden. */
1543{
1544 int f_v = (verbose_level >= 1);
1545 ItemTyp SplitItem;
1546 Buffer *SplitBF = NULL;
1547 int sum1, sum2;
1548 int z;
1549 int new_page_num;
1550
1551 if (f_v) {
1552 cout << "Split page=" << BF->PageNum << " at x=" << x << endl;
1553 }
1554 if (f_v) {
1555 cout << "btree::Split() original page:" << endl;
1556 page_print(BF, cout);
1557 }
1558 SplitBF = new Buffer;
1559 fill_char((char *)SplitBF, sizeof(Buffer), 0);
1560 new_page_num = AllocateRec(f_v);
1561 if (f_v) {
1562 cout << "Split new page=" << new_page_num << endl;
1563 }
1564 SplitBF->PageNum = (int_4) new_page_num;
1565 if (x < BTREEHALFPAGESIZE) {
1566 SplitItem = BF->Page.Item[BTREEHALFPAGESIZE];
1567 for (z = BTREEHALFPAGESIZE - 1; z >= x + 1; z--) {
1568 BF->Page.Item[z + 1] = BF->Page.Item[z];
1569 }
1570 BF->Page.Item[x + 1] = *Item;
1571 }
1572 else {
1573 if (x > BTREEHALFPAGESIZE) {
1574 SplitItem = BF->Page.Item[BTREEHALFPAGESIZE + 1];
1575 for (z = BTREEHALFPAGESIZE + 2; z <= x; z++) {
1576 BF->Page.Item[z - 1] = BF->Page.Item[z];
1577 }
1578 BF->Page.Item[x] = *Item;
1579 }
1580 else {
1581 SplitItem = *Item;
1582 }
1583 }
1584 SplitBF->Page.Item[0].Ref = SplitItem.Ref;
1585 SplitBF->Page.Item[0].Childs = sum2 = SplitItem.Childs;
1586 sum1 = BF->Page.Item[0].Childs;
1587 for (z = 1; z <= BTREEHALFPAGESIZE; z++) {
1588 SplitBF->Page.Item[z] = BF->Page.Item[BTREEHALFPAGESIZE + z];
1589 sum2 += SplitBF->Page.Item[z].Childs;
1590 sum1 += BF->Page.Item[z].Childs;
1591 }
1592 sum1 += BTREEHALFPAGESIZE;
1593 sum2 += BTREEHALFPAGESIZE;
1595 SplitBF->Page.NumItems = BTREEHALFPAGESIZE;
1596 SplitItem.Ref = SplitBF->PageNum;
1597 SplitItem.Childs = (int_4) sum2;
1598 *Item = SplitItem;
1599
1600 if (f_v) {
1601 cout << "btree::Split() after split:" << endl;
1602 cout << "original page: " << BF->PageNum << endl;
1603 page_print(BF, cout);
1604 cout << "new page: " << SplitBF->PageNum << endl;
1605 page_print(SplitBF, cout);
1606 }
1607
1608 if (f_v) {
1609 cout << "btree::Split() saving new page:" << endl;
1610 }
1611 SavePage(SplitBF, verbose_level - 1);
1612
1613 *RisenNeighbourChilds = sum1;
1614 if (f_v) {
1615 cout << "SplitItem:";
1616 key_print(Item->Key.c, cout);
1617 cout << endl;
1618 }
1619
1620 delete SplitBF;
1621}
1622
1623static int DKFound;
1624static int DKidx, DKcur;
1625/*static Buffer *DKBF;*/
1626static int f_keydeleted;
1627
1628void btree::delete_ith(int idx, int verbose_level)
1629/* Loescht einen Datensatz in der Datenbank
1630 * --
1631 * DelKey - Zu loeschender Schluessel */
1632{
1633 int f_v = (verbose_level >= 1);
1634 int z, z2;
1635 int Underflow;
1636 /* Buffer BF; */
1637 Buffer *Root_BF;
1638
1639 if (f_v) {
1640 cout << "btree::delete_ith idx=" << idx << endl;
1641 }
1642 if (!f_open()) {
1643 cout << "btree::delete_ith() file not open" << endl;
1644 exit(1);
1645 }
1646
1647
1648
1649 DKidx = idx;
1650 DKcur = 0;
1651 /* DKBF = &BF; */
1652 f_keydeleted = FALSE;
1653 Delete(Root(), Underflow, verbose_level);
1654#if 0
1655 Root_BF = RootBF + buf_idx();
1656#else
1657 Root_BF = new Buffer;
1658#endif
1659 if (f_v) {
1660 cout << "loading root page " << Root() << endl;
1661 }
1662 LoadPage(Root_BF, Root(), verbose_level - 1);
1663
1664 if (Underflow && Root_BF->Page.NumItems == 0) {
1665 z = Root();
1666 z2 = Root_BF->Page.Item[0].Ref;
1667 if (z2 == 0) { /* leere Datenbank */
1668#ifdef WRITE_INFO_ONLY_AT_END
1669#else
1670 WriteInfo(FALSE /* f_v */);
1671#endif
1672 return;
1673 }
1674 LoadPage(Root_BF, z2, verbose_level - 1);
1675
1676 ReleaseRec(z);
1677 Root() = Root_BF->PageNum; // !!!
1678
1679#ifdef WRITE_INFO_ONLY_AT_END
1680#else
1681 WriteInfo(FALSE /* f_v */);
1682#endif
1683 }
1684 if (f_v) {
1685 cout << "btree::delete_ith done" << endl;
1686 }
1687}
1688
1689void btree::Delete(int Node, int& Underflow, int verbose_level)
1690{
1691 int f_v = (verbose_level >= 1);
1692 int x, y, z;
1693 Buffer *DKBF = NULL;
1694
1695 if (f_v) {
1696 cout << "btree::Delete Node=" << Node << endl;
1697 }
1698 if (Node == 0) {
1699 Underflow = FALSE;
1700 return;
1701 }
1702 DKBF = new Buffer;
1703 fill_char((char *) DKBF, sizeof(Buffer), 0);
1704 LoadPage(DKBF, Node, verbose_level - 1);
1705
1706 /* SearchPage(p, DKBF, DKpDelKey, NIL, &idx, &x, &DKFound);*/
1707
1708 DKFound = page_i_th(DKidx, DKBF, &DKcur, &x, verbose_level);
1709 if (DKFound) {
1710 y = DKBF->Page.Item[x - 1].Ref;
1711 if (y == 0) {
1712 DKBF->Page.NumItems--;
1713 Underflow = DKBF->Page.NumItems < BTREEHALFPAGESIZE;
1714 for (z = x; z <= DKBF->Page.NumItems; z++) {
1715 DKBF->Page.Item[z] = DKBF->Page.Item[z + 1];
1716 }
1717 SavePage(DKBF, verbose_level - 1);
1718 f_keydeleted = TRUE;
1719 }
1720 else {
1721 FindGreatest(y,
1722 Underflow, DKBF, x, verbose_level);
1723
1724 if (f_keydeleted) {
1725 DKBF->Page.Item[x - 1].Childs--;
1726 SavePage(DKBF, verbose_level - 1);
1727 }
1728 if (Underflow) {
1729 Compensate(Node,
1730 y,
1731 x - 1,
1732 Underflow,
1733 verbose_level);
1734 }
1735 }
1736 }
1737 else {
1738 y = DKBF->Page.Item[x].Ref;
1739
1740 Delete(y, Underflow, verbose_level);
1741
1742 if (f_keydeleted) {
1743 LoadPage(DKBF, Node, verbose_level - 1);
1744 DKBF->Page.Item[x].Childs--;
1745 SavePage(DKBF, verbose_level - 1);
1746 }
1747 if (Underflow) {
1748 Compensate(Node,
1749 y,
1750 x,
1751 Underflow,
1752 verbose_level);
1753 }
1754 }
1755 delete DKBF;
1756 if (f_v) {
1757 cout << "btree::Delete done" << endl;
1758 }
1759}
1760
1761void btree::FindGreatest(int Node1,
1762 int& Underflow, Buffer *DKBF, int x,
1763 int verbose_level)
1764{
1765 int f_v = (verbose_level >= 1);
1766 int Node2;
1767 int NumBF;
1768 Buffer *buf = NULL;
1769 Buffer *Root_BF;
1770
1771 if (f_v) {
1772 cout << "btree::FindGreatest Node1=" << Node1 << " x=" << x << endl;
1773 }
1774 buf = new Buffer;
1775 fill_char((char *)buf, sizeof(Buffer), 0);
1776 LoadPage(buf, Node1, verbose_level - 1);
1777 NumBF = buf->Page.NumItems;
1778 Node2 = buf->Page.Item[NumBF].Ref;
1779 if (Node2 != 0) {
1780 FindGreatest(Node2, Underflow, DKBF, x, verbose_level);
1781 if (f_keydeleted) {
1782 LoadPage(buf, Node1, verbose_level - 1);
1783 buf->Page.Item[NumBF].Childs--;
1784 SavePage(buf, verbose_level - 1);
1785 }
1786 if (Underflow) {
1787 Compensate(Node1, Node2,
1788 NumBF, Underflow,
1789 verbose_level);
1790 }
1791 }
1792 else {
1793 DKBF->Page.Item[x].Key = buf->Page.Item[NumBF].Key;
1794 DKBF->Page.Item[x].Data = buf->Page.Item[NumBF].Data;
1795 f_keydeleted = TRUE;
1796 if (DKBF->PageNum == Root()) {
1797 Root_BF = RootBF + buf_idx();
1798 *Root_BF = *DKBF;
1799 }
1800 NumBF--;
1801 Underflow = (NumBF < BTREEHALFPAGESIZE);
1802 buf->Page.NumItems = (int_4) NumBF;
1803 SavePage(buf, verbose_level - 1);
1804 }
1805 delete buf;
1806 if (f_v) {
1807 cout << "btree::FindGreatest done" << endl;
1808 }
1809}
1810
1811void btree::Compensate(int Precedent,
1812 int Node, int Path, int& Underflow,
1813 int verbose_level)
1814{
1815 int f_v = (verbose_level >= 1);
1816 int Neighbour;
1817 int NumBF2, NumBF3;
1818 int x, z;
1819 int sum;
1820 Buffer *BF1 = NULL;
1821 Buffer *BF2 = NULL;
1822 Buffer *BF3 = NULL;
1823
1824 if (f_v) {
1825 cout << "btree::Compensate Precedent=" << Precedent << " Node=" << Node << endl;
1826 }
1827 BF1 = new Buffer;
1828 BF2 = new Buffer;
1829 BF3 = new Buffer;
1830 fill_char((char *)BF1, sizeof(Buffer), 0);
1831 fill_char((char *)BF2, sizeof(Buffer), 0);
1832 fill_char((char *)BF3, sizeof(Buffer), 0);
1833 LoadPage(BF1, Node, verbose_level - 1);
1834 LoadPage(BF3, Precedent, verbose_level - 1);
1835 NumBF3 = BF3->Page.NumItems;
1836 if (f_v) {
1837 cout << "Path=" << Path << endl;
1838 cout << "NumBF3=" << NumBF3 << endl;
1839 }
1840 if (Path < NumBF3) {
1841 if (f_v) {
1842 cout << "rightmost leave with neighbor to the right" << endl;
1843 cout << "Path=" << Path << endl;
1844 cout << "NumBF3=" << NumBF3 << endl;
1845 }
1846 /* Blatt nicht rechts aussen, dh. ein rechter
1847 * Nachbar existiert. */
1848 Neighbour = BF3->Page.Item[Path + 1].Ref;
1849 LoadPage(BF2, Neighbour, verbose_level - 1);
1850 NumBF2 = BF2->Page.NumItems;
1851 x = (NumBF2 + 1 - BTREEHALFPAGESIZE) / 2;
1852 BF1->Page.Item[BTREEHALFPAGESIZE].Key = BF3->Page.Item[Path + 1].Key;
1853 BF1->Page.Item[BTREEHALFPAGESIZE].Data = BF3->Page.Item[Path + 1].Data;
1854 BF1->Page.Item[BTREEHALFPAGESIZE].Ref = BF2->Page.Item[0].Ref;
1855 BF1->Page.Item[BTREEHALFPAGESIZE].Childs = sum = BF2->Page.Item[0].Childs;
1856 if (x > 0) {
1857 if (f_v) {
1858 cout << "case I with x=" << x << endl;
1859 }
1860 /*printf("Fall I x = %d\n", x);*/
1861 for (z = 1; z <= x - 1; z++) {
1862 BF1->Page.Item[BTREEHALFPAGESIZE + z] = BF2->Page.Item[z];
1863 sum += BF2->Page.Item[z].Childs;
1864 }
1865 sum += x;
1866 BF3->Page.Item[Path].Childs += sum;
1867 BF3->Page.Item[Path + 1].Childs -= sum;
1868 BF3->Page.Item[Path + 1].Key = BF2->Page.Item[x].Key;
1869 BF3->Page.Item[Path + 1].Data = BF2->Page.Item[x].Data;
1870 BF2->Page.Item[0].Ref = BF2->Page.Item[x].Ref;
1871 BF2->Page.Item[0].Childs = BF2->Page.Item[x].Childs;
1872 NumBF2 = NumBF2 - x;
1873 for (z = 1; z <= NumBF2; z++) {
1874 BF2->Page.Item[z] = BF2->Page.Item[x + z];
1875 }
1876 BF2->Page.NumItems = (int_4) NumBF2;
1877 BF1->Page.NumItems = (int_4) (BTREEHALFPAGESIZE + x - 1);
1878 SavePage(BF1, verbose_level - 1);
1879 SavePage(BF2, verbose_level - 1);
1880 SavePage(BF3, verbose_level - 1);
1881 Underflow = FALSE;
1882 }
1883 else {
1884 if (f_v) {
1885 cout << "case II with x=" << x << endl;
1886 }
1887 /*printf("Fall II x = %d\n", x);*/
1888 BF3->Page.Item[Path].Childs += BF3->Page.Item[Path + 1].Childs + 1;
1889 for (z = 1; z <= BTREEHALFPAGESIZE; z++) {
1890 BF1->Page.Item[BTREEHALFPAGESIZE + z] = BF2->Page.Item[z];
1891 }
1892 for (z = Path + 1; z <= NumBF3 - 1; z++) {
1893 BF3->Page.Item[z] = BF3->Page.Item[z + 1];
1894 }
1896 BF3->Page.NumItems = (int_4) NumBF3 - 1L;
1897 Underflow = (NumBF3 <= BTREEHALFPAGESIZE);
1898 SavePage(BF1, verbose_level - 1);
1899 SavePage(BF3, verbose_level - 1);
1900 ReleaseRec(Neighbour);
1901 }
1902 }
1903 else {
1904 if (f_v) {
1905 cout << "rightmost leave with neighbor to the left" << endl;
1906 }
1907 /* Blatt rechts aussen; Nachbar links */
1908 Neighbour = BF3->Page.Item[Path - 1].Ref;
1909 LoadPage(BF2, Neighbour, verbose_level - 1);
1910 NumBF2 = BF2->Page.NumItems;
1911 x = (NumBF2 + 1 - BTREEHALFPAGESIZE) / 2;
1912 if (x > 0) {
1913 if (f_v) {
1914 cout << "case III with x=" << x << endl;
1915 }
1916 /*printf("Fall III x = %d\n", x);*/
1917 for (z = BTREEHALFPAGESIZE - 1L; z >= 1; z--) {
1918 BF1->Page.Item[z + x] = BF1->Page.Item[z];
1919 }
1920 BF1->Page.Item[x].Key = BF3->Page.Item[Path].Key;
1921 BF1->Page.Item[x].Data = BF3->Page.Item[Path].Data;
1922 BF1->Page.Item[x].Ref = BF1->Page.Item[0].Ref;
1923 BF1->Page.Item[x].Childs = BF1->Page.Item[0].Childs;
1924 NumBF2 = NumBF2 - x;
1925 BF1->Page.Item[0].Ref = BF2->Page.Item[NumBF2 + 1].Ref;
1926 BF1->Page.Item[0].Childs = sum =
1927 BF2->Page.Item[NumBF2 + 1].Childs;
1928 for (z = x - 1; z >= 1; z--) {
1929 BF1->Page.Item[z] = BF2->Page.Item[NumBF2 + 1 + z];
1930 sum += BF2->Page.Item[NumBF2 + 1 + z].Childs;
1931 }
1932 sum += x;
1933 BF3->Page.Item[Path].Key = BF2->Page.Item[NumBF2 + 1].Key;
1934 BF3->Page.Item[Path].Data = BF2->Page.Item[NumBF2 + 1].Data;
1935 BF3->Page.Item[Path].Childs += sum;
1936 BF3->Page.Item[Path - 1].Childs -= sum;
1937 BF2->Page.NumItems = (int_4) NumBF2;
1938 BF1->Page.NumItems = (int_4) (x + BTREEHALFPAGESIZE - 1L);
1939 SavePage(BF1, verbose_level - 1);
1940 SavePage(BF2, verbose_level - 1);
1941 SavePage(BF3, verbose_level - 1);
1942 Underflow = FALSE;
1943 }
1944 else {
1945 if (f_v) {
1946 cout << "case IV with x=" << x << endl;
1947 }
1948 /*printf("Fall IV x = %d\n", x);*/
1949 BF2->Page.Item[NumBF2 + 1].Key = BF3->Page.Item[Path].Key;
1950 BF2->Page.Item[NumBF2 + 1].Data = BF3->Page.Item[Path].Data;
1951 BF2->Page.Item[NumBF2 + 1].Ref = BF1->Page.Item[0].Ref;
1952 BF2->Page.Item[NumBF2 + 1].Childs = BF1->Page.Item[0].Childs;
1953 for (z = 1; z <= BTREEHALFPAGESIZE - 1; z++) {
1954 BF2->Page.Item[NumBF2 + 1 + z] = BF1->Page.Item[z];
1955 }
1957 BF3->Page.NumItems = (int_4) NumBF3 - 1;
1958 BF3->Page.Item[Path - 1].Childs +=
1959 BF3->Page.Item[Path].Childs + 1;
1960 Underflow = (NumBF3 <= BTREEHALFPAGESIZE);
1961 SavePage(BF2, verbose_level - 1);
1962 SavePage(BF3, verbose_level - 1);
1963 ReleaseRec(Node);
1964 }
1965 }
1966 delete BF1;
1967 delete BF2;
1968 delete BF3;
1969 if (f_v) {
1970 cout << "btree::Compensate done" << endl;
1971 }
1972}
1973
1974void btree::print_all(ostream& ost)
1975{
1976 int verbose_level = 0;
1977
1978 int bt_len = length(verbose_level);
1979
1980 print_range(0, bt_len, ost);
1981}
1982
1983void btree::print_range(int first, int len, ostream& ost)
1984{
1985 int i, j, bt_len;
1986 KEYTYPE key;
1987 DATATYPE data;
1988 int verbose_level = 0;
1989
1990 bt_len = length(verbose_level);
1991 for (i = 0; i < len; i++) {
1992 j = first + i;
1993 if (j < 0) {
1994 continue;
1995 }
1996 if (j >= bt_len) {
1997 continue;
1998 }
1999 ith(j, &key, &data, verbose_level);
2000 cout << j << " : ";
2001 key_print(key.c, ost);
2002 cout << endl;
2003 }
2004}
2005
2006void btree::print_page(int x, ostream& ost)
2007{
2008 int y;
2009 Buffer BF;
2010 int verbose_level = 0;
2011
2012 if (x == 0) {
2013 return;
2014 }
2015 LoadPage(&BF, x, verbose_level);
2016 ost << "page " << x << ":\n";
2017 page_print(&BF, ost);
2018 for (y = 0; y <= BF.Page.NumItems; y++) {
2019 print_page(BF.Page.Item[y].Ref, ost);
2020 }
2021}
2022
2023void btree::page_print(Buffer *BF, ostream& ost)
2024{
2025 int i, len; //, childs, ref, datref, data_size;
2026 ItemTyp *item = NULL;
2027
2028 ost << "PageNum = " << BF->PageNum << endl;
2029 len = BF->Page.NumItems;
2030 ost << "BF->Page.NumItems = " << len << endl;
2031 for (i = 0; i <= len; i++) {
2032 // ostrstream s;
2033
2034 item = &BF->Page.Item[i];
2035
2036 item_print(item, i, ost);
2037
2038#if 0
2039 childs = item->Childs;
2040 ref = item->Ref;
2041 ost << "item " << i << ": Childs=" << childs << " Ref=" << ref;
2042 if (i != 0) {
2043 datref = item->Data.datref;
2044 data_size = item->Data.data_size;
2045 ost << " (" << datref << "/" << data_size << "): ";
2046 key_print(item->Key.c, ost);
2047 // bt_key_print(item->Key.c, key(), s);
2048 // s << ends;
2049 // ost << s;
2050 }
2051 ost << endl;
2052#endif
2053 }
2054 ost << endl;
2055}
2056
2057void btree::item_print(ItemTyp *item, int i, ostream& ost)
2058{
2059 int childs, ref, datref, data_size;
2060
2061 childs = item->Childs;
2062 ref = item->Ref;
2063
2064 ost << setw(3) << i << ": ";
2065
2066 if (i != 0) {
2067 key_print(item->Key.c, ost);
2068
2069 datref = item->Data.datref;
2070 data_size = item->Data.data_size;
2071 ost << " (" << setw(10) << datref
2072 << "/" << setw(6) << data_size << "): ";
2073 // bt_key_print(item->Key.c, key(), s);
2074 // s << ends;
2075 // ost << s;
2076 }
2077
2078 ost << "_{" << setw(8) << childs
2079 << "," << setw(8) << ref << "}" << endl; }
2080
2081
2082// #############################################################################
2083// global functions and low level functions
2084// #############################################################################
2085
2086
2088{
2089 int idx = fstream_table_get_free_entry();
2090 fstream *f = new fstream(filename().s(), ios::in | ios::out | ios::binary);
2091 fstream_table[idx] = f;
2092 fstream_table_used[idx] = TRUE;
2093 stream() = idx;
2094 f_open() = TRUE;
2095 // cout << "btree::file_open() file " << filename().s() << " opened" << endl;
2096}
2097
2099{
2100 hollerith cmd;
2101
2102 cmd.init("rm ");
2103 cmd.append(filename().s());
2104 system(cmd.s());
2105
2106 int idx = fstream_table_get_free_entry();
2107 {
2108 fstream *f = new fstream(filename().s(), ios::out | ios::binary);
2109 if (!*f) {
2110 cout << "btree::file_create() file " << filename().s() << " could not be created" << endl;
2111 exit(1);
2112 }
2113 f->close();
2114 delete f;
2115 }
2116 fstream *f = new fstream(filename().s(), ios::in | ios::out | ios::binary);
2117 if (!*f) {
2118 cout << "btree::file_create() file " << filename().s() << " could not be opened" << endl;
2119 exit(1);
2120 }
2121 fstream_table[idx] = f;
2122 fstream_table_used[idx] = TRUE;
2123 stream() = idx;
2124 f_open() = TRUE;
2125 // cout << "btree::file_create() file " << filename().s() << " created" << endl;
2126}
2127
2129{
2130 int idx = (int) stream();
2131 if (!fstream_table_used[idx]) {
2132 cout << "btree::file_close() !fstream_table_used[idx]" << endl;
2133 cout << "idx=" << idx << endl;
2134 exit(1);
2135 }
2136 delete fstream_table[idx];
2138 stream() = 0;
2139 f_open() = FALSE;
2140 // cout << "btree::file_close() file " << filename().s() << " closed" << endl;
2141}
2142
2143void btree::file_write(PageTyp *page, const char *message)
2144{
2145 if (!f_open()) {
2146 cout << "btree::file_write() file not open" << endl;
2147 exit(1);
2148 }
2149 int idx = (int) stream();
2150 //cout << "file_write idx=" << idx << " " << message << endl;
2151 if (!fstream_table_used[idx]) {
2152 cout << "btree::file_write() !fstream_table_used[idx]" << endl;
2153 cout << "idx=" << idx << endl;
2154 exit(1);
2155 }
2156 fstream_table[idx]->write((char *) page, sizeof(PageTyp));
2157}
2158
2159void btree::file_read(PageTyp *page, const char *message)
2160{
2161 if (!f_open()) {
2162 cout << "btree::file_read() file not open" << endl;
2163 exit(1);
2164 }
2165 int idx = (int) stream();
2166 //cout << "file_read idx=" << idx << " " << message << endl;
2167 if (!fstream_table_used[idx]) {
2168 cout << "btree::file_read() !fstream_table_used[idx]" << endl;
2169 cout << "idx=" << idx << endl;
2170 exit(1);
2171 }
2172 fstream_table[idx]->read((char *) page, sizeof(PageTyp));
2173}
2174
2175void btree::file_seek(int page_no)
2176{
2177 int offset;
2178
2179 //cout << "file_seek page " << page_no << endl;
2180 if (!f_open()) {
2181 cout << "btree::file_seek() file not open" << endl;
2182 exit(1);
2183 }
2184 offset = page_no * (int)sizeof(PageTyp);
2185 int idx = (int) stream();
2186 if (!fstream_table_used[idx]) {
2187 cout << "btree::file_seek() !fstream_table_used[idx]" << endl;
2188 cout << "idx=" << idx << endl;
2189 exit(1);
2190 }
2191 fstream_table[idx]->seekg(offset);
2192}
2193
2194
2195
2196static void bt_item_copy(ItemTyp *a, ItemTyp *b)
2197{
2198 int i, len;
2199 char *pca = (char *)a;
2200 char *pcb = (char *)b;
2201
2202 len = sizeof(ItemTyp);
2203 for (i = 0; i < len; i++)
2204 pcb[i] = pca[i];
2205}
2206
2207}}
2208
#define MAX_ROOT_BUF
Definition: btree.cpp:22
DISCRETA vector class for vectors of DISCRETA objects.
Definition: discreta.h:797
Vector & append(discreta_base &x)
Definition: vector.cpp:400
void m_ii(int i, int a)
Definition: discreta.h:824
void copyobject_to(discreta_base &x)
Definition: vector.cpp:72
DISCRETA class for databases.
Definition: discreta.h:1442
void init_string(int output_size, int field1, int field2)
Definition: bt_key.cpp:109
void init_int2(int field1, int field2)
Definition: bt_key.cpp:104
enum bt_key_kind & type()
Definition: discreta.h:1458
void init_int4(int field1, int field2)
Definition: bt_key.cpp:99
DISCRETA class for a database.
Definition: discreta.h:1672
void file_read(PageTyp *page, const char *message)
Definition: btree.cpp:2159
void page_print(Buffer *BF, std::ostream &ost)
Definition: btree.cpp:2023
void search_interval_int4_int4(int l0, int u0, int l1, int u1, int &first, int &len, int verbose_level)
Definition: btree.cpp:666
void Update(int Node, int *Rise, ItemTyp *RisenItem, int *RisenNeighbourChilds, int f_v)
Definition: btree.cpp:1405
void add_key_int4(int field1, int field2)
Definition: btree.cpp:241
void init(const char *file_name, int f_duplicatekeys, int btree_idx)
Definition: btree.cpp:221
int search(void *pSearchKey, DATATYPE *pData, int *idx, int key_depth, int verbose_level)
Definition: btree.cpp:924
btree & operator=(const discreta_base &x)
Definition: btree.cpp:166
int search_int4_int4(int data1, int data2, int &idx, int verbose_level)
Definition: btree.cpp:783
int search_datref_of_unique_int4(int i, int verbose_level)
Definition: btree.cpp:860
void print_all(std::ostream &ost)
Definition: btree.cpp:1974
void open(int verbose_level)
Definition: btree.cpp:311
int search_datref_of_unique_int4_if_there(int i, int verbose_level)
Definition: btree.cpp:874
void file_write(PageTyp *page, const char *message)
Definition: btree.cpp:2143
void ReadInfo(int verbose_level)
Definition: btree.cpp:388
void print_page(int x, std::ostream &ost)
Definition: btree.cpp:2006
void add_key_string(int output_size, int field1, int field2)
Definition: btree.cpp:257
int page_i_th(int l, Buffer *buffer, int *cur, int *i, int verbose_level)
Definition: btree.cpp:1265
void search_interval_int4_int4_int4(int l0, int u0, int l1, int u1, int l2, int u2, int &first, int &len, int verbose_level)
Definition: btree.cpp:702
void key_print(char *the_key, std::ostream &ost)
Definition: btree.cpp:270
int length(int verbose_level)
Definition: btree.cpp:1165
int SearchPage(Buffer *buffer, void *pSearchKey, DATATYPE *pSearchData, int *cur, int *x, int key_depth, int verbose_level)
Definition: btree.cpp:1045
void item_print(ItemTyp *item, int i, std::ostream &ost)
Definition: btree.cpp:2057
void create(int verbose_level)
Definition: btree.cpp:275
void close(int verbose_level)
Definition: btree.cpp:356
void SavePage(Buffer *BF, int verbose_level)
Definition: btree.cpp:585
void add_key_int2(int field1, int field2)
Definition: btree.cpp:249
void search_interval_int4_int4_int4_int4(int l0, int u0, int l1, int u1, int l2, int u2, int l3, int u3, int &first, int &len, int verbose_level)
Definition: btree.cpp:740
void Compensate(int Precedent, int Node, int Path, int &Underflow, int verbose_level)
Definition: btree.cpp:1811
void Split(Buffer *BF, ItemTyp *Item, int x, int *RisenNeighbourChilds, int verbose_level)
Definition: btree.cpp:1528
void delete_ith(int idx, int verbose_level)
Definition: btree.cpp:1628
void Delete(int Node, int &Underflow, int verbose_level)
Definition: btree.cpp:1689
void insert_key(KEYTYPE *pKey, DATATYPE *pData, int verbose_level)
Definition: btree.cpp:1310
int search_unique_int4_int4_int4_int4(int i0, int i1, int i2, int i3, int verbose_level)
Definition: btree.cpp:826
std::ostream & print(std::ostream &)
Definition: btree.cpp:213
void get_datrefs(int first, int len, Vector &datrefs)
Definition: btree.cpp:911
void copyobject_to(discreta_base &x)
Definition: btree.cpp:200
int search_string(discreta_base &key_op, int &pos, int verbose_level)
Definition: btree.cpp:620
void key_fill_in(char *the_key, Vector &the_object)
Definition: btree.cpp:265
void ith(int l, KEYTYPE *key, DATATYPE *data, int verbose_level)
Definition: btree.cpp:1209
void FindGreatest(int Node1, int &Underflow, Buffer *DKBF, int x, int verbose_level)
Definition: btree.cpp:1761
void LoadPage(Buffer *BF, int x, int verbose_level)
Definition: btree.cpp:533
void file_seek(int page_no)
Definition: btree.cpp:2175
int AllocateRec(int verbose_level)
Definition: btree.cpp:451
void search_interval_int4(int i_min, int i_max, int &first, int &len, int verbose_level)
Definition: btree.cpp:637
void WriteInfo(int verbose_level)
Definition: btree.cpp:417
int SearchBtree(int page, void *pSearchKey, DATATYPE *pData, Buffer *Buf, int *idx, int key_depth, int verbose_level)
Definition: btree.cpp:968
void print_range(int first, int len, std::ostream &ost)
Definition: btree.cpp:1983
int search_unique_int4(int i, int verbose_level)
Definition: btree.cpp:809
DISCRETA base class. All DISCRETA classes are derived from this class.
Definition: discreta.h:382
void copyobject(discreta_base &x)
Definition: base.cpp:194
DISCRETA string class.
Definition: discreta.h:626
DISCRETA integer class.
Definition: discreta.h:667
DISCRETA class for bulk storage.
Definition: discreta.h:1848
void allocate_rec(Buffer *BF, int buf_idx, int x, int verbose_level)
Definition: page_table.cpp:383
void save_page(Buffer *BF, int buf_idx, int verbose_level)
Definition: page_table.cpp:318
int load_page(Buffer *BF, int x, int buf_idx, int verbose_level)
Definition: page_table.cpp:357
void write_pages_to_file(btree *B, int buf_idx, int verbose_level)
Definition: page_table.cpp:418
#define MAX_FSTREAM_TABLE
Definition: discreta.h:1806
#define BTREE_PAGE_LENGTH_LOG
Definition: discreta.h:1618
#define BTREEMAXKEYLEN
Definition: discreta.h:1490
#define BTREEHALFPAGESIZE
Definition: discreta.h:1615
#define BTREEMAXPAGESIZE
Definition: discreta.h:1616
int int_4
Definition: foundations.h:181
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
unsigned int uint_4
Definition: foundations.h:184
int root_buf_alloc(void)
Definition: btree.cpp:123
void fill_char(void *v, int cnt, int c)
Definition: global.cpp:1605
fstream * fstream_table[MAX_FSTREAM_TABLE]
Definition: btree.cpp:39
void database_init(int verbose_level)
Definition: btree.cpp:53
struct orbiter::layer2_discreta::buffer Buffer
DISCRETA auxiliary class related to the class database.
void page_table_exit(int verbose_level)
Definition: page_table.cpp:51
int page_table_alloc(int verbose_level)
Definition: page_table.cpp:69
void page_table_free(int idx, int verbose_level)
Definition: page_table.cpp:98
void bt_key_fill_in(char *key, Vector &V, Vector &the_object)
Definition: bt_key.cpp:416
struct orbiter::layer2_discreta::pagetyp PageTyp
DISCRETA auxiliary class related to the class database.
int f_RootBF_free[MAX_ROOT_BUF]
Definition: btree.cpp:31
page_table * page_table_pointer(int slot)
Definition: page_table.cpp:130
void database_exit(void)
Definition: btree.cpp:98
void root_buf_free(int i)
Definition: btree.cpp:138
void bt_key_fill_in_int4(char **p_key, discreta_base &key_op)
Definition: bt_key.cpp:364
void bt_key_fill_in_string(char **p_key, int output_size, discreta_base &key_op)
Definition: bt_key.cpp:404
void page_table_init(int verbose_level)
Definition: page_table.cpp:33
int fstream_table_used[MAX_FSTREAM_TABLE]
Definition: btree.cpp:38
void bt_key_get_int4(char **key, int_4 &i)
Definition: bt_key.cpp:482
void bt_key_print(char *key, Vector &V, ostream &ost)
Definition: bt_key.cpp:183
int bt_key_compare(char *key1, char *key2, Vector &V, int depth)
Definition: bt_key.cpp:302
int fstream_table_get_free_entry()
Definition: btree.cpp:109
struct orbiter::layer2_discreta::itemtyp ItemTyp
DISCRETA auxiliary class related to the class database.
the orbiter library for the classification of combinatorial objects
DISCRETA auxiliary class related to the class database.
Definition: discreta.h:1659
DISCRETA auxiliary class related to the class database.
Definition: discreta.h:1507
DISCRETA auxiliary class related to the class database.
Definition: discreta.h:1631
DISCRETA auxiliary class related to the class database.
Definition: discreta.h:1498
DISCRETA auxiliary class related to the class database.
Definition: discreta.h:1642
ItemTyp Item[BTREEMAXPAGESIZE+1]
Definition: discreta.h:1648
DISCRETA internal class.
Definition: discreta.h:353