bool BTreeDriver::TestLargeWorkload() { Status status; BTreeFile *btf; bool res; btf = new BTreeFile(status, "BTreeTest4"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "Starting Test 4..." << std::endl; std::cout << "BTreeIndex created successfully." << std::endl; res = InsertRange(btf, 1, 1000, 1, 5, true); res = res && TestNumEntries(btf, 1000); res = InsertRange(btf, 1, 1000, 2, 5, false); res = res && TestNumEntries(btf, 2000); res = InsertRange(btf, 501, 1500, 3, 5, false); res = res && TestNumEntries(btf, 3000); res = InsertRange(btf, 2001, 4000, 1, 5, false); res = res && TestNumEntries(btf, 5000); char low[MAX_KEY_LENGTH]; char high[MAX_KEY_LENGTH]; toString(1000, low, 5); toString(1000, high, 5); BTreeFileScan *scan = btf->OpenScan(low, high); res = res && TestScanCount(scan, 3); delete scan; toString(3000, low, 5); toString(3000, high, 5); scan = btf->OpenScan(low, high); res = res && TestScanCount(scan, 1); delete scan; res = res && TestAbsent(btf, 1700, 1, 5); if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; return res; }
HeapFile *SortFile(HeapFile *S, int len, int offset) { Status s; Scan *scan; scan = S->OpenScan(s); if (s != OK) { cerr << "ERROR : cannot open scan on the heapfile to sort.\n"; } // // Scan the HeapFile S, new a B+Tree and insert the records into B+Tree. // BTreeFile *btree; btree = new BTreeFile (s, "BTree", ATTR_INT, sizeof(int)); char *recPtr = new char[len]; int recLen = len; RecordID rid; while (scan->GetNext(rid, recPtr, recLen) == OK) { btree->Insert(recPtr + offset, rid); } delete scan; HeapFile *sorted; sorted = new HeapFile(NULL, s); // create a temp HeapFile if (s != OK) { cerr << "Cannot create new file for sortedS\n"; } // // Now scan the B+-Tree and insert the records into a // new (sorted) HeapFile. // BTreeFileScan *btreeScan; btreeScan = (BTreeFileScan *)btree->OpenScan(NULL, NULL); int key; while (btreeScan->GetNext(rid, &key) == OK) { S->GetRecord (rid, recPtr, recLen); sorted->InsertRecord (recPtr, recLen, rid); } btree->DestroyFile(); delete btree; delete btreeScan; delete [] recPtr; return sorted; }
void BTreeTest::test4() { Status status; BTreeFile *btf; IndexFileScan* scan; int key, lokey, hikey; RID rid; int num = 1000; int num_deletes = 400; int i; dummy values[num]; cout << "\n---------test4() key type is Integer--------------\n"; // test create() // if index exists, open it else create btf = new BTreeFile(status, "BTreeIndex", attrInteger, sizeof(int)); if (status != OK) { minibase_errors.show_errors(); exit(1); } cout << "\nBTreeIndex created successfully." << endl << endl; cout << " Creating " << num << " random entries" << endl; for ( i = 0; i < num; i++) { values[i].key = i * 8 + (rand() % 8); values[i].r.pageNo = i; values[i].r.slotNo = i+1; values[i].sort_value1 = rand() % 1000000; values[i].sort_value2 = rand() % 1000000; /*cout << " key " << values[i].key << " sort_value1 " << values[i].sort_value1 << " sort_value2 " << values[i].sort_value2 << endl;*/ } // test insert() // put values in insertion order qsort( values, num, sizeof(dummy), eval1); cout << "\n------Start to insert " << num << " records------" << endl; for (i=0; i < num; i++){ //cout << " Inserting key " << values[i].key << " order " //<< values[i].sort_value1 << endl; if (btf->insert(&(values[i].key), values[i].r) != OK) { minibase_errors.show_errors(); } } cout << "\n------ End of insert------" << endl; // test delete() cout << "\n\n------ Delete the first " << num_deletes << " of the records-----" << endl; // place records in deletion order qsort(values, num, sizeof(dummy), eval2); for (i = 0; i < num_deletes; i++) { /* cout << "Deleting record with key = " << values[i].key << " [pageNo,slotNo] = "; cout << "[" << values[i].r.pageNo<<"," << values[i].r.slotNo << "]" <<endl; */ if (btf->Delete(&values[i].key, values[i].r) != OK) { minibase_errors.show_errors(); } } cout << "Deleted " << i << " records " << endl; cout << "\n------ End of delete ------" << endl; delete btf; btf = new BTreeFile(status, "BTreeIndex"); // test scan and delete_current() cout << "\n\n------ Testing scans ------" << endl; lokey = 570; hikey = 690; i= 1000; while (i < 1020){ rid.pageNo = i; rid.slotNo = i+ 1; if(i < 1010) key = lokey; else key = hikey; if(btf->insert(&key,rid) != OK) minibase_errors.show_errors(); i++; } //AllScan scan = btf->new_scan(NULL,NULL); cout << "\n\n------Start AllScan------" << endl; test_scan(scan); delete scan; cout << "\n------End of AllScan------" << endl; //MaxRangeScan scan = btf->new_scan(NULL, &hikey); cout << "\n\n------Start MaxRangeScan with hikey = "<<hikey<<"------\n"; test_scan(scan); delete scan; cout << "\n------End of MaxRangeScan with hikey = "<<hikey<<"------\n"; //MinRangeScan; scan = btf->new_scan(&lokey, NULL); cout << "\n\n------Start MinRangeScan with lokey = "<<lokey<<"------\n"; test_scan(scan); delete scan; cout << "\n------End of MinRangeScan with lokey = "<<lokey<<"------\n"; //ExactMatch scan = btf->new_scan(&hikey, &hikey); cout << "\n\n------Start ExactMatch with key = " <<hikey <<"-------\n"; test_scan(scan); delete scan; cout << "\n------End of ExactMatch with key = " <<hikey <<"-------\n"; //MinMaxRangeScan with delete_current() scan = btf->new_scan(&lokey, &hikey); cout << "\n\n------Start MinMaxRangeScan with lokey = "<<lokey << " hikey = "<<hikey<<"------\n"; cout << "Will also perform delete_current()\n"; int count = 0; status = OK; while (status == OK) { char* temp = new char[scan->keysize()]; // BK if ((status = scan->get_next(rid, temp)) == OK) { count++; if ((status = scan->delete_current()) == OK) { cout << "Record with [pageNo,slotNo] = "; cout << "[" << rid.pageNo<<","<<rid.slotNo<<"] deleted"<<endl; } else { cout << "Failure to delete record...\n"; minibase_errors.show_errors(); } delete [] temp; // BK } } if (status != DONE) { cout << "Something is wrong in test4\n"; minibase_errors.show_errors(); } cout << "Number of records scanned = " << count << endl; cout << "\n------End of MinMaxRangeScan -----------------------\n"; delete scan; delete btf; // test destroyFile() cout << "\n\n-----------Destroying index----------\n"; btf = new BTreeFile(status, "BTreeIndex"); cout << "\n-------Start to destroy the index----------" << endl; status = btf->destroyFile(); if (status != OK) minibase_errors.show_errors(); delete btf; cout << "\n--------- End of destroying the index -----" <<endl; cout << "\n\n--------- End of test4 -------------" <<endl; }
void BTreeTest::test3() { cout << "\n--------test3() key type is String---------\n"; Status status; BTreeFile *btf; IndexFileScan* scan; int keysize = MAX_KEY_SIZE1; char* key = new char[keysize]; char* lokey = new char[keysize]; char* hikey = new char[keysize]; int i = 0; RID rid, lorid; ifstream keysamples; keysamples.open("keys",ios::in); if (!keysamples) { cout << "keys not found.\n"; cout << " there is a copy in $MINIBASE_HOME/programs/minibase "<< endl; return; } // test create() btf = new BTreeFile(status, "BTreeIndex", attrString, keysize); if (status != OK) { minibase_errors.show_errors(); exit(1); } cout << "BTreeIndex created successfully." << endl; // test insert() cout << "\n------Start to insert records--------" << endl; keysamples.getline(key, keysize, '\n'); while(!keysamples.eof()) { rid.pageNo = (int)(key[0]+key[1]+key[2]); rid.slotNo = rid.pageNo; if (btf->insert(key, rid) != OK) { minibase_errors.show_errors(); } i++; if(i==20) strncpy(lokey,key,keysize); if(i==100) strncpy(hikey,key,keysize); keysamples.getline(key, keysize, '\n'); } cout << "\nNumber of records inserted is " << i << endl; cout << "\n--------------End of insert----------------" << endl; // test delete() cout << "\n------Start to delete some records----------" << endl; // delete the lokey lorid.pageNo = (int)(lokey[0]+lokey[1]+lokey[2]); lorid.slotNo = lorid.pageNo; if (btf->Delete(lokey, lorid) != OK) minibase_errors.show_errors(); else cout << "\nSuccessfully deleted record with key = " << lokey << endl; cout << "\n---------------End of delete----------------" << endl; delete btf; btf = new BTreeFile(status, "BTreeIndex"); // test scan and delete_current //AllScan scan = btf->new_scan(NULL,NULL); cout << "\n---------------Start AllScan------------" << endl; test_scan(scan); delete scan; cout <<"\n------End of AllScan------" << endl; //MaxRangeScan scan = btf->new_scan(NULL, hikey); cout << "\n\n------Start MaxRangeScan with hikey = "<<hikey<< "------\n"; test_scan(scan); delete scan; cout << "\n------End of MaxRangeScan with hikey = "<<hikey<< "------\n"; //MinRangeScan; scan = btf->new_scan(lokey, NULL); cout << "\n\n-----Start MinRangeScan with lokey = "<<lokey<< "------\n"; test_scan(scan); delete scan; cout << "\n------End of MinRangeScan with lokey = "<<lokey<< "------\n"; //ExactMatch scan = btf->new_scan(hikey, hikey); cout << "\n\n------Start ExactMatch with key = " <<hikey << "------\n"; test_scan(scan); delete scan; cout << "\n------End of ExactMatch with key = " <<hikey << "------\n"; //MinMaxRangeScan scan = btf->new_scan(lokey, hikey); cout << "\n\n------Start MinMaxRangeScan------" << endl; if(scan == NULL) { cout << "Cannot open a scan." << endl; } cout << "\n------Start scan with lokey = "<<lokey << " hikey = "<<hikey << "-----" << endl; int count = 0; status = OK; while (status == OK) { char* temp = new char[scan->keysize()]; // BK if ((status = scan->get_next(rid, temp)) == OK) { count++; if ((status = scan->delete_current()) == OK) { cout << "Record with [pageNo,slotNo] = "; cout << "[" << rid.pageNo<<","<<rid.slotNo<<"] deleted"<<endl; } else minibase_errors.show_errors(); } delete [] temp; // BK } if (status != DONE) { cout << "Problem...\n"; minibase_errors.show_errors(); } cout << "Number of records scanned = " << count << endl; cout << "\n-------End of MinMaxRangeScan------\n"; delete scan; cout << "\n\n------Testing abnormal scans------\n"; // test abnormal scans // lokey > hikey strcpy(lokey, "zabcd"); strcpy(hikey, "abcde"); scan = btf->new_scan(lokey, hikey); char *temp1 = new char[MAX_KEY_SIZE1]; if ((status = scan->get_next(rid, temp1)) == OK) { cout << " Error: find next??? nothing to find!!" << endl; minibase_errors.show_errors(); exit(1); } if (status != DONE) minibase_errors.show_errors(); delete scan; cout << " Failed as expected: no records scanned " << endl; // lokey > the largest key strcpy(lokey, "zabcd"); strcpy(hikey, "zcdef"); scan = btf->new_scan(lokey, hikey); if ((status = scan->get_next(rid, temp1)) == OK) { cout << " Error: find next??? nothing to find!!" << endl; minibase_errors.show_errors(); exit(1); } if (status != DONE) minibase_errors.show_errors(); delete scan; cout << " Failed as expected: no records scanned " << endl; // hikey < smallest key strcpy(lokey, "aaa"); strcpy(hikey, "aaaaa"); scan = btf->new_scan(lokey, hikey); cout << "\n----Start MinMaxRangeScan with lokey = " << lokey ; cout << " hikey = " << hikey << "-------\n" ; cout << " -------hikey is smaller than the smallest key" << endl; if ((status = scan->get_next(rid, temp1)) == OK) { cout << " Error: find next??? nothing to find!!" << endl; minibase_errors.show_errors(); exit(1); } if (status != DONE) minibase_errors.show_errors(); delete scan; cout << " Failed as expected: no records scanned " << endl; delete temp1; delete btf; // test destroyFile() btf = new BTreeFile(status, "BTreeIndex"); cout << "-------Start to destroy the index-----------" << endl; status = btf->destroyFile(); if (status != OK) minibase_errors.show_errors(); cout << "-------End to destroy the index-----------" << endl; delete btf; delete key; delete lokey; delete hikey; cout << "\n\n---------End of Test 3 ---------------------\n\n"; }
void BTreeTest::test2() { cout << "\n-------------test2() key type is Integer------------\n"; Status status; BTreeFile *btf; IndexFileScan* scan; int lokey, hikey; RID rid; // test open() btf = new BTreeFile(status, "BTreeIndex"); if (status != OK) { minibase_errors.show_errors(); cout << "You should run test1 first to create the index!\n"; return; } cout << "BTreeIndex opened successfully." << endl; //test abnormal scans //lokey > hikey lokey = 1000; hikey = 100; scan = btf->new_scan(&lokey,&hikey); cout << "\n-----Start MinMaxRangeScan with lokey = " << lokey \ << " hikey = " << hikey << "-----\n"; char* temp = new char[scan->keysize()]; // BK if ((status = scan->get_next(rid, temp)) == OK) { cout << "Error: find next??? no way!" << endl; minibase_errors.show_errors(); exit(1); } if(status != DONE) minibase_errors.show_errors(); delete scan; cout << " Failed as expected " << endl; //lokey > largest key lokey = 10000; hikey = 10010; scan = btf->new_scan(&lokey,&hikey); cout << "\n-----Start MinMaxRangeScan with lokey = " << lokey \ << " hikey = " << hikey << "-----\n"; if ((status = scan->get_next(rid, temp)) == OK) { cout << "Error: find next??? no way!" << endl; minibase_errors.show_errors(); exit(1); } if(status != DONE) minibase_errors.show_errors(); delete scan; cout << " Failed as expected " << endl; //hikey < smallest key lokey = -100; hikey = -50; scan = btf->new_scan(&lokey,&hikey); cout << "\n-----Start MinMaxRangeScan with lokey = " << lokey \ << " hikey = " << hikey << "------\n"; if ((status = scan->get_next(rid, temp)) == OK) { cout << "Error: find next??? no way!" << endl; minibase_errors.show_errors(); exit(1); } if(status != DONE) minibase_errors.show_errors(); delete scan; cout << " Failed as expected " << endl; // test destroyFile() cout << "\n------Start to destroy the index------" << endl; status = btf->destroyFile(); if (status != OK) minibase_errors.show_errors(); cout << "\n------Destroyed the index without any errors---" << endl; delete [] temp; delete btf; cout << "\n ----End of Test 2----------------------\n\n"; }
void BTreeTest::test1() { cout << "\n---------test1() key type is Integer--random------\n"; Status status; BTreeFile *btf; IndexFileScan* scan; int key, lokey, hikey,i; RID rid; int num; // test create() // if index exists, open it else create btf = new BTreeFile(status, "BTreeIndex", attrInteger, sizeof(int)); if (status != OK) { minibase_errors.show_errors(); exit(1); } cout << "BTreeIndex created successfully." << endl << endl; // test insert() num = 2000; struct dummy{ RID r; int key; }; cout << "\nstart BTreeIndex insertion" << endl << endl; dummy kill[410]; for (i = 0; i < num; i++) { rid.pageNo = i; rid.slotNo = i+1; key = num - i; if (i % 10 == 0) { kill[(i/10)].r.pageNo = rid.pageNo; kill[(i/10)].r.slotNo = rid.slotNo; kill[i/10].key = key; } if (btf->insert(&key, rid) != OK) { cout << "Inserting record with key = " << key << " [pageNo,slotNo] = "; cout << "[" << rid.pageNo<<","<<rid.slotNo<<"] failed!!\n" <<endl; minibase_errors.show_errors(); } } // test delete() cout << "\nstart BTreeIndex deletion" << endl << endl; int j = 0; for (i = 0; i < num; i++) { if (i % 10 == 0) { j++; if (btf->Delete(&kill[i/10].key, kill[(i/10)].r) != OK) { cout << " Deleting record with key = " << kill[i/10].key << " [pageNo,slotNo] = "; cout << "[" << kill[i/10].r.pageNo<<","<<kill[i/10].r.slotNo<<"] failed !!"<<endl; minibase_errors.show_errors(); } } } delete btf; btf = new BTreeFile(status, "BTreeIndex"); if(status == OK) cout<<"\n BTreeIndex opened successfully." << endl << endl; // test scan and delete_current() cout << "\n----------- Testing scans -------------" << endl; lokey = 200; hikey = 400; //AllScan scan = btf->new_scan(NULL,NULL); test_scan(scan); delete scan; //MaxRangeScan scan = btf->new_scan(NULL, &hikey); test_scan(scan); delete scan; //MinRangeScan; scan = btf->new_scan(&lokey, NULL); test_scan(scan); delete scan; //ExactMatch scan = btf->new_scan(&hikey, &hikey); test_scan(scan); delete scan; //MinMaxRangeScan with delete_current() scan = btf->new_scan(&lokey, &hikey); int count = 0; int size = scan->keysize(); char* temp = new char[size]; int* ikey; char* ckey; status = OK; while (status == OK) { if ((status = scan->get_next(rid, temp)) == OK) { count++; if ((status = scan->delete_current()) == OK) { cout << "Record with [pageNo,slotNo] = "; cout << "[" << rid.pageNo<<","<<rid.slotNo<<"]"; if (size == sizeof(int)) { ikey = (int *) temp; cout << "\tkey = " << *ikey; } else { ckey = (char*) temp; cout <<"\t key = " << ckey; } cout << "\tdeleted !!" <<endl; } else { cout << "Failure to delete record...\n"; minibase_errors.show_errors(); } } else if (status != DONE) minibase_errors.show_errors(); } delete [] temp; if (status != DONE) { cout << "Something is wrong in test1\n"; minibase_errors.show_errors(); } // delete scan; delete btf; cout << "\n---------------End of Test 1----------------------\n\n"; }
bool BTreeDriver::TestDeleteCurrent() { Status status; BTreeFile *btf; bool res; btf = new BTreeFile(status, "BTreeTest6"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "Starting Test 6..." << std::endl; std::cout << "BTreeIndex created successfully." << std::endl; std::cout << "Inserting entries..." << std::endl; InsertRange(btf, 1, 10); char low[MAX_KEY_LENGTH]; toString(3, low); BTreeFileScan* scan = btf->OpenScan(low, NULL); std::cout << "Deleting entries..." << std::endl; RecordID rid; char* keyPtr; scan->GetNext(rid, keyPtr); // 3 scan->GetNext(rid, keyPtr); // 4 scan->DeleteCurrent(); // 5 scan->GetNext(rid, keyPtr); // 6 scan->GetNext(rid, keyPtr); // 7 scan->GetNext(rid, keyPtr); // 8 scan->DeleteCurrent(); delete scan; res = TestAbsent(btf, 4); res = TestAbsent(btf, 8); std::cout << "Inserting duplicate entry..." << std::endl; InsertKey(btf, 1, 3); toString(1, low); scan = btf->OpenScan(low, NULL); std::cout << "Deleting entry..." << std::endl; scan->GetNext(rid, keyPtr); // 1 scan->DeleteCurrent(); // 1 delete scan; res = TestAbsent(btf, 1, 1); res = TestPresent(btf, 1, 3); if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; return res; }
bool BTreeDriver::TestBufferPool() { // does some operations // at the end check if there's anything left in the buffer pool std::cout << "Starting Test 5..." << std::endl; unsigned int pinnedPages = MINIBASE_BM->GetNumOfBuffers() - MINIBASE_BM->GetNumOfUnpinnedBuffers(); std::cout << "# pinned pages: " << pinnedPages << std::endl; BTreeFile* btf; Status status; bool res = true; btf = new BTreeFile(status, "BTreeTest5"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "BTreeIndex created successfully." << std::endl; std::cout << "Performing various operations on BTreeFile." << std::endl; InsertRange(btf, 1, 1000, 1, 5, true); InsertRange(btf, 1, 1000, 2, 5, false); InsertRange(btf, 501, 1500, 3, 5, false); InsertRange(btf, 2001, 4000, 1, 5, false); char low[MAX_KEY_LENGTH]; char high[MAX_KEY_LENGTH]; BTreeFileScan *scan = btf->OpenScan(NULL, NULL); RecordID rid; char* key; int count = 0; while (scan->GetNext(rid, key) != DONE) { count++; } if (count != 5000) { std::cerr << "Number of pages inserted doesn't equal 5000. Check insert." << std::endl; res = false; } delete scan; if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; unsigned int numPinned = MINIBASE_BM->GetNumOfBuffers() - MINIBASE_BM->GetNumOfUnpinnedBuffers(); if (pinnedPages - numPinned != 0) { std::cerr << pinnedPages - numPinned << " pages still left in buffer pool after clean up." << std::endl; res = false; } return res; }
bool BTreeDriver::TestInsertsWithIndexSplits() { Status status; BTreeFile *btf; bool res; btf = new BTreeFile(status, "BTreeTest3"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "Starting Test 3..." << std::endl; std::cout << "BTreeIndex created successfully." << std::endl; // Insert a bunch of long keys into the tree until we cause the root // node to split. std::cout << "Inserting 31 large keys..." << std::endl; res = InsertRange(btf, 1, 31, 1, 20); res = res && TestNumLeafPages(btf, 2); res = res && TestNumEntries(btf, 31); std::cout << "Inserting keys until root splits." << std::endl; PageID rootId = btf->header->GetRootPageID(); PageID newRootId; int key = 32; int numInserted = 0; PageID leftPid, rightPid; IndexPage *leftPage; IndexPage *rightPage; while (true) { res = res && InsertKey(btf, key, 1, 20); newRootId = btf->header->GetRootPageID(); // there was a split. Check balance. if (newRootId != rootId) { IndexPage *ip; if (MINIBASE_BM->PinPage(newRootId, (Page *&) ip) == FAIL) { std::cerr << "Error pinning root page." << std::endl; res = false; } if (ip->GetNumOfRecords() != 1) { std::cerr << "Error: Expected 1 key in root, got " << ip->GetNumOfRecords() << std::endl; res = false; } leftPid = ip->GetPrevPage(); char *rightKey; ip->GetMinKeyValue(rightKey, rightPid); if (MINIBASE_BM->PinPage(leftPid, (Page *&) leftPage) == FAIL) { std::cerr << "Error pinning left leaf page." << std::endl; res = false; } if (MINIBASE_BM->PinPage(rightPid, (Page *&) rightPage) == FAIL) { std::cerr << "Error pinning right leaf page." << std::endl; res = false; } res = res && TestBalance(btf, leftPage, rightPage); if (MINIBASE_BM->UnpinPage(leftPid, CLEAN) == FAIL) { std::cerr << "Error unpinning left leaf page." << std::endl; res = false; } if (MINIBASE_BM->UnpinPage(rightPid, CLEAN) == FAIL) { std::cerr << "Error unpinning right leaf page." << std::endl; res = false; } if (MINIBASE_BM->UnpinPage(newRootId, CLEAN) == FAIL) { std::cerr << "Error unpinning root page." << std::endl; res = false; } break; } key++; numInserted++; } res = res && TestNumEntries(btf, key); if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; return res; }
bool BTreeDriver::TestInsertsWithLeafSplits() { Status status; BTreeFile *btf; bool res; LeafPage *leftPage; LeafPage *rightPage; btf = new BTreeFile(status, "BTreeTest2"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "Starting Test 2..." << std::endl; std::cout << "BTreeIndex created successfully." << std::endl; std::cout << "Inserting 30 large keys..." << std::endl; res = InsertRange(btf, 1, 30, 1, 20); res = res && TestNumLeafPages(btf, 1); res = res && TestNumEntries(btf, 30); // Insert some more long keys. This should cause the tree to split. std::cout << "Causing split with new key in right node..." << std::endl; res = res && InsertKey(btf, 31, 1, 20); res = res && TestNumLeafPages(btf, 2); res = res && TestNumEntries(btf, 31); // Make sure that the split happened as expected. PageID leftPid = btf->GetLeftLeaf(); if (MINIBASE_BM->PinPage(leftPid, (Page *&) leftPage) == FAIL) { std::cerr << "Error pinning left leaf page." << std::endl; res = false; } PageID rightPid = leftPage->GetNextPage(); if (MINIBASE_BM->PinPage(rightPid, (Page *&) rightPage) == FAIL) { std::cerr << "Error pinning right leaf page." << std::endl; res = false; } res = res && TestBalance(btf, leftPage, rightPage); if (MINIBASE_BM->UnpinPage(leftPid, CLEAN) == FAIL) { std::cerr << "Error unpinning left leaf page." << std::endl; res = false; } if (MINIBASE_BM->UnpinPage(rightPid, CLEAN) == FAIL) { std::cerr << "Error unpinning right leaf page." << std::endl; res = false; } // We destroy and rebuild the file before to reduce // dependence on working Delete function. if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; // Create a new tree. btf = new BTreeFile(status, "BTreeTest2"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } // Insert 30 long keys. std::cout << "Inserting 30 large keys..." << std::endl; res = InsertRange(btf, 2, 31, 1, 20); res = res && TestNumLeafPages(btf, 1); res = res && TestNumEntries(btf, 30); // Insert some more nodes with long keys into the tree. // This should cause the tree to split. std::cout << "Causing split with new key in left node..." << std::endl; res = res && InsertKey(btf, 1, 1, 20); res = res && TestNumLeafPages(btf, 2); res = res && TestNumEntries(btf, 31); // Make sure that the tree is balanced. leftPid = btf->GetLeftLeaf(); if (MINIBASE_BM->PinPage(leftPid, (Page *&) leftPage) == FAIL) { std::cerr << "Error pinning left leaf page." << std::endl; res = false; } rightPid = leftPage->GetNextPage(); if (MINIBASE_BM->PinPage(rightPid, (Page *&) rightPage) == FAIL) { std::cerr << "Error pinning right leaf page." << std::endl; res = false; } res = res && TestBalance(btf, leftPage, rightPage); if (MINIBASE_BM->UnpinPage(leftPid, CLEAN) == FAIL) { std::cerr << "Error unpinning left leaf page." << std::endl; res = false; } if (MINIBASE_BM->UnpinPage(rightPid, CLEAN) == FAIL) { std::cerr << "Error unpinning right leaf page." << std::endl; res = false; } if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; // That's all, folks. return res; }
bool BTreeDriver::TestSinglePage() { Status status; BTreeFile *btf; btf = new BTreeFile(status, "BTreeTest1"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "Starting Test 1..." << std::endl; std::cout << "BTreeIndex created successfully." << std::endl; bool res; std::cout << "Inserting 59 initial keys..." << std::endl; res = InsertRange(btf, 1, 59); res = res && TestNumLeafPages(btf, 1); res = res && TestNumEntries(btf, 59); std::cout << "Checking a few individual keys..." << std::endl; res = res && TestAbsent(btf, 0); res = res && TestPresent(btf, 2); res = res && TestPresent(btf, 59); res = res && TestAbsent(btf, 60); std::cout << "Checking scans..." << std::endl; char low[MAX_KEY_LENGTH]; char high[MAX_KEY_LENGTH]; toString(5, low); toString(15, high); BTreeFileScan *scan = btf->OpenScan(low, high); res = res && TestScanCount(scan, 11); delete scan; toString(58, low); toString(64, high); scan = btf->OpenScan(low, high); res = res && TestScanCount(scan, 2); delete scan; toString(0, low); toString(5, high); scan = btf->OpenScan(low, high); res = res && TestScanCount(scan, 5); delete scan; // We destroy and rebuild the file before to reduce // dependence on working Delete function. if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; btf = new BTreeFile(status, "BTreeTest2"); if (status != OK) { std::cerr << "ERROR: Couldn't create a BTreeFile" << std::endl; minibase_errors.show_errors(); std::cerr << "Hit [enter] to continue..." << std::endl; std::cin.get(); exit(1); } std::cout << "Inserting 124 duplicates." << std::endl; res = res && InsertDuplicates(btf, 3, 124); res = res && TestNumLeafPages(btf, 1); res = res && TestNumEntries(btf, 124); if (btf->DestroyFile() != OK) { std::cerr << "Error destroying BTreeFile" << std::endl; res = false; } delete btf; return res; }
//-------------------------------------------------------------------- // JoinMethod::SortFile // // Purpose : Sorts a relation by an integer attribute. // Input : file - pointer to the HeapFile to be sorted. // len - length of the records in the file. (assume fixed size). // offset - offset of the sort attribute from the beginning of the record. // Method : We create a B+-Tree using that attribute as the key. Then // we scan the B+-Tree and insert the records into a new // HeapFile. he HeapFile guarantees that the order of // insertion will be the same as the order of scan later. // Return : The new sorted relation/HeapFile. //-------------------------------------------------------------------- HeapFile* JoinMethod::SortHeapFile(HeapFile *file, int len, int offset) { Status s; Scan *scan; scan = file->OpenScan(s); if (s != OK) { std::cerr << "ERROR : cannot open scan on the heapfile to sort." << std::endl; } // // Scan the HeapFile S, create a new B+Tree and insert the records into B+Tree. // BTreeFile *btree; btree = new BTreeFile (s, "BTree"); char* recPtr = new char[len]; int recLen = len; RecordID rid; char* recKey = new char[100]; while (scan->GetNext(rid, recPtr, recLen) == OK) { int* valPtr = (int*)(recPtr+offset); int val = *valPtr; toString(val,recKey); btree->Insert(recKey, rid); } delete scan; delete [] recKey; //std::cout << "created B+ tree!" << std::endl; HeapFile *sorted = new HeapFile(NULL, s); // create a temp HeapFile if (s != OK) { std::cerr << "Cannot create new file for sortedS\n"; } // Now scan the B+-Tree and insert the records into a // new (sorted) HeapFile. BTreeFileScan* btreeScan = btree->OpenScan(NULL, NULL); //int key; char* keyPtr; while (btreeScan->GetNext(rid, keyPtr) == OK) { //std::cout << "scanning " << rid << " " << keyPtr << std::endl; file->GetRecord (rid, recPtr, recLen); sorted->InsertRecord (recPtr, recLen, rid); } btree->DestroyFile(); delete btree; delete btreeScan; delete [] recPtr; return sorted; }
HeapFile* IndexNestedLoopJoin(JoinSpec specOfR, JoinSpec specOfS) { Status status = OK; // Create a HeapFile for join results HeapFile* joinedFile = new HeapFile(NULL, status); if (OK != status) { cerr << "ERROR: cannot create a file for the joined relation.\n"; return NULL; } int recLenR = specOfR.recLen; int recLenS = specOfS.recLen; int recLenJoined = recLenR + recLenS; char* recR = new char[recLenR]; char* recS = new char[recLenS]; char* recJoined = new char[recLenJoined]; RecordID ridR, ridS, ridJoined; // Build the B+-tree index on the inner relation (S) Scan* scanS = specOfS.file->OpenScan(status); if (OK != status) { cerr << "ERROR: cannot open scan on the relation S heap file.\n"; return NULL; } BTreeFile* bTree = new BTreeFile(status, "IJBT", ATTR_INT, sizeof(int)); while (OK == scanS->GetNext(ridS, recS, recLenS)) { bTree->Insert(recS + specOfS.offset, ridS); } delete scanS; // Iterate through the outer relation (R) and join Scan* scanR = specOfR.file->OpenScan(status); if (OK != status) { cerr << "ERROR: cannot open scan on the relation R heap file.\n"; return NULL; } while (OK == scanR->GetNext(ridR, recR, recLenR)) { int* joinArgR = (int*)&recR[specOfR.offset]; BTreeFileScan* bTreeScan = (BTreeFileScan*)bTree->OpenSearchScan(joinArgR, joinArgR); int key; while (OK == bTreeScan->GetNext(ridS, &key)) { specOfS.file->GetRecord(ridS, recS, recLenS); MakeNewRecord(recJoined, recR, recS, recLenR, recLenS); joinedFile->InsertRecord(recJoined, recLenJoined, ridJoined); } delete bTreeScan; } // Release the allocated resources delete scanR; delete[] recR; delete[] recS; delete[] recJoined; delete bTree; return joinedFile; }