COMP9315 db

#include
#include
#include
#include
// #include
#include
#include
#include
#include “db.h”

Conf* cf = NULL;
Database* db = NULL;

Conf* init_conf(const UINT page_size, const UINT buf_slots, const UINT file_limit, const char* buf_policy){
cf = malloc(sizeof(Conf));
cf->page_size = page_size;
cf->buf_slots = buf_slots;
cf->file_limit = file_limit;
strcpy(cf->buf_policy,buf_policy);
return cf;

void free_conf(){

Conf* get_conf(){
return cf;

Database* get_db(){
return db;

void free_db(){
if (db != NULL) free(db);

// build database
Database* init_db(char* input_data_path, char* data_path){

// check if db folder exists
struct stat st = {0};
if(stat(data_path, &st) == -1){
printf(“Database folder does not exist. Create the folder %s.\n”,data_path);
mkdir(data_path, 0777);

db = NULL;

// open the input data file
FILE* input_fp = fopen(input_data_path,”r”);
printf(“Input data path:%s\n”,input_data_path);
if (input_fp == NULL){
perror(“Fail to open the input data file.\n”);

// file pointer to write tuples
FILE* table_fp = NULL;

INT table_idx = -1;
INT ntuples_per_page = 0;
INT nbytes_free = 0;

INT processed_ntuples = 0;

UINT64 page_id = 0;

char line[100];
while(fgets(line,100,input_fp)){

// lines to write comments
if(line[0] == ‘#’) continue;

// line for database meta info
if(line[0] == ‘d’){
UINT ntables;
char desc[50];

// get number of tables
sscanf(line,”%s %d”,desc,&ntables);

// initialize Database instance
db = malloc(sizeof(Database)+ntables*sizeof(Table));
db->ntables = ntables;
strcpy(db->path,data_path);

// printf(“data path: %s\n”,db->path);

// line for table meta info
if(line[0] == ‘t’){

++table_idx;

// close the old one if exists
if(table_idx > 0){
// the current table is not the first

if(processed_ntuples != 0){
// the last page is not full
// add 0 to the end
INT8 f = 0;
UINT left_space = sizeof(INT)*t.nattrs*(ntuples_per_page-processed_ntuples)+nbytes_free;

for (UINT i = 0; i < left_space; i++) fwrite(&f,sizeof(INT8),1,table_fp); processed_ntuples = 0; fclose(table_fp); char desc[50]; // initialzie a table instance // Table t; sscanf(line,"%s %u %s %u",desc,&t.oid,t.name,&t.nattrs); t.ntuples = 0; // add the table pointer to the DB instance db->tables[table_idx] = t;

// produce table file path
char table_path[200];
sprintf(table_path,”%s/%u”,db->path,t.oid);
// open file pointer for the table
table_fp = fopen(table_path,”wb”);

// reset page id
page_id = 0;

// calculate number of tuples per page
ntuples_per_page = (cf->page_size-sizeof(UINT64))/sizeof(INT)/t.nattrs;
nbytes_free = (cf->page_size-sizeof(UINT64)) % (sizeof(INT)*t.nattrs);
// printf(“ntuples = %u, free bytes = %u\n”,ntuples_per_page,nbytes_free);

processed_ntuples = 0;

// skip empty lines
if(!isdigit(line[0])) continue;

// we are processing the first tuple for a page
if(processed_ntuples == 0){
// write a page id to the file
fwrite(&page_id,sizeof(UINT64),1,table_fp);
++page_id;
++processed_ntuples;
++db->tables[table_idx].ntuples;
// printf(“processed tuples = %u, tuples per page = %u\n”,processed_ntuples,ntuples_per_page);

// write tuple to file
// assume each table has only one file

char* token = strtok(line,” “);

while(token != NULL){

// read each attribute and write it to the hard drive
sscanf(token,”%d”,&attr);

fwrite(&attr,sizeof(INT),1,table_fp);

token = strtok(NULL,” “);

// when the derived number of tuples reaches the maximum number of tuples per page
// we add 0 to the end if necessary
if(processed_ntuples == ntuples_per_page){
INT8 f = 0;
for (UINT i = 0; i < nbytes_free; i++) fwrite(&f,sizeof(INT8),1,table_fp); processed_ntuples = 0; if(processed_ntuples != 0){ // the last page is not full // add 0 to the end INT8 f = 0; UINT left_space = sizeof(INT)*t.nattrs*(ntuples_per_page-processed_ntuples)+nbytes_free; for (UINT i = 0; i < left_space; i++) fwrite(&f,sizeof(INT8),1,table_fp); processed_ntuples = 0; fclose(table_fp); fclose(input_fp); return db; void reset_IO(){ cf->read_io = 0;
cf->write_io = 0;

void log_read_page(UINT64 pid){
// the following print info is for testing
// comment it out to avoid too much output in terminal when developing
// printf(“Read page %llu\n”,pid);
cf->read_io ++;
void log_release_page(UINT64 pid){
// the following print info is for testing
// comment it out to avoid too much output in terminal when developing
// printf(“Release page %llu\n”,pid);

void log_open_file(UINT oid){
// the following print info is for testing
// comment it out to avoid too much output in terminal when developing
// printf(“Open file %u\n”,oid);
void log_close_file(UINT oid){
// the following print info is for testing
// comment it out to avoid too much output in terminal when developing
// printf(“Close file %u\n”,oid);