better verbose messages
This commit is contained in:
parent
bafb629b6a
commit
66d4591ebb
5
common.h
5
common.h
@ -3,8 +3,9 @@
|
||||
|
||||
#define VERBOSITY_QUIET -1
|
||||
#define VERBOSITY_NORMAL 0
|
||||
#define VERBOSITY_VERBOSE 1
|
||||
#define VERBOSITY_DEBUG 2
|
||||
#define VERBOSITY_DEBUG 1
|
||||
#define VERBOSITY_VERBOSE 2
|
||||
#define VERBOSITY_VERY_VERBOSE 3
|
||||
|
||||
#include <stdio.h>
|
||||
#include "optparse.h"
|
||||
|
65
index.c
65
index.c
@ -10,11 +10,15 @@
|
||||
#define BTREE_ERR_CANNOT_OPEN_FILE -1
|
||||
#define BTREE_ERR_PAGE_SIZE_DIFFERENT -2
|
||||
|
||||
#define BTREE_OPTIMIZE_RECORDS_MIN 10
|
||||
#define BTREE_OPTIMIZE_THRESHOLD 0.1
|
||||
|
||||
#define SWAP(type, x, y) do { type __tmp__; __tmp__ = y; y = x; x = __tmp__; } while (0)
|
||||
|
||||
/* private functions */
|
||||
void _btree_insert_into_node(btree_t *tree, btree_node_t *node, btree_entry_t *entry);
|
||||
void _btree_remove_from_node(btree_t *tree, btree_node_t *node, unsigned index);
|
||||
void _btree_optimize_if_needed(btree_t *tree) ;
|
||||
|
||||
int _btree_save_header(btree_t *tree)
|
||||
{
|
||||
@ -42,14 +46,14 @@ page_t _btree_alloc(btree_t *tree)
|
||||
|
||||
page += bit + 1;
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[alloc] allocated page %zu.\n", page);
|
||||
printfv(VERBOSITY_VERBOSE, "[alloc] allocated page %zu.\n", page);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
void _btree_page_free(btree_t *tree, page_t page)
|
||||
{
|
||||
printfv(VERBOSITY_DEBUG, "[alloc] freeing page %zu.\n", page);
|
||||
printfv(VERBOSITY_VERBOSE, "[alloc] freeing page %zu.\n", page);
|
||||
|
||||
uint8_t bitmap[PAGE_SIZE];
|
||||
file_read(tree->file, 1 + (page / (PAGE_SIZE * 8)) * PAGE_SIZE, bitmap, PAGE_SIZE);
|
||||
@ -88,7 +92,7 @@ bool _btree_stack_empty(btree_t *tree)
|
||||
|
||||
void _btree_stack_push(btree_t *tree, btree_node_t *node, unsigned n)
|
||||
{
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Pushing %zu page on parent stack, entry index %u\n", node->page, n);
|
||||
printfv(VERBOSITY_VERBOSE, "[btree] Pushing %zu page on parent stack, entry index %u\n", node->page, n);
|
||||
tree->trace.current++;
|
||||
tree->trace.current->node = *node;
|
||||
tree->trace.current->entry = btree_get_entry(&tree->trace.current->node, n);
|
||||
@ -149,7 +153,7 @@ unsigned _btree_concat_entries(void* current, size_t na, void* added, size_t nb)
|
||||
|
||||
void _btree_node_insert_entry(btree_node_t* node, btree_entry_t entry)
|
||||
{
|
||||
printfv(VERBOSITY_DEBUG, "[btree] inserting { %zu < %zu > %zu } on %zu\n", entry.left, entry.key, entry.right, node->page);
|
||||
printfv(VERBOSITY_VERBOSE, "[btree] inserting { %zu < %zu > %zu } on %zu\n", entry.left, entry.key, entry.right, node->page);
|
||||
|
||||
_btree_concat_entries(node->entries, node->header.entries, &entry, 1);
|
||||
node->header.entries++;
|
||||
@ -371,10 +375,10 @@ void _btree_split_node(btree_t *tree, btree_node_t *old, btree_entry_t *entry)
|
||||
tree->header.root = parent->page;
|
||||
_btree_save_header(tree);
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[btree] designated new root %zu.\n", parent->page);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Designated new root %zu.\n", parent->page);
|
||||
};
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[btree] spliting node %zu.\n", old->page);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Spliting node %zu.\n", old->page);
|
||||
|
||||
btree_entry_t parent_entry = *NODE_ENTRY(buffer, half);
|
||||
|
||||
@ -457,7 +461,7 @@ page_t btree_insert(btree_t *tree, record_t record)
|
||||
btree_node_t node;
|
||||
|
||||
if (btree_find(tree, key, NULL, &node, NULL) != PAGE_NONE) {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] record with key %zu already exists.\n", key);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Record with key %zu already exists.\n", key);
|
||||
return PAGE_NONE;
|
||||
}
|
||||
|
||||
@ -465,12 +469,18 @@ page_t btree_insert(btree_t *tree, record_t record)
|
||||
btree_entry_t entry = { PAGE_NONE, key, offset, PAGE_NONE };
|
||||
|
||||
_btree_insert_into_node(tree, &node, &entry);
|
||||
|
||||
tree->header.changes++;
|
||||
tree->header.records++;
|
||||
|
||||
_btree_optimize_if_needed(tree);
|
||||
|
||||
return node.page;
|
||||
}
|
||||
|
||||
void _btree_merge(btree_t *tree, btree_node_t* left, btree_node_t* right)
|
||||
{
|
||||
printfv(VERBOSITY_DEBUG, "[btree] merging %zu with %zu.\n", left->page, right->page);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Merging %zu with %zu.\n", left->page, right->page);
|
||||
|
||||
size_t nl = left->header.entries,
|
||||
nr = right->header.entries,
|
||||
@ -501,7 +511,7 @@ void _btree_merge(btree_t *tree, btree_node_t* left, btree_node_t* right)
|
||||
left->header.flags |= NODE_IS_ROOT;
|
||||
tree->header.root = left->page;
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[btree] designated new root %zu.\n", left->page);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Designated new root %zu.\n", left->page);
|
||||
} else {
|
||||
_btree_write_node(&parent->node, tree, parent->node.page);
|
||||
}
|
||||
@ -518,7 +528,7 @@ void _btree_fix_underflow(btree_t *tree, btree_node_t *node) {
|
||||
_btree_load_node(&sibling, tree, siblings.left);
|
||||
entry = siblings.left_entry;
|
||||
if (sibling.header.entries + node->header.entries >= 2*tree->header.d) {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] rebalancing with left sibling %zu.\n", siblings.left);
|
||||
printfv(VERBOSITY_VERBOSE, "[btree] rebalancing with left sibling %zu.\n", siblings.left);
|
||||
_btree_rebalance(tree, &sibling, node, siblings.left_entry);
|
||||
return;
|
||||
}
|
||||
@ -528,13 +538,13 @@ void _btree_fix_underflow(btree_t *tree, btree_node_t *node) {
|
||||
_btree_load_node(&sibling, tree, siblings.right);
|
||||
entry = siblings.right_entry;
|
||||
if (sibling.header.entries + node->header.entries >= 2*tree->header.d) {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] rebalancing with right sibling %zu.\n", siblings.right);
|
||||
printfv(VERBOSITY_VERBOSE, "[btree] rebalancing with right sibling %zu.\n", siblings.right);
|
||||
_btree_rebalance(tree, node, &sibling, siblings.right_entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[btree] unable to rebalance.\n");
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Enable to rebalance.\n");
|
||||
|
||||
if (siblings.right != PAGE_NONE) {
|
||||
_btree_merge(tree, node, &sibling);
|
||||
@ -563,7 +573,7 @@ void _btree_remove_from_node(btree_t *tree, btree_node_t *node, unsigned index)
|
||||
node->header.entries = m;
|
||||
|
||||
if ((~node->header.flags & NODE_IS_ROOT) && node->header.entries < tree->header.d) {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] underflow in %zu.\n", node->page);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Underflow in %zu.\n", node->page);
|
||||
_btree_fix_underflow(tree, node);
|
||||
} else {
|
||||
_btree_write_node(node, tree, node->page);
|
||||
@ -578,7 +588,7 @@ page_t btree_remove(btree_t *tree, record_key_t key)
|
||||
unsigned index;
|
||||
|
||||
if (btree_find(tree, key, NULL, &node, &index) == PAGE_NONE) {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] record with key %zu does not exist.\n", key);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Record with key %zu does not exist.\n", key);
|
||||
// 404
|
||||
return PAGE_NONE;
|
||||
}
|
||||
@ -586,11 +596,11 @@ page_t btree_remove(btree_t *tree, record_key_t key)
|
||||
entry = btree_get_entry(&node, index);
|
||||
|
||||
if (node.header.flags & NODE_IS_LEAF) {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] removing record with key %zu from leaf %zu.\n", entry->key, node.page);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Removing record with key %zu from leaf %zu.\n", entry->key, node.page);
|
||||
_btree_remove_from_node(tree, &node, index);
|
||||
_btree_write_node(&node, tree, node.page);
|
||||
} else {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] removing record with key %zu from node %zu.\n", entry->key, node.page);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Removing record with key %zu from node %zu.\n", entry->key, node.page);
|
||||
|
||||
btree_node_t *replacement;
|
||||
btree_entry_t *replaced;
|
||||
@ -608,7 +618,7 @@ page_t btree_remove(btree_t *tree, record_key_t key)
|
||||
replaced = NODE_ENTRY(node.entries, 0);
|
||||
entry = btree_get_entry(replacement, index);
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[btree] exchanging %zu with %zu.\n", entry->key, replaced->key);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Exchanging %zu with %zu.\n", entry->key, replaced->key);
|
||||
SWAP(record_key_t, replaced->key, entry->key);
|
||||
SWAP(offset_t, replaced->location, entry->location);
|
||||
_btree_write_node(replacement, tree, replacement->page);
|
||||
@ -616,13 +626,18 @@ page_t btree_remove(btree_t *tree, record_key_t key)
|
||||
_btree_remove_from_node(tree, &node, 0);
|
||||
}
|
||||
|
||||
tree->header.changes++;
|
||||
tree->header.records--;
|
||||
|
||||
_btree_optimize_if_needed(tree);
|
||||
|
||||
return node.page;
|
||||
}
|
||||
|
||||
bool btree_update(btree_t *tree, record_key_t key, record_t record)
|
||||
{
|
||||
if (record.key != key) {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] update key mismatch, removing %zu and adding %zu.\n", key, record.key);
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Update key mismatch, removing %zu and adding %zu.\n", key, record.key);
|
||||
btree_remove(tree, key);
|
||||
return btree_insert(tree, record) != PAGE_NONE;
|
||||
}
|
||||
@ -663,6 +678,8 @@ page_t btree_read_record(btree_t *tree, record_key_t key, record_t *record)
|
||||
void btree_close(btree_t* tree)
|
||||
{
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Closing index %s.\n", tree->file->filename);
|
||||
_btree_save_header(tree);
|
||||
|
||||
file_close(tree->file);
|
||||
tape_close(tree->main);
|
||||
}
|
||||
@ -673,6 +690,15 @@ void btree_flush(btree_t* tree)
|
||||
file_flush(tree->main->file);
|
||||
}
|
||||
|
||||
void _btree_optimize_if_needed(btree_t *tree)
|
||||
{
|
||||
double ratio = (double)tree->header.changes / (double)tree->header.records;
|
||||
if (tree->header.records > BTREE_OPTIMIZE_RECORDS_MIN && ratio > BTREE_OPTIMIZE_THRESHOLD) {
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Auto optimization triggered.\n");
|
||||
btree_optimize(tree);
|
||||
}
|
||||
}
|
||||
|
||||
void _btree_optimize_page(btree_t* tree, tape_t* tmp, page_t page)
|
||||
{
|
||||
if (!page) return;
|
||||
@ -696,10 +722,13 @@ void _btree_optimize_page(btree_t* tree, tape_t* tmp, page_t page)
|
||||
|
||||
void btree_optimize(btree_t *tree)
|
||||
{
|
||||
|
||||
char tmp[PATH_MAX + 4], old[PATH_MAX];
|
||||
strcpy(old, tree->main->file->filename);
|
||||
sprintf(tmp, "%s.tmp", old);
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[btree] Optimizing btree using temp file %s.\n", tmp);
|
||||
|
||||
tape_t *temp = tape_open(tmp, "wb+");
|
||||
_btree_optimize_page(tree, temp, tree->header.root);
|
||||
tape_close(temp);
|
||||
|
4
index.h
4
index.h
@ -23,7 +23,9 @@ typedef struct {
|
||||
size_t page_size; /* 8 bytes long */
|
||||
page_t root; /* 8 bytes long */
|
||||
char main[256]; /* 256 bytes long */
|
||||
} btree_header_t; /* 280 bytes long */
|
||||
size_t records; /* 8 bytes long */
|
||||
size_t changes; /* 8 bytes long */
|
||||
} btree_header_t; /* 296 bytes long */
|
||||
|
||||
typedef struct {
|
||||
uint16_t flags;
|
||||
|
12
io.c
12
io.c
@ -19,7 +19,7 @@ file_t* file_open(const char* filename, const char* mode)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[io] File %s opened in %s with page size %zu.\n", filename, mode, PAGE_SIZE);
|
||||
printfv(VERBOSITY_VERY_VERBOSE, "[io] File %s opened in %s with page size %zu.\n", filename, mode, PAGE_SIZE);
|
||||
file_t* result = malloc(sizeof(file_t));
|
||||
|
||||
result->file = handle;
|
||||
@ -34,7 +34,7 @@ void file_close(file_t* file)
|
||||
{
|
||||
file_flush(file);
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[io] Closing file %s.\n", file->filename);
|
||||
printfv(VERBOSITY_VERY_VERBOSE, "[io] Closing file %s.\n", file->filename);
|
||||
fclose(file->file);
|
||||
|
||||
free(file->filename);
|
||||
@ -48,14 +48,14 @@ size_t file_read(file_t* file, page_t page, void* buffer, size_t length)
|
||||
page_cache_entry_t *entry = _file_load_page(file, page);
|
||||
memcpy(buffer, entry->data, length);
|
||||
|
||||
printfv(VERBOSITY_DEBUG, "[io] Reading page %zu in %s (%zu bytes).\n", page, file->filename, entry->size);
|
||||
printfv(VERBOSITY_VERY_VERBOSE, "[io] Reading page %zu in %s (%zu bytes).\n", page, file->filename, entry->size);
|
||||
|
||||
return entry->size;
|
||||
}
|
||||
|
||||
size_t file_write(file_t* file, page_t page, const void* buffer, size_t length)
|
||||
{
|
||||
printfv(VERBOSITY_DEBUG, "[io] Writing page %zu in %s (%zu bytes).\n", page, file->filename, length);
|
||||
printfv(VERBOSITY_VERY_VERBOSE, "[io] Writing page %zu in %s (%zu bytes).\n", page, file->filename, length);
|
||||
writes_all++;
|
||||
|
||||
page_cache_entry_t *entry = _file_load_page(file, page);
|
||||
@ -92,7 +92,7 @@ page_cache_entry_t *_file_load_page(file_t* file, page_t page)
|
||||
memset(entry->data, 0, PAGE_SIZE);
|
||||
entry->size = fread(entry->data, 1, PAGE_SIZE, file->file);
|
||||
if (entry->size) {
|
||||
printfv(VERBOSITY_DEBUG, "[io] Loading page %u of %s (%zu bytes).\n", page, file->filename, entry->size);
|
||||
printfv(VERBOSITY_VERY_VERBOSE, "[io] Loading page %u of %s (%zu bytes).\n", page, file->filename, entry->size);
|
||||
reads++;
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ page_cache_entry_t *_file_load_page(file_t* file, page_t page)
|
||||
void _file_flush_page(file_t *file, page_cache_entry_t *entry)
|
||||
{
|
||||
if (entry->flags & PAGE_PRESENT && entry->flags & PAGE_DIRTY) {
|
||||
printfv(VERBOSITY_DEBUG, "[io] Flushing page %u to %s (%zu bytes).\n", entry->page, file->filename, entry->size);
|
||||
printfv(VERBOSITY_VERY_VERBOSE, "[io] Flushing page %u to %s (%zu bytes).\n", entry->page, file->filename, entry->size);
|
||||
|
||||
fseek(file->file, entry->page * PAGE_SIZE, SEEK_SET);
|
||||
fwrite(entry->data, 1, entry->size, file->file);
|
||||
|
Loading…
Reference in New Issue
Block a user