BadgerDB
 All Classes Namespaces Functions Variables Typedefs Friends Pages
main.cpp
1 #include <iostream>
2 #include <stdlib.h>
3 //#include <stdio.h>
4 #include <cstring>
5 #include <memory>
6 #include "page.h"
7 #include "buffer.h"
8 #include "file_iterator.h"
9 #include "page_iterator.h"
10 #include "exceptions/file_not_found_exception.h"
11 #include "exceptions/invalid_page_exception.h"
12 #include "exceptions/page_not_pinned_exception.h"
13 #include "exceptions/page_pinned_exception.h"
14 #include "exceptions/buffer_exceeded_exception.h"
15 
16 #define PRINT_ERROR(str) \
17 { \
18  std::cerr << "On Line No:" << __LINE__ << "\n"; \
19  std::cerr << str << "\n"; \
20  exit(1); \
21 }
22 
23 using namespace badgerdb;
24 
25 const PageId num = 100;
26 PageId pid[num], pageno1, pageno2, pageno3, i;
27 RecordId rid[num], rid2, rid3;
28 Page *page, *page2, *page3;
29 char tmpbuf[100];
30 BufMgr* bufMgr;
31 File *file1ptr, *file2ptr, *file3ptr, *file4ptr, *file5ptr;
32 
33 void test1();
34 void test2();
35 void test3();
36 void test4();
37 void test5();
38 void test6();
39 void testBufMgr();
40 
41 int main()
42 {
43  //Following code shows how to you File and Page classes
44 
45  const std::string& filename = "test.db";
46  // Clean up from any previous runs that crashed.
47  try
48  {
49  File::remove(filename);
50  }
52  {
53  }
54 
55  {
56  // Create a new database file.
57  File new_file = File::create(filename);
58 
59  // Allocate some pages and put data on them.
60  PageId third_page_number;
61  for (int i = 0; i < 5; ++i) {
62  Page new_page = new_file.allocatePage();
63  if (i == 3) {
64  // Keep track of the identifier for the third page so we can read it
65  // later.
66  third_page_number = new_page.page_number();
67  }
68  new_page.insertRecord("hello!");
69  // Write the page back to the file (with the new data).
70  new_file.writePage(new_page);
71  }
72 
73  // Iterate through all pages in the file.
74  for (FileIterator iter = new_file.begin();
75  iter != new_file.end();
76  ++iter) {
77  // Iterate through all records on the page.
78  for (PageIterator page_iter = (*iter).begin();
79  page_iter != (*iter).end();
80  ++page_iter) {
81  std::cout << "Found record: " << *page_iter
82  << " on page " << (*iter).page_number() << "\n";
83  }
84  }
85 
86  // Retrieve the third page and add another record to it.
87  Page third_page = new_file.readPage(third_page_number);
88  const RecordId& rid = third_page.insertRecord("world!");
89  new_file.writePage(third_page);
90 
91  // Retrieve the record we just added to the third page.
92  std::cout << "Third page has a new record: "
93  << third_page.getRecord(rid) << "\n\n";
94  }
95  // new_file goes out of scope here, so file is automatically closed.
96 
97  // Delete the file since we're done with it.
98  File::remove(filename);
99 
100  //This function tests buffer manager, comment this line if you don't wish to test buffer manager
101  testBufMgr();
102 }
103 
104 void testBufMgr()
105 {
106  // create buffer manager
107  bufMgr = new BufMgr(num);
108 
109  // create dummy files
110  const std::string& filename1 = "test.1";
111  const std::string& filename2 = "test.2";
112  const std::string& filename3 = "test.3";
113  const std::string& filename4 = "test.4";
114  const std::string& filename5 = "test.5";
115 
116  try
117  {
118  File::remove(filename1);
119  File::remove(filename2);
120  File::remove(filename3);
121  File::remove(filename4);
122  File::remove(filename5);
123  }
124  catch(FileNotFoundException e)
125  {
126  }
127 
128  File file1 = File::create(filename1);
129  File file2 = File::create(filename2);
130  File file3 = File::create(filename3);
131  File file4 = File::create(filename4);
132  File file5 = File::create(filename5);
133 
134  file1ptr = &file1;
135  file2ptr = &file2;
136  file3ptr = &file3;
137  file4ptr = &file4;
138  file5ptr = &file5;
139 
140  //Test buffer manager
141  //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.
142  //Commenting a particular test requires commenting all tests that follow it else those tests would fail.
143  test1();
144  test2();
145  test3();
146  test4();
147  test5();
148  test6();
149 
150  //Close files before deleting them
151  file1.~File();
152  file2.~File();
153  file3.~File();
154  file4.~File();
155  file5.~File();
156 
157  //Delete files
158  File::remove(filename1);
159  File::remove(filename2);
160  File::remove(filename3);
161  File::remove(filename4);
162  File::remove(filename5);
163 
164  delete bufMgr;
165 
166  std::cout << "\n" << "Passed all tests." << "\n";
167 }
168 
169 void test1() // TEST allocate and read page
170 {
171  //Allocating pages in a file...
172  for (i = 0; i < num; i++)
173  {
174  bufMgr->allocPage(file1ptr, pid[i], page);
175  sprintf((char*)tmpbuf, "test.1 Page %d %7.1f", pid[i], (float)pid[i]);
176  rid[i] = page->insertRecord(tmpbuf);
177  bufMgr->unPinPage(file1ptr, pid[i], true);
178  }
179 
180  //Reading pages back...
181  for (i = 0; i < num; i++)
182  {
183  bufMgr->readPage(file1ptr, pid[i], page);
184  sprintf((char*)&tmpbuf, "test.1 Page %d %7.1f", pid[i], (float)pid[i]);
185  if(strncmp(page->getRecord(rid[i]).c_str(), tmpbuf, strlen(tmpbuf)) != 0)
186  {
187  PRINT_ERROR("ERROR :: CONTENTS DID NOT MATCH");
188  }
189  bufMgr->unPinPage(file1ptr, pid[i], false);
190  }
191  std::cout<< "Test 1 passed" << "\n";
192 }
193 
194 void test2() // TEST write and read back multiple files
195 {
196  //Writing and reading back multiple files
197  //The page number and the value should match
198 
199  for (i = 0; i < num/3; i++)
200  {
201  bufMgr->allocPage(file2ptr, pageno2, page2);
202  sprintf((char*)tmpbuf, "test.2 Page %d %7.1f", pageno2, (float)pageno2);
203  rid2 = page2->insertRecord(tmpbuf);
204 
205  int index = rand() % num;
206  pageno1 = pid[index];
207  bufMgr->readPage(file1ptr, pageno1, page);
208  sprintf((char*)tmpbuf, "test.1 Page %d %7.1f", pageno1, (float)pageno1);
209  if(strncmp(page->getRecord(rid[index]).c_str(), tmpbuf, strlen(tmpbuf)) != 0)
210  {
211  PRINT_ERROR("ERROR :: CONTENTS DID NOT MATCH");
212  }
213 
214  bufMgr->allocPage(file3ptr, pageno3, page3);
215  sprintf((char*)tmpbuf, "test.3 Page %d %7.1f", pageno3, (float)pageno3);
216  rid3 = page3->insertRecord(tmpbuf);
217 
218  bufMgr->readPage(file2ptr, pageno2, page2);
219  sprintf((char*)&tmpbuf, "test.2 Page %d %7.1f", pageno2, (float)pageno2);
220  if(strncmp(page2->getRecord(rid2).c_str(), tmpbuf, strlen(tmpbuf)) != 0)
221  {
222  PRINT_ERROR("ERROR :: CONTENTS DID NOT MATCH");
223  }
224 
225  bufMgr->readPage(file3ptr, pageno3, page3);
226  sprintf((char*)&tmpbuf, "test.3 Page %d %7.1f", pageno3, (float)pageno3);
227  if(strncmp(page3->getRecord(rid3).c_str(), tmpbuf, strlen(tmpbuf)) != 0)
228  {
229  PRINT_ERROR("ERROR :: CONTENTS DID NOT MATCH");
230  }
231 
232  bufMgr->unPinPage(file1ptr, pageno1, false);
233  }
234 
235  for (i = 0; i < num/3; i++) {
236  bufMgr->unPinPage(file2ptr, i+1, true);
237  bufMgr->unPinPage(file2ptr, i+1, true);
238  bufMgr->unPinPage(file3ptr, i+1, true);
239  bufMgr->unPinPage(file3ptr, i+1, true);
240  }
241 
242  std::cout << "Test 2 passed" << "\n";
243 }
244 
245 void test3() // TEST readPage with none-exist file
246 {
247  try
248  {
249  bufMgr->readPage(file4ptr, 1, page);
250  PRINT_ERROR("ERROR :: File4 should not exist. Exception should have been thrown before execution reaches this point.");
251  }
252  catch(InvalidPageException e)
253  {
254  }
255 
256  std::cout << "Test 3 passed" << "\n";
257 }
258 
259 void test4() // TEST unPinPage
260 {
261  bufMgr->allocPage(file4ptr, i, page);
262  bufMgr->unPinPage(file4ptr, i, true);
263  try
264  {
265  bufMgr->unPinPage(file4ptr, i, false);
266  PRINT_ERROR("ERROR :: Page is already unpinned. Exception should have been thrown before execution reaches this point.");
267  }
268  catch(PageNotPinnedException e)
269  {
270  }
271 
272  std::cout << "Test 4 passed" << "\n";
273 }
274 
275 void test5() // TEST allocBuf when buffer full
276 {
277  for (i = 0; i < num; i++) {
278  bufMgr->allocPage(file5ptr, pid[i], page);
279  sprintf((char*)tmpbuf, "test.5 Page %d %7.1f", pid[i], (float)pid[i]);
280  rid[i] = page->insertRecord(tmpbuf);
281  }
282 
283  PageId tmp;
284  try
285  {
286  bufMgr->allocPage(file5ptr, tmp, page);
287  PRINT_ERROR("ERROR :: No more frames left for allocation. Exception should have been thrown before execution reaches this point.");
288  }
289  catch(BufferExceededException e)
290  {
291  }
292 
293  std::cout << "Test 5 passed" << "\n";
294 
295  for (i = 1; i <= num; i++)
296  bufMgr->unPinPage(file5ptr, i, true);
297 }
298 
299 void test6() // TEST flush file with pinned pages
300 {
301  //flushing file with pages still pinned. Should generate an error
302  for (i = 1; i <= num; i++) {
303  bufMgr->readPage(file1ptr, i, page);
304  }
305 
306  try
307  {
308  bufMgr->flushFile(file1ptr);
309  PRINT_ERROR("ERROR :: Pages pinned for file being flushed. Exception should have been thrown before execution reaches this point.");
310  }
311  catch(PagePinnedException e)
312  {
313  }
314 
315  std::cout << "Test 6 passed" << "\n";
316 
317  for (i = 1; i <= num; i++)
318  bufMgr->unPinPage(file1ptr, i, true);
319 
320  bufMgr->flushFile(file1ptr);
321 }
322 
323 // User new test
324 void test7()
325 {
326 
327  for (i = 1; i <= num; i++) {
328  bufMgr->readPage(file1ptr, i, page);
329  }
330  try {
331  bufMgr->disposePage(file1ptr,0);
332  PRINT_ERROR("ERROR :: This should delete the first page in file.");
333  }
334 
335 }
336 
337 
An exception that is thrown when a page which is expected to be pinned in the buffer pool is found to...
FileIterator begin()
Definition: file.cpp:214
FileIterator end()
Definition: file.cpp:219
The central class which manages the buffer pool including frame allocation and deallocation to pages ...
Definition: buffer.h:160
void readPage(File *file, const PageId PageNo, Page *&page)
Definition: buffer.cpp:117
std::string getRecord(const RecordId &record_id) const
Definition: page.cpp:43
Iterator for iterating over the records in a page.
Definition: page_iterator.h:23
Class which represents a file in the filesystem containing database pages.
Definition: file.h:73
void unPinPage(File *file, const PageId PageNo, const bool dirty)
Definition: buffer.cpp:133
static File create(const std::string &filename)
Definition: file.cpp:29
std::uint32_t PageId
Identifier for a page in a file.
Definition: types.h:15
An exception that is thrown when a file operation is requested for a filename that doesn't exist...
An exception that is thrown when an attempt is made to access an invalid page in a file...
Class which represents a fixed-size database page containing records.
Definition: page.h:107
void writePage(const Page &new_page)
Definition: file.cpp:169
void flushFile(const File *file)
Definition: buffer.cpp:148
PageId page_number() const
Definition: page.h:193
Iterator for iterating over the pages in a file.
Definition: file_iterator.h:23
static void remove(const std::string &filename)
Definition: file.cpp:37
An exception that is thrown when a page which is not expected to be pinned in the buffer pool is foun...
Page readPage(const PageId page_number) const
Definition: file.cpp:149
Page allocatePage()
Definition: file.cpp:84
void disposePage(File *file, const PageId PageNo)
Definition: buffer.cpp:191
Identifier for a record in a page.
Definition: types.h:30
An exception that is thrown when buffer capacity is exceeded.
void allocPage(File *file, PageId &PageNo, Page *&page)
Definition: buffer.cpp:177
RecordId insertRecord(const std::string &record_data)
Definition: page.cpp:33