static inline void persist_col(struct column *col, const char *tname) { if (col->status == ONDISK || col->status == INMEMORY) return; char buf[PATHLEN]; char *path = vbsnprintf(buf, sizeof buf, "%s/%s.%s.bin", DBPATH, tname, col->name); cs165_log(stderr, "%s: %s\n", tname, path); persist_data(col->data.vals, col->data.sz, sizeof (int), path); if (path != buf) free(path); if (col->index) persist_index(col, col->table->name); }
/** * parse_command takes as input the send_message from the client and then * parses it into the appropriate query. Stores into send_message the * status to send back. * Returns a db_operator. **/ db_operator* parse_command(message* recv_message, message* send_message, status* parse_status) { send_message->status = OK_WAIT_FOR_RESPONSE; // check load flags here db_operator *dbo = init_dbo(); // Here you parse the message and fill in the proper db_operator fields for // now we just log the payload cs165_log(stdout, recv_message->payload); // Here, we give you a default parser, you are welcome to replace it with anything you want *parse_status = parse_command_string(recv_message->payload, dsl_commands, dbo); return dbo; }
static inline void persist_index(struct column *col, const char *tname) { char buf[PATHLEN]; char *path; switch(col->index->type) { case SORTED: path = vbsnprintf(buf, sizeof buf, "%s/%s.%s.sorted.bin", DBPATH, tname, col->name); cs165_log(stderr, "%s: %s\n", tname, path); persist_data(col->index->index, col->data.sz, sizeof (struct sindex), path); if (path != buf) free(path); case BTREE: break; // TODO: expensive, easier to fully reconstruct case IDX_INVALID: break; } }
static void restore_col_data(struct column *col) { char *tname = col->table->name; char buf[PATHLEN]; char *path = vbsnprintf(buf, sizeof buf, "%s/%s.%s.bin", DBPATH, tname, col->name); char *data; off_t sz = filemap(path, &data, PROT_READ); vector_init(&col->data, col->table->length); memcpy(col->data.vals, data, sz); col->data.sz = sz / sizeof (int); col->data.capacity = col->data.sz; col->status = INMEMORY; cs165_log(stdout, "col capacity %d, %d\n", col->data.sz, col->data.vals[col->data.sz-1]); fileunmap(data, sz); }
size_t sindex_find(int **v, int value, size_t sz, struct sindex *idx) { int ret = sindex_index_of(idx, value, sz); if (ret == -1) { *v = NULL; return 0; } int low_idx = sindex_search_until(idx, sz, ret, value, false); int high_idx = sindex_search_until(idx, sz, ret, value, true); size_t num_tuples = high_idx - low_idx + 1; cs165_log(stderr, "select_clustered: %zu %zu %zu\n", low_idx, high_idx, num_tuples); int *vec = malloc(num_tuples * sizeof *vec); for (size_t j = 0, k = low_idx; j < num_tuples; j++) vec[j] = idx[k+j].pos; *v = vec; return num_tuples; }
static struct column restore_col(char *record, struct table *tbl) { struct col_record *rec = (struct col_record *) record; bool clustered = tbl->clustered == tbl->col_count; struct column col = { .name = strdup(rec->name), .table = tbl, .index = NULL, .clustered = clustered, .status = ONDISK, .data = { 0, 0, NULL } }; cs165_log(stderr, "clustered = %d\n", col.clustered); enum index_type idx_type = rec->idx_type - '0'; switch(idx_type) { case IDX_INVALID: break; case SORTED: case BTREE: col.index = malloc(sizeof(struct column_index)); col.index->type = idx_type; col.index->index = NULL; break; } return col; } static struct table restore_tbl(char *record, size_t *col_count) { struct tbl_record *rec = (struct tbl_record *) record; struct table tbl = { .name = strdup(rec->name), .length = rec->length, .clustered = rec->clustered, .col_count = 0 }; tbl.col = malloc(sizeof(struct column) * rec->col_count); *col_count = rec->col_count; return tbl; } static struct db *restore_db(char *record) { struct db_record *rec = (struct db_record *) record; struct db *db = malloc(sizeof *db); assert (db); db->table_count = 0; db->capacity = rec->capacity; db->tables = malloc(sizeof(struct table) * db->capacity); assert(db->tables); db->name = strdup(rec->name); return db; } static struct db *restore(char *meta, size_t sz) { enum meta_state state = DB_RECORD; struct db *db; struct table *tbl; struct column *col; char *rec; size_t col_count = 0, prev = 0; char varbuf[VARNAME_SIZE]; for (size_t j = 0; j < sz; j++) { if (meta[j] == '|') { meta[j] = '\0'; rec = &meta[prev]; prev = j + 1; switch(state) { case DB_RECORD: db = restore_db(rec); //map_insert(db->name, db, ENTITY); state = TBL_RECORD; break; case TBL_RECORD: db->tables[db->table_count] = restore_tbl(rec, &col_count); tbl = &db->tables[db->table_count++]; snprintf(varbuf, sizeof varbuf, "%s.%s", db->name, tbl->name); map_insert(strdup(varbuf), tbl, ENTITY); state = COL_RECORD; break; case COL_RECORD: tbl->col[tbl->col_count] = restore_col(rec, tbl); col = &tbl->col[tbl->col_count++]; snprintf(varbuf, sizeof varbuf, "%s.%s.%s", db->name, tbl->name, col->name); map_insert(strdup(varbuf), col, ENTITY); if (col_count == tbl->col_count) state = TBL_RECORD; break; } } } assert(state == TBL_RECORD); assert(db->table_count <= db->capacity); return db; } static struct db *restore_meta(void) { char buf[PATHLEN]; char *path = vbsnprintf(buf, sizeof buf, "%s/%s.bin", DBPATH, METAFILE); char *meta; off_t sz = filemap(path, &meta, PROT_READ | PROT_WRITE); struct db *db = restore(meta, sz); fileunmap(meta, sz); return db; } ////////////////////////////////////////////////////////////////////////////// static void restore_sindex(struct column *col) { char *tname = col->table->name; char buf[PATHLEN]; char *path = vbsnprintf(buf, sizeof buf, "%s/%s.%s.sorted.bin", DBPATH, tname, col->name); char *data; off_t sz = filemap(path, &data, PROT_READ); col->index->index = sindex_alloc(col->data.sz); memcpy(col->index->index, data, sz); assert(is_sorted(col->index->index, col->data.sz) == true); fileunmap(data, sz); }