The database can be run with a set of APIs. To create a Database:
DB* Open(std::string name, int max_size, int initial_directory_size, int max_directory_size, int search_alg, int Bloomfilter_num_bits);
It takes the name of the database, the max memtable size (in terms of the number of KV pairs in the memtable), the initial and max directory size for the buffer pool, search algorithm of binary search or B-Tree (0 or 1 respectively) and the number of bits in the bloom filter. If the name corresponds to an existing database, it will be loaded.
Once the pointer to the DB is obtained, its various DB class methods (operations) can be called:
int put(int key, int value);
int get(int key);
int update(int key, int value);
int remove(int key);
struct kv_pairs* scan(int key1, int key2);
For put, update and remove, the return value is 0 on success. For get, the return value is the corresponding value of the key. If the key does not exist, INT_MIN will be returned. The scan function searches for a range of keys and allocates memory on the heap for the return. The return value is a pointer to a kv_pair struct defined as:
struct kv_pairs {
int** kv; // Array of [key, value] pairs
int kv_size; // Size of kv
};
The kv is a pointer to an array of arrays, with each subarray containing [key, value]. And kv_size is the size of the array above, in other words, the length of the returned kv_pairs.
Since the kv_pairs struct is allocated on the heap, we also included a DB method to easily free all the memory allocated for a kv_pairs struct. Simply call:
void freeKVpairs(kv_pairs* p);
Lastly, to close the DB and move any temporary in-memory data to storage:
int Close();
Note that the Close function is a method of the DB class. While Open is a function that can be called on its own.
An example use case of the above:
#define MEM_SIZE 512
#define DIR_INIT 8
#define DIR_MAX 32
#define BIN_SEARCH 0
#define BTREE_SEARCH 1
#define BITS_BLOOM 5
int main()
{
DB* db = Open("db_t", MEM_SIZE, DIR_INIT, DIR_MAX, BTREE_SEARCH, BITS_BLOOM);
db->put(5, 15);
db->put(6, 16);
int value_5 = db->get(5); // returns 15
int value_100 = db->get(100); // returns INT_MIN
db->update(5, 150);
value_5 = db->get(5); // returns 150
db->remove(6);
int value_6 = db->get(6); // returns INT_MIN
db->put(7, 17);
struct kv_pairs* scanned_kv = db->scan(0, 20);
for (int i = 0; i < scanned_kv->kv_size; i++) { // displays the scan result
std::cout << "key: " << scanned_kv->kv[i][0] << "\n";
std::cout << "value: " << scanned_kv->kv[i][1] << "\n";
}
db->set_max_dir_size(16); // set the maximum size of the buffer pool directory to 16 (4 bits)
db->freeKVpairs(scanned_kv); // free the scanned kv pairs
db->Close(); // close DB, transform everything to persistent storage
}