WiscDB
|
The files in this package are organized under the following hierarchy:
include/ header files for provided classes lib/ object files for provided classes (File, Page) exceptions/ library of exceptions defined for WiscDB . main code for WiscDB, Lab 1
You will likely be most interested in files in the main directory
All command examples are meant to be run at the command prompt from the wiscdb
directory. When executing a command, omit the $
prompt (so “$ make
” means you just type “make
” and press enter).
To build the executable:
$ make
To run the executable, first build the code, then run:
$ ./wiscdb_main
If you want to edit what wiscdb_main
does, edit main.cpp
.
Documentation is generated by using Doxygen. If you have updated the documentation and need to regenerate the output files, run:
$ make doc
Resulting documentation will be placed in the docs/
directory; open index.html
with your web browser to view it.
Interaction with the underlying filesystem is handled by two classes: File and Page. Files store zero or more fixed-length pages; each page holds zero or more variable-length records.
Record data is represented using std::strings of arbitrary characters.
Files must first be created before they can be used:
// Create and open a new file with the name "filename.db". wiscdb::File new_file = wiscdb::File::create("filename.db");
If you want to open an existing file, use File::open like so:
// Open an existing file with the name "filename.db". wiscdb::File existing_file = wiscdb::File::open("filename.db");
Multiple File objects share the same stream to the underlying file. The stream will be automatically closed when the last File object is out of scope; no explicit close command is necessary.
You can delete a file with File::remove:
// Delete a file with the name "filename.db". wiscdb::File::remove("filename.db");
Data is added to a File by first allocating a Page, populating it with data, and then writing the Page back to the File.
For example:
#include "file.h" ... // Write a record with the value "hello, world!" to the file. wiscdb::File db_file = wiscdb::File::open("filename.db"); wiscdb::Page new_page = db_file.allocatePage(); new_page.insertRecord("hello, world!"); db_file.writePage(new_page);
Pages are read back from a File using their page numbers:
#include "file.h" #include "page.h" ... // Allocate a page and then read it back. wiscdb::Page new_page = db_file.allocatePage(); db_file.writePage(new_page); const wiscdb::PageId& page_number = new_page.page_number(); wiscdb::Page same_page = db_file.readPage(page_number);
You can also iterate through all pages in the File:
#include "file_iterator.h" ... for (wiscdb::FileIterator iter = db_file.begin(); iter != db_file.end(); ++iter) { std::cout << "Read page: " << iter->page_number() << std::endl; }
Pages hold variable-length records containing arbitrary data.
To insert data on a page:
#include "page.h" ... wiscdb::Page new_page; new_page.insertRecord("hello, world!");
Data is read by using RecordIds, which are provided when data is inserted:
#include "page.h" ... wiscdb::Page new_page; const wiscdb::RecordId& rid = new_page.insertRecord("hello, world!"); new_page.getRecord(rid); // returns "hello, world!"
As Pages use std::string to represent data, it's very natural to insert strings; however, any data can be stored:
#include "page.h" ... struct Point { int x; int y; }; Point new_point = {10, -5}; wiscdb::Page new_page; std::string new_data(reinterpret_cast<char*>(&new_point), sizeof(new_point)); const wiscdb::RecordId& rid = new_page.insertRecord(new_data); Point read_point = *reinterpret_cast<const Point*>(new_page.getRecord(rid).data());
Note that serializing structures like this is not industrial strength; it's better to use something like Google's protocol buffers or Boost serialization.
You can also iterate through all records in the Page:
#include "page_iterator.h" ... for (wiscdb::PageIterator iter = new_page.begin(); iter != new_page.end(); ++iter) { std::cout << "Record data: " << *iter << std::endl;