BadgerDB
|
00001 #include <iostream> 00002 #include <stdlib.h> 00003 //#include <stdio.h> 00004 #include <cstring> 00005 #include <memory> 00006 #include "page.h" 00007 #include "buffer.h" 00008 #include "file_iterator.h" 00009 #include "page_iterator.h" 00010 #include "exceptions/file_not_found_exception.h" 00011 #include "exceptions/invalid_page_exception.h" 00012 #include "exceptions/page_not_pinned_exception.h" 00013 #include "exceptions/page_pinned_exception.h" 00014 #include "exceptions/buffer_exceeded_exception.h" 00015 00016 #define PRINT_ERROR(str) \ 00017 { \ 00018 std::cerr << "On Line No:" << __LINE__ << "\n"; \ 00019 std::cerr << str << "\n"; \ 00020 exit(1); \ 00021 } 00022 00023 using namespace badgerdb; 00024 00025 const PageId num = 100; 00026 PageId pid[num], pageno1, pageno2, pageno3, i; 00027 RecordId rid[num], rid2, rid3; 00028 Page *page, *page2, *page3; 00029 char tmpbuf[100]; 00030 BufMgr* bufMgr; 00031 File *file1ptr, *file2ptr, *file3ptr, *file4ptr, *file5ptr; 00032 00033 void test1(); 00034 void test2(); 00035 void test3(); 00036 void test4(); 00037 void test5(); 00038 void test6(); 00039 void testBufMgr(); 00040 00041 int main() 00042 { 00043 //Following code shows how to you File and Page classes 00044 00045 const std::string& filename = "test.db"; 00046 // Clean up from any previous runs that crashed. 00047 try 00048 { 00049 File::remove(filename); 00050 } 00051 catch(FileNotFoundException) 00052 { 00053 } 00054 00055 { 00056 // Create a new database file. 00057 File new_file = File::create(filename); 00058 00059 // Allocate some pages and put data on them. 00060 PageId third_page_number; 00061 for (int i = 0; i < 5; ++i) { 00062 Page new_page = new_file.allocatePage(); 00063 if (i == 3) { 00064 // Keep track of the identifier for the third page so we can read it 00065 // later. 00066 third_page_number = new_page.page_number(); 00067 } 00068 new_page.insertRecord("hello!"); 00069 // Write the page back to the file (with the new data). 00070 new_file.writePage(new_page); 00071 } 00072 00073 // Iterate through all pages in the file. 00074 for (FileIterator iter = new_file.begin(); 00075 iter != new_file.end(); 00076 ++iter) { 00077 // Iterate through all records on the page. 00078 for (PageIterator page_iter = (*iter).begin(); 00079 page_iter != (*iter).end(); 00080 ++page_iter) { 00081 std::cout << "Found record: " << *page_iter 00082 << " on page " << (*iter).page_number() << "\n"; 00083 } 00084 } 00085 00086 // Retrieve the third page and add another record to it. 00087 Page third_page = new_file.readPage(third_page_number); 00088 const RecordId& rid = third_page.insertRecord("world!"); 00089 new_file.writePage(third_page); 00090 00091 // Retrieve the record we just added to the third page. 00092 std::cout << "Third page has a new record: " 00093 << third_page.getRecord(rid) << "\n\n"; 00094 } 00095 // new_file goes out of scope here, so file is automatically closed. 00096 00097 // Delete the file since we're done with it. 00098 File::remove(filename); 00099 00100 //This function tests buffer manager, comment this line if you don't wish to test buffer manager 00101 testBufMgr(); 00102 } 00103 00104 void testBufMgr() 00105 { 00106 // create buffer manager 00107 bufMgr = new BufMgr(num); 00108 00109 // create dummy files 00110 const std::string& filename1 = "test.1"; 00111 const std::string& filename2 = "test.2"; 00112 const std::string& filename3 = "test.3"; 00113 const std::string& filename4 = "test.4"; 00114 const std::string& filename5 = "test.5"; 00115 00116 try 00117 { 00118 File::remove(filename1); 00119 File::remove(filename2); 00120 File::remove(filename3); 00121 File::remove(filename4); 00122 File::remove(filename5); 00123 } 00124 catch(FileNotFoundException e) 00125 { 00126 } 00127 00128 File file1 = File::create(filename1); 00129 File file2 = File::create(filename2); 00130 File file3 = File::create(filename3); 00131 File file4 = File::create(filename4); 00132 File file5 = File::create(filename5); 00133 00134 file1ptr = &file1; 00135 file2ptr = &file2; 00136 file3ptr = &file3; 00137 file4ptr = &file4; 00138 file5ptr = &file5; 00139 00140 //Test buffer manager 00141 //Comment tests which you do not wish to run now. Tests are dependent on their preceding tests. So, they have to be run in the following order. 00142 //Commenting a particular test requires commenting all tests that follow it else those tests would fail. 00143 test1(); 00144 test2(); 00145 test3(); 00146 test4(); 00147 test5(); 00148 test6(); 00149 00150 //Close files before deleting them 00151 file1.~File(); 00152 file2.~File(); 00153 file3.~File(); 00154 file4.~File(); 00155 file5.~File(); 00156 00157 //Delete files 00158 File::remove(filename1); 00159 File::remove(filename2); 00160 File::remove(filename3); 00161 File::remove(filename4); 00162 File::remove(filename5); 00163 00164 delete bufMgr; 00165 00166 std::cout << "\n" << "Passed all tests." << "\n"; 00167 } 00168 00169 void test1() 00170 { 00171 //Allocating pages in a file... 00172 for (i = 0; i < num; i++) 00173 { 00174 bufMgr->allocPage(file1ptr, pid[i], page); 00175 sprintf((char*)tmpbuf, "test.1 Page %d %7.1f", pid[i], (float)pid[i]); 00176 rid[i] = page->insertRecord(tmpbuf); 00177 bufMgr->unPinPage(file1ptr, pid[i], true); 00178 } 00179 00180 //Reading pages back... 00181 for (i = 0; i < num; i++) 00182 { 00183 bufMgr->readPage(file1ptr, pid[i], page); 00184 sprintf((char*)&tmpbuf, "test.1 Page %d %7.1f", pid[i], (float)pid[i]); 00185 if(strncmp(page->getRecord(rid[i]).c_str(), tmpbuf, strlen(tmpbuf)) != 0) 00186 { 00187 PRINT_ERROR("ERROR :: CONTENTS DID NOT MATCH"); 00188 } 00189 bufMgr->unPinPage(file1ptr, pid[i], false); 00190 } 00191 std::cout<< "Test 1 passed" << "\n"; 00192 } 00193 00194 void test2() 00195 { 00196 //Writing and reading back multiple files 00197 //The page number and the value should match 00198 00199 for (i = 0; i < num/3; i++) 00200 { 00201 bufMgr->allocPage(file2ptr, pageno2, page2); 00202 sprintf((char*)tmpbuf, "test.2 Page %d %7.1f", pageno2, (float)pageno2); 00203 rid2 = page2->insertRecord(tmpbuf); 00204 00205 int index = random() % num; 00206 pageno1 = pid[index]; 00207 bufMgr->readPage(file1ptr, pageno1, page); 00208 sprintf((char*)tmpbuf, "test.1 Page %d %7.1f", pageno1, (float)pageno1); 00209 if(strncmp(page->getRecord(rid[index]).c_str(), tmpbuf, strlen(tmpbuf)) != 0) 00210 { 00211 PRINT_ERROR("ERROR :: CONTENTS DID NOT MATCH"); 00212 } 00213 00214 bufMgr->allocPage(file3ptr, pageno3, page3); 00215 sprintf((char*)tmpbuf, "test.3 Page %d %7.1f", pageno3, (float)pageno3); 00216 rid3 = page3->insertRecord(tmpbuf); 00217 00218 bufMgr->readPage(file2ptr, pageno2, page2); 00219 sprintf((char*)&tmpbuf, "test.2 Page %d %7.1f", pageno2, (float)pageno2); 00220 if(strncmp(page2->getRecord(rid2).c_str(), tmpbuf, strlen(tmpbuf)) != 0) 00221 { 00222 PRINT_ERROR("ERROR :: CONTENTS DID NOT MATCH"); 00223 } 00224 00225 bufMgr->readPage(file3ptr, pageno3, page3); 00226 sprintf((char*)&tmpbuf, "test.3 Page %d %7.1f", pageno3, (float)pageno3); 00227 if(strncmp(page3->getRecord(rid3).c_str(), tmpbuf, strlen(tmpbuf)) != 0) 00228 { 00229 PRINT_ERROR("ERROR :: CONTENTS DID NOT MATCH"); 00230 } 00231 00232 bufMgr->unPinPage(file1ptr, pageno1, false); 00233 } 00234 00235 for (i = 0; i < num/3; i++) { 00236 bufMgr->unPinPage(file2ptr, i+1, true); 00237 bufMgr->unPinPage(file2ptr, i+1, true); 00238 bufMgr->unPinPage(file3ptr, i+1, true); 00239 bufMgr->unPinPage(file3ptr, i+1, true); 00240 } 00241 00242 std::cout << "Test 2 passed" << "\n"; 00243 } 00244 00245 void test3() 00246 { 00247 try 00248 { 00249 bufMgr->readPage(file4ptr, 1, page); 00250 PRINT_ERROR("ERROR :: File4 should not exist. Exception should have been thrown before execution reaches this point."); 00251 } 00252 catch(InvalidPageException e) 00253 { 00254 } 00255 00256 std::cout << "Test 3 passed" << "\n"; 00257 } 00258 00259 void test4() 00260 { 00261 bufMgr->allocPage(file4ptr, i, page); 00262 bufMgr->unPinPage(file4ptr, i, true); 00263 try 00264 { 00265 bufMgr->unPinPage(file4ptr, i, false); 00266 PRINT_ERROR("ERROR :: Page is already unpinned. Exception should have been thrown before execution reaches this point."); 00267 } 00268 catch(PageNotPinnedException e) 00269 { 00270 } 00271 00272 std::cout << "Test 4 passed" << "\n"; 00273 } 00274 00275 void test5() 00276 { 00277 for (i = 0; i < num; i++) { 00278 bufMgr->allocPage(file5ptr, pid[i], page); 00279 sprintf((char*)tmpbuf, "test.5 Page %d %7.1f", pid[i], (float)pid[i]); 00280 rid[i] = page->insertRecord(tmpbuf); 00281 } 00282 00283 PageId tmp; 00284 try 00285 { 00286 bufMgr->allocPage(file5ptr, tmp, page); 00287 PRINT_ERROR("ERROR :: No more frames left for allocation. Exception should have been thrown before execution reaches this point."); 00288 } 00289 catch(BufferExceededException e) 00290 { 00291 } 00292 00293 std::cout << "Test 5 passed" << "\n"; 00294 00295 for (i = 1; i <= num; i++) 00296 bufMgr->unPinPage(file5ptr, i, true); 00297 } 00298 00299 void test6() 00300 { 00301 //flushing file with pages still pinned. Should generate an error 00302 for (i = 1; i <= num; i++) { 00303 bufMgr->readPage(file1ptr, i, page); 00304 } 00305 00306 try 00307 { 00308 bufMgr->flushFile(file1ptr); 00309 PRINT_ERROR("ERROR :: Pages pinned for file being flushed. Exception should have been thrown before execution reaches this point."); 00310 } 00311 catch(PagePinnedException e) 00312 { 00313 } 00314 00315 std::cout << "Test 6 passed" << "\n"; 00316 00317 for (i = 1; i <= num; i++) 00318 bufMgr->unPinPage(file1ptr, i, true); 00319 00320 bufMgr->flushFile(file1ptr); 00321 }