-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBTreeFile.java
846 lines (727 loc) · 27.6 KB
/
BTreeFile.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
/*
* @(#) bt.java 98/03/24
* Copyright (c) 1998 UW. All Rights Reserved.
* Author: Xiaohu Li ([email protected]).
*
*/
package btree;
import java.io.*;
import java.util.logging.Logger;
import diskmgr.*;
import bufmgr.*;
import global.*;
import heap.*;
import btree.*;
/**
* btfile.java This is the main definition of class BTreeFile, which derives
* from abstract base class IndexFile. It provides an insert/delete interface.
*/
public class BTreeFile extends IndexFile implements GlobalConst {
private final static int MAGIC0 = 1989;
private final static String lineSep = System.getProperty("line.separator");
private static FileOutputStream fos;
private static DataOutputStream trace;
static Logger logger = Logger.getLogger(BTreeFile.class.getName());//added to create a log file
/**
* It causes a structured trace to be written to a file. This output is used
* to drive a visualization tool that shows the inner workings of the b-tree
* during its operations.
*
* @param filename
* input parameter. The trace file name
* @exception IOException
* error from the lower layer
*/
public static void traceFilename(String filename) throws IOException {
fos = new FileOutputStream(filename);
trace = new DataOutputStream(fos);
}
/**
* Stop tracing. And close trace file.
*
* @exception IOException
* error from the lower layer
*/
public static void destroyTrace() throws IOException {
if (trace != null)
trace.close();
if (fos != null)
fos.close();
fos = null;
trace = null;
}
private BTreeHeaderPage headerPage;
private PageId headerPageId;
private String dbname;
/**
* Access method to data member.
*
* @return Return a BTreeHeaderPage object that is the header page of this
* btree file.
*/
public BTreeHeaderPage getHeaderPage() {
return headerPage;
}
private PageId get_file_entry(String filename) throws GetFileEntryException {
try {
return SystemDefs.JavabaseDB.get_file_entry(filename);
} catch (Exception e) {
e.printStackTrace();
throw new GetFileEntryException(e, "");
}
}
private Page pinPage(PageId pageno) throws PinPageException {
try {
Page page = new Page();
SystemDefs.JavabaseBM.pinPage(pageno, page, false/* Rdisk */);
return page;
} catch (Exception e) {
e.printStackTrace();
throw new PinPageException(e, "");
}
}
private void add_file_entry(String fileName, PageId pageno)
throws AddFileEntryException {
try {
SystemDefs.JavabaseDB.add_file_entry(fileName, pageno);
} catch (Exception e) {
e.printStackTrace();
throw new AddFileEntryException(e, "");
}
}
private void unpinPage(PageId pageno) throws UnpinPageException {
try {
SystemDefs.JavabaseBM.unpinPage(pageno, false /* = not DIRTY */);
} catch (Exception e) {
e.printStackTrace();
throw new UnpinPageException(e, "");
}
}
private void freePage(PageId pageno) throws FreePageException {
try {
SystemDefs.JavabaseBM.freePage(pageno);
} catch (Exception e) {
e.printStackTrace();
throw new FreePageException(e, "");
}
}
private void delete_file_entry(String filename)
throws DeleteFileEntryException {
try {
SystemDefs.JavabaseDB.delete_file_entry(filename);
} catch (Exception e) {
e.printStackTrace();
throw new DeleteFileEntryException(e, "");
}
}
private void unpinPage(PageId pageno, boolean dirty)
throws UnpinPageException {
try {
SystemDefs.JavabaseBM.unpinPage(pageno, dirty);
} catch (Exception e) {
e.printStackTrace();
throw new UnpinPageException(e, "");
}
}
/**
* BTreeFile class an index file with given filename should already exist;
* this opens it.
*
* @param filename
* the B+ tree file name. Input parameter.
* @exception GetFileEntryException
* can not ger the file from DB
* @exception PinPageException
* failed when pin a page
* @exception ConstructPageException
* BT page constructor failed
*/
public BTreeFile(String filename) throws GetFileEntryException,
PinPageException, ConstructPageException {
headerPageId = get_file_entry(filename);
headerPage = new BTreeHeaderPage(headerPageId);
dbname = new String(filename);
/*
*
* - headerPageId is the PageId of this BTreeFile's header page; -
* headerPage, headerPageId valid and pinned - dbname contains a copy of
* the name of the database
*/
}
/**
* if index file exists, open it; else create it.
*
* @param filename
* file name. Input parameter.
* @param keytype
* the type of key. Input parameter.
* @param keysize
* the maximum size of a key. Input parameter.
* @param delete_fashion
* full delete or naive delete. Input parameter. It is either
* DeleteFashion.NAIVE_DELETE or DeleteFashion.FULL_DELETE.
* @exception GetFileEntryException
* can not get file
* @exception ConstructPageException
* page constructor failed
* @exception IOException
* error from lower layer
* @exception AddFileEntryException
* can not add file into DB
*/
public BTreeFile(String filename, int keytype, int keysize,
int delete_fashion) throws GetFileEntryException,
ConstructPageException, IOException, AddFileEntryException {
headerPageId = get_file_entry(filename);
if (headerPageId == null) // file not exist
{
headerPage = new BTreeHeaderPage();
headerPageId = headerPage.getPageId();
add_file_entry(filename, headerPageId);
headerPage.set_magic0(MAGIC0);
headerPage.set_rootId(new PageId(INVALID_PAGE));
headerPage.set_keyType((short) keytype);
headerPage.set_maxKeySize(keysize);
headerPage.set_deleteFashion(delete_fashion);
headerPage.setType(NodeType.BTHEAD);
} else {
headerPage = new BTreeHeaderPage(headerPageId);
}
dbname = new String(filename);
}
/**
* Close the B+ tree file. Unpin header page.
*
* @exception PageUnpinnedException
* error from the lower layer
* @exception InvalidFrameNumberException
* error from the lower layer
* @exception HashEntryNotFoundException
* error from the lower layer
* @exception ReplacerException
* error from the lower layer
*/
public void close() throws PageUnpinnedException,
InvalidFrameNumberException, HashEntryNotFoundException,
ReplacerException {
if (headerPage != null) {
SystemDefs.JavabaseBM.unpinPage(headerPageId, true);
headerPage = null;
}
}
/**
* Destroy entire B+ tree file.
*
* @exception IOException
* error from the lower layer
* @exception IteratorException
* iterator error
* @exception UnpinPageException
* error when unpin a page
* @exception FreePageException
* error when free a page
* @exception DeleteFileEntryException
* failed when delete a file from DM
* @exception ConstructPageException
* error in BT page constructor
* @exception PinPageException
* failed when pin a page
*/
public void destroyFile() throws IOException, IteratorException,
UnpinPageException, FreePageException, DeleteFileEntryException,
ConstructPageException, PinPageException {
if (headerPage != null) {
PageId pgId = headerPage.get_rootId();
if (pgId.pid != INVALID_PAGE)
_destroyFile(pgId);
unpinPage(headerPageId);
freePage(headerPageId);
delete_file_entry(dbname);
headerPage = null;
}
}
private void _destroyFile(PageId pageno) throws IOException,
IteratorException, PinPageException, ConstructPageException,
UnpinPageException, FreePageException {
BTSortedPage sortedPage;
Page page = pinPage(pageno);
sortedPage = new BTSortedPage(page, headerPage.get_keyType());
if (sortedPage.getType() == NodeType.INDEX) {
BTIndexPage indexPage = new BTIndexPage(page,
headerPage.get_keyType());
RID rid = new RID();
PageId childId;
KeyDataEntry entry;
for (entry = indexPage.getFirst(rid); entry != null; entry = indexPage
.getNext(rid)) {
childId = ((IndexData) (entry.data)).getData();
_destroyFile(childId);
}
} else { // BTLeafPage
unpinPage(pageno);
freePage(pageno);
}
}
private void updateHeader(PageId newRoot) throws IOException,
PinPageException, UnpinPageException {
BTreeHeaderPage header;
PageId old_data;
header = new BTreeHeaderPage(pinPage(headerPageId));
old_data = headerPage.get_rootId();
header.set_rootId(newRoot);
// clock in dirty bit to bm so our dtor needn't have to worry about it
unpinPage(headerPageId, true /* = DIRTY */);
// ASSERTIONS:
// - headerPage, headerPageId valid, pinned and marked as dirty
}
/**
* insert record with the given key and rid
*
* @param key
* the key of the record. Input parameter.
* @param rid
* the rid of the record. Input parameter.
* @exception KeyTooLongException
* key size exceeds the max keysize.
* @exception KeyNotMatchException
* key is not integer key nor string key
* @exception IOException
* error from the lower layer
* @exception LeafInsertRecException
* insert error in leaf page
* @exception IndexInsertRecException
* insert error in index page
* @exception ConstructPageException
* error in BT page constructor
* @exception UnpinPageException
* error when unpin a page
* @exception PinPageException
* error when pin a page
* @exception NodeNotMatchException
* node not match index page nor leaf page
* @exception ConvertException
* error when convert between revord and byte array
* @exception DeleteRecException
* error when delete in index page
* @exception IndexSearchException
* error when search
* @exception IteratorException
* iterator error
* @exception LeafDeleteException
* error when delete in leaf page
* @exception InsertException
* error when insert in index page
*/
public void insert(KeyClass key, RID rid) throws KeyTooLongException,
KeyNotMatchException, LeafInsertRecException,
IndexInsertRecException, ConstructPageException,
UnpinPageException, PinPageException, NodeNotMatchException,
ConvertException, DeleteRecException, IndexSearchException,
IteratorException, LeafDeleteException, InsertException,
IOException {
/*PageId get_rootId() throws IOException {
return this.getNextPage();
}*/
try {
logger.info("********** Entering insert method ***********");
if(headerPage.get_rootId().pid == INVALID_PAGE) { //there is no root page
logger.info("********** Creating Root Page ***********");
BTLeafPage newRootPage = new BTLeafPage(headerPage.get_keyType());
newRootPage.setNextPage(new PageId(INVALID_PAGE));
newRootPage.setPrevPage(new PageId(INVALID_PAGE));
pinPage(newRootPage.getCurPage());
newRootPage.insertRecord(key,rid);
updateHeader(newRootPage.getCurPage());
unpinPage(newRootPage.getCurPage(), true);// setting the page to dirty
} else {//root page already exist
logger.info("********** Root Page Exist Creating new pages ***********");
KeyDataEntry newRootEntry;
newRootEntry = _insert(key, rid, headerPage.get_rootId());
logger.info("********** New Root Entry *********** "+ newRootEntry);
if(newRootEntry != null) {//split occured
BTIndexPage newPage = new BTIndexPage(NodeType.INDEX);
newPage.insertKey(newRootEntry.key, ((IndexData) newRootEntry.data).getData());
newPage.setPrevPage(headerPage.get_rootId());// set prev page to current page
updateHeader(newPage.getCurPage());//update given first in slide0
unpinPage(((IndexData) newRootEntry.data).getData(),true);
}
}
logger.info("********** Exiting insert method ***********");
} catch(LeafInsertRecException e) {
e.printStackTrace();
} catch(UnpinPageException e) {
e.printStackTrace();
} catch(IndexInsertRecException e) {
e.printStackTrace();
}
}
private KeyDataEntry _insert(KeyClass key, RID rid, PageId currentPageId)
throws PinPageException, IOException, ConstructPageException,
LeafDeleteException, ConstructPageException, DeleteRecException,
IndexSearchException, UnpinPageException, LeafInsertRecException,
ConvertException, IteratorException, IndexInsertRecException,
KeyNotMatchException, NodeNotMatchException, InsertException {
logger.info("********** Entering _insert method ***********");
Page page = new Page();
pinPage(currentPageId);
BTSortedPage currentPage = new BTSortedPage(currentPageId,headerPage.get_keyType());//sorted page with current page instance
KeyDataEntry upEntry = null;
logger.info("********** Current Page Type *********** "+ currentPage.getType());
if(currentPage.getType() == NodeType.INDEX) {//if node is index
logger.info("********** Index Page inserting data ***********");
BTIndexPage currentIndexPage = new BTIndexPage(currentPageId,headerPage.get_keyType());
PageId currentIndexPageID = currentIndexPage.getCurPage();
PageId nextPageID = currentIndexPage.getPageNoByKey(key);
unpinPage(currentIndexPageID,true);
upEntry = _insert(key,rid,nextPageID);
if(upEntry == null) {
logger.info("********** upEntry null ***********");
return null;
} else {
logger.info("********** upEntry not null ***********");
if(currentIndexPage.available_space() >= BT.getKeyDataLength(upEntry.key, NodeType.INDEX)) {//if empty insert
currentIndexPage.insertKey(upEntry.key,((IndexData) upEntry.data).getData() );
} else {// not empty splitting the index
BTIndexPage newIndexPage = new BTIndexPage(headerPage.get_keyType());
PageId newIndexPageID = newIndexPage.getCurPage();
KeyDataEntry tmpKeyDataEntry;
KeyDataEntry lastRecord;
RID delRID = new RID();
for(tmpKeyDataEntry = currentIndexPage.getFirst(delRID); tmpKeyDataEntry!=null; tmpKeyDataEntry = currentIndexPage.getFirst( delRID)) {
//to transfer data from current page to new page
newIndexPage.insertKey( tmpKeyDataEntry.key, ((IndexData) tmpKeyDataEntry.data).getData());//insert
currentIndexPage.deleteSortedRecord(delRID);//delete
}
int count = 1;
for(tmpKeyDataEntry = newIndexPage.getFirst(delRID);count<=newIndexPage.numberOfRecords()/2;tmpKeyDataEntry = newIndexPage.getFirst(delRID)) {
//make the number of records equal in both the index page
currentIndexPage.insertKey(tmpKeyDataEntry.key, ((IndexData) tmpKeyDataEntry.data).getData());
newIndexPage.deleteSortedRecord(delRID);//delete
lastRecord = tmpKeyDataEntry;//check this
count++;
}
//compare the keys
if(BT.keyCompare(upEntry.key, tmpKeyDataEntry.key)>0)
newIndexPage.insertKey(upEntry.key, ((IndexData) upEntry.data).getData());
else
currentIndexPage.insertKey(upEntry.key, ((IndexData) upEntry.data).getData());
unpinPage(currentIndexPageID, true);
upEntry = newIndexPage.getFirst(delRID);
newIndexPage.setPrevPage(((IndexData)upEntry.data).getData());
newIndexPage.deleteSortedRecord(delRID);//delete the moved up record
unpinPage(newIndexPageID, true);
((IndexData)upEntry.data).setData(newIndexPageID);//set to next index page in hierarchy
return upEntry;
}
}
} else if(currentPage.getType() == NodeType.LEAF) {
logger.info("********** Leaf Page inserting data ***********");
BTLeafPage currentLeafPage = new BTLeafPage(currentPageId,headerPage.get_keyType());
if(currentLeafPage.available_space() >= BT.getKeyDataLength(key,NodeType.LEAF)) {//slide exception
logger.info("********** Leaf Page Empty ***********");
currentLeafPage.insertRecord(key,rid);
unpinPage(currentLeafPage.getCurPage(), true);
return null;
} else {
logger.info("********** Leaf Page Full ***********");
BTLeafPage newLeafPage = new BTLeafPage(headerPage.get_keyType());
PageId newLeafPageID = newLeafPage.getCurPage();
newLeafPage.setNextPage(currentLeafPage.getNextPage());//since new page will be in middle it will point to next page of old page
newLeafPage.setPrevPage(currentLeafPage.getCurPage());//pointing to old page
currentLeafPage.setNextPage(newLeafPageID);//old page next to new page
KeyDataEntry tmpKeyDataEntry;
KeyDataEntry lastRecord = null;
RID delRID = new RID();
for(tmpKeyDataEntry = currentLeafPage.getFirst(delRID); tmpKeyDataEntry!=null;tmpKeyDataEntry = currentLeafPage.getFirst(delRID)) {
newLeafPage.insertRecord(tmpKeyDataEntry.key, ((LeafData)tmpKeyDataEntry.data).getData());
currentLeafPage.deleteSortedRecord(delRID);
}
int count = 1;
for(tmpKeyDataEntry = newLeafPage.getFirst(delRID);count<=newLeafPage.numberOfRecords()/2;tmpKeyDataEntry = newLeafPage.getFirst(delRID)) {
//make the number of records equal in both the index page
currentLeafPage.insertRecord(tmpKeyDataEntry.key,((LeafData)tmpKeyDataEntry.data).getData());
newLeafPage.deleteSortedRecord(delRID);//delete
//lastRecord = tmpKeyDataEntry;//check this
lastRecord = tmpKeyDataEntry;
count++;
}
if(BT.keyCompare(key, lastRecord.key)>0)//check this
newLeafPage.insertRecord(key, rid);
else
currentLeafPage.insertRecord(key,rid);
unpinPage(currentLeafPage.getCurPage(), true);
tmpKeyDataEntry = newLeafPage.getFirst(delRID);
upEntry =new KeyDataEntry(tmpKeyDataEntry.key, newLeafPageID);
unpinPage(newLeafPageID, true);
logger.info("********** Exiting Leaf Page Full ***********");
return upEntry;
}
} else {
throw new InsertException(null,"");
}
logger.info("********** Exiting _insert method ***********");
return null;
}
/**
* delete leaf entry given its <key, rid> pair. `rid' is IN the data entry;
* it is not the id of the data entry)
*
* @param key
* the key in pair <key, rid>. Input Parameter.
* @param rid
* the rid in pair <key, rid>. Input Parameter.
* @return true if deleted. false if no such record.
* @exception DeleteFashionException
* neither full delete nor naive delete
* @exception LeafRedistributeException
* redistribution error in leaf pages
* @exception RedistributeException
* redistribution error in index pages
* @exception InsertRecException
* error when insert in index page
* @exception KeyNotMatchException
* key is neither integer key nor string key
* @exception UnpinPageException
* error when unpin a page
* @exception IndexInsertRecException
* error when insert in index page
* @exception FreePageException
* error in BT page constructor
* @exception RecordNotFoundException
* error delete a record in a BT page
* @exception PinPageException
* error when pin a page
* @exception IndexFullDeleteException
* fill delete error
* @exception LeafDeleteException
* delete error in leaf page
* @exception IteratorException
* iterator error
* @exception ConstructPageException
* error in BT page constructor
* @exception DeleteRecException
* error when delete in index page
* @exception IndexSearchException
* error in search in index pages
* @exception IOException
* error from the lower layer
*
*/
public boolean Delete(KeyClass key, RID rid) throws DeleteFashionException,
LeafRedistributeException, RedistributeException,
InsertRecException, KeyNotMatchException, UnpinPageException,
IndexInsertRecException, FreePageException,
RecordNotFoundException, PinPageException,
IndexFullDeleteException, LeafDeleteException, IteratorException,
ConstructPageException, DeleteRecException, IndexSearchException,
IOException {
if (headerPage.get_deleteFashion() == DeleteFashion.NAIVE_DELETE)
return NaiveDelete(key, rid);
else
throw new DeleteFashionException(null, "");
}
/*
* findRunStart. Status BTreeFile::findRunStart (const void lo_key, RID
* *pstartrid)
*
* find left-most occurrence of `lo_key', going all the way left if lo_key
* is null.
*
* Starting record returned in *pstartrid, on page *pppage, which is pinned.
*
* Since we allow duplicates, this must "go left" as described in the text
* (for the search algorithm).
*
* @param lo_key find left-most occurrence of `lo_key', going all the way
* left if lo_key is null.
*
* @param startrid it will reurn the first rid =< lo_key
*
* @return return a BTLeafPage instance which is pinned. null if no key was
* found.
*/
BTLeafPage findRunStart(KeyClass lo_key, RID startrid) throws IOException,
IteratorException, KeyNotMatchException, ConstructPageException,
PinPageException, UnpinPageException {
BTLeafPage pageLeaf;
BTIndexPage pageIndex;
Page page;
BTSortedPage sortPage;
PageId pageno;
PageId curpageno = null; // iterator
PageId prevpageno;
PageId nextpageno;
RID curRid;
KeyDataEntry curEntry;
pageno = headerPage.get_rootId();
if (pageno.pid == INVALID_PAGE) { // no pages in the BTREE
pageLeaf = null; // should be handled by
// startrid =INVALID_PAGEID ; // the caller
return pageLeaf;
}
page = pinPage(pageno);
sortPage = new BTSortedPage(page, headerPage.get_keyType());
if (trace != null) {
trace.writeBytes("VISIT node " + pageno + lineSep);
trace.flush();
}
// ASSERTION
// - pageno and sortPage is the root of the btree
// - pageno and sortPage valid and pinned
while (sortPage.getType() == NodeType.INDEX) {
pageIndex = new BTIndexPage(page, headerPage.get_keyType());
prevpageno = pageIndex.getPrevPage();
curEntry = pageIndex.getFirst(startrid);
while (curEntry != null && lo_key != null
&& BT.keyCompare(curEntry.key, lo_key) < 0) {
prevpageno = ((IndexData) curEntry.data).getData();
curEntry = pageIndex.getNext(startrid);
}
unpinPage(pageno);
pageno = prevpageno;
page = pinPage(pageno);
sortPage = new BTSortedPage(page, headerPage.get_keyType());
if (trace != null) {
trace.writeBytes("VISIT node " + pageno + lineSep);
trace.flush();
}
}
pageLeaf = new BTLeafPage(page, headerPage.get_keyType());
curEntry = pageLeaf.getFirst(startrid);
while (curEntry == null) {
// skip empty leaf pages off to left
nextpageno = pageLeaf.getNextPage();
unpinPage(pageno);
if (nextpageno.pid == INVALID_PAGE) {
// oops, no more records, so set this scan to indicate this.
return null;
}
pageno = nextpageno;
pageLeaf = new BTLeafPage(pinPage(pageno), headerPage.get_keyType());
curEntry = pageLeaf.getFirst(startrid);
}
// ASSERTIONS:
// - curkey, curRid: contain the first record on the
// current leaf page (curkey its key, cur
// - pageLeaf, pageno valid and pinned
if (lo_key == null) {
return pageLeaf;
// note that pageno/pageLeaf is still pinned;
// scan will unpin it when done
}
while (BT.keyCompare(curEntry.key, lo_key) < 0) {
curEntry = pageLeaf.getNext(startrid);
while (curEntry == null) { // have to go right
nextpageno = pageLeaf.getNextPage();
unpinPage(pageno);
if (nextpageno.pid == INVALID_PAGE) {
return null;
}
pageno = nextpageno;
pageLeaf = new BTLeafPage(pinPage(pageno),
headerPage.get_keyType());
curEntry = pageLeaf.getFirst(startrid);
}
}
return pageLeaf;
}
/*
* Status BTreeFile::NaiveDelete (const void *key, const RID rid)
*
* Remove specified data entry (<key, rid>) from an index.
*
* We don't do merging or redistribution, but do allow duplicates.
*
* Page containing first occurrence of key `key' is found for us by
* findRunStart. We then iterate for (just a few) pages, if necesary, to
* find the one containing <key,rid>, which we then delete via
* BTLeafPage::delUserRid.
*/
private boolean NaiveDelete(KeyClass key, RID rid)
throws LeafDeleteException, KeyNotMatchException, PinPageException,
ConstructPageException, IOException, UnpinPageException,
PinPageException, IndexSearchException, IteratorException {
// remove the return statement and start your code.
return false;
}
/**
* create a scan with given keys Cases: (1) lo_key = null, hi_key = null
* scan the whole index (2) lo_key = null, hi_key!= null range scan from min
* to the hi_key (3) lo_key!= null, hi_key = null range scan from the lo_key
* to max (4) lo_key!= null, hi_key!= null, lo_key = hi_key exact match (
* might not unique) (5) lo_key!= null, hi_key!= null, lo_key < hi_key range
* scan from lo_key to hi_key
*
* @param lo_key
* the key where we begin scanning. Input parameter.
* @param hi_key
* the key where we stop scanning. Input parameter.
* @exception IOException
* error from the lower layer
* @exception KeyNotMatchException
* key is not integer key nor string key
* @exception IteratorException
* iterator error
* @exception ConstructPageException
* error in BT page constructor
* @exception PinPageException
* error when pin a page
* @exception UnpinPageException
* error when unpin a page
*/
public BTFileScan new_scan(KeyClass lo_key, KeyClass hi_key)
throws IOException, KeyNotMatchException, IteratorException,
ConstructPageException, PinPageException, UnpinPageException
{
BTFileScan scan = new BTFileScan();
if (headerPage.get_rootId().pid == INVALID_PAGE) {
scan.leafPage = null;
return scan;
}
scan.treeFilename = dbname;
scan.endkey = hi_key;
scan.didfirst = false;
scan.deletedcurrent = false;
scan.curRid = new RID();
scan.keyType = headerPage.get_keyType();
scan.maxKeysize = headerPage.get_maxKeySize();
scan.bfile = this;
// this sets up scan at the starting position, ready for iteration
scan.leafPage = findRunStart(lo_key, scan.curRid);
return scan;
}
void trace_children(PageId id) throws IOException, IteratorException,
ConstructPageException, PinPageException, UnpinPageException {
if (trace != null) {
BTSortedPage sortedPage;
RID metaRid = new RID();
PageId childPageId;
KeyClass key;
KeyDataEntry entry;
sortedPage = new BTSortedPage(pinPage(id), headerPage.get_keyType());
// Now print all the child nodes of the page.
if (sortedPage.getType() == NodeType.INDEX) {
BTIndexPage indexPage = new BTIndexPage(sortedPage,
headerPage.get_keyType());
trace.writeBytes("INDEX CHILDREN " + id + " nodes" + lineSep);
trace.writeBytes(" " + indexPage.getPrevPage());
for (entry = indexPage.getFirst(metaRid); entry != null; entry = indexPage
.getNext(metaRid)) {
trace.writeBytes(" " + ((IndexData) entry.data).getData());
}
} else if (sortedPage.getType() == NodeType.LEAF) {
BTLeafPage leafPage = new BTLeafPage(sortedPage,
headerPage.get_keyType());
trace.writeBytes("LEAF CHILDREN " + id + " nodes" + lineSep);
for (entry = leafPage.getFirst(metaRid); entry != null; entry = leafPage
.getNext(metaRid)) {
trace.writeBytes(" " + entry.key + " " + entry.data);
}
}
unpinPage(id);
trace.writeBytes(lineSep);
trace.flush();
}
}
}
//problem faced unpin exception unpinning before update!