Fix index creation and lookup logic
This commit is contained in:
parent
f121847e00
commit
389ed2a5e3
|
@ -64,6 +64,7 @@ struct libretrodb_index
|
||||||
char name[50];
|
char name[50];
|
||||||
uint64_t key_size;
|
uint64_t key_size;
|
||||||
uint64_t next;
|
uint64_t next;
|
||||||
|
uint64_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct libretrodb_metadata
|
typedef struct libretrodb_metadata
|
||||||
|
@ -184,7 +185,7 @@ int libretrodb_open(const char *path, libretrodb_t *db)
|
||||||
libretrodb_header_t header;
|
libretrodb_header_t header;
|
||||||
libretrodb_metadata_t md;
|
libretrodb_metadata_t md;
|
||||||
RFILE *fd = filestream_open(path,
|
RFILE *fd = filestream_open(path,
|
||||||
RETRO_VFS_FILE_ACCESS_READ,
|
RETRO_VFS_FILE_ACCESS_READ_WRITE | RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING,
|
||||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||||
|
|
||||||
if (!fd)
|
if (!fd)
|
||||||
|
@ -223,27 +224,29 @@ error:
|
||||||
static int libretrodb_find_index(libretrodb_t *db, const char *index_name,
|
static int libretrodb_find_index(libretrodb_t *db, const char *index_name,
|
||||||
libretrodb_index_t *idx)
|
libretrodb_index_t *idx)
|
||||||
{
|
{
|
||||||
ssize_t eof = filestream_get_size(db->fd);
|
filestream_seek(db->fd,
|
||||||
ssize_t offset = filestream_seek(db->fd,
|
(ssize_t)db->first_index_offset,
|
||||||
(ssize_t)db->first_index_offset,
|
RETRO_VFS_SEEK_POSITION_START);
|
||||||
RETRO_VFS_SEEK_POSITION_START);
|
|
||||||
|
|
||||||
/* TODO: this should use filestream_eof instead */
|
while (!filestream_eof(db->fd))
|
||||||
while (offset < eof)
|
|
||||||
{
|
{
|
||||||
uint64_t name_len = 50;
|
uint64_t name_len = 50;
|
||||||
/* Read index header */
|
/* Read index header */
|
||||||
rmsgpack_dom_read_into(db->fd,
|
if (rmsgpack_dom_read_into(db->fd,
|
||||||
"name", idx->name, &name_len,
|
"name", idx->name, &name_len,
|
||||||
"key_size", &idx->key_size,
|
"key_size", &idx->key_size,
|
||||||
"next", &idx->next, NULL);
|
"next", &idx->next,
|
||||||
|
"count", &idx->count,
|
||||||
|
NULL) < 0) {
|
||||||
|
printf("Invalid index header\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (strncmp(index_name, idx->name, strlen(idx->name)) == 0)
|
if (strncmp(index_name, idx->name, strlen(idx->name)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
filestream_seek(db->fd, (ssize_t)idx->next,
|
filestream_seek(db->fd, (ssize_t)idx->next,
|
||||||
RETRO_VFS_SEEK_POSITION_CURRENT);
|
RETRO_VFS_SEEK_POSITION_CURRENT);
|
||||||
offset = filestream_tell(db->fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -254,7 +257,7 @@ static int binsearch(const void *buff, const void *item,
|
||||||
{
|
{
|
||||||
int mid = (int)(count / 2);
|
int mid = (int)(count / 2);
|
||||||
int item_size = field_size + sizeof(uint64_t);
|
int item_size = field_size + sizeof(uint64_t);
|
||||||
uint64_t *current = (uint64_t *)buff + (mid * item_size);
|
uint8_t *current = (buff + (mid * item_size));
|
||||||
int rv = memcmp(current, item, field_size);
|
int rv = memcmp(current, item, field_size);
|
||||||
|
|
||||||
if (rv == 0)
|
if (rv == 0)
|
||||||
|
@ -278,7 +281,8 @@ int libretrodb_find_entry(libretrodb_t *db, const char *index_name,
|
||||||
{
|
{
|
||||||
libretrodb_index_t idx;
|
libretrodb_index_t idx;
|
||||||
int rv;
|
int rv;
|
||||||
void *buff;
|
uint8_t *buff;
|
||||||
|
int count;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
ssize_t bufflen, nread = 0;
|
ssize_t bufflen, nread = 0;
|
||||||
|
|
||||||
|
@ -286,13 +290,12 @@ int libretrodb_find_entry(libretrodb_t *db, const char *index_name,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
bufflen = idx.next;
|
bufflen = idx.next;
|
||||||
|
|
||||||
if (!(buff = malloc(bufflen)))
|
if (!(buff = malloc(bufflen)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (nread < bufflen)
|
while (nread < bufflen)
|
||||||
{
|
{
|
||||||
void *buff_ = (uint64_t *)buff + nread;
|
void *buff_ = (buff + nread);
|
||||||
rv = (int)filestream_read(db->fd, buff_, bufflen - nread);
|
rv = (int)filestream_read(db->fd, buff_, bufflen - nread);
|
||||||
|
|
||||||
if (rv <= 0)
|
if (rv <= 0)
|
||||||
|
@ -303,14 +306,16 @@ int libretrodb_find_entry(libretrodb_t *db, const char *index_name,
|
||||||
nread += rv;
|
nread += rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = binsearch(buff, key, db->count, (ssize_t)idx.key_size, &offset);
|
rv = binsearch(buff, key, idx.count, (ssize_t)idx.key_size, &offset);
|
||||||
free(buff);
|
free(buff);
|
||||||
|
|
||||||
if (rv == 0)
|
if (rv == 0) {
|
||||||
filestream_seek(db->fd, (ssize_t)offset,
|
filestream_seek(db->fd, (ssize_t)offset, RETRO_VFS_SEEK_POSITION_START);
|
||||||
RETRO_VFS_SEEK_POSITION_START);
|
rmsgpack_dom_read(db->fd, out);
|
||||||
|
return 0;
|
||||||
return rmsgpack_dom_read(db->fd, out);
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -447,7 +452,15 @@ int libretrodb_create_index(libretrodb_t *db,
|
||||||
uint64_t *buff_u64 = NULL;
|
uint64_t *buff_u64 = NULL;
|
||||||
uint8_t field_size = 0;
|
uint8_t field_size = 0;
|
||||||
uint64_t item_loc = filestream_tell(db->fd);
|
uint64_t item_loc = filestream_tell(db->fd);
|
||||||
bintree_t *tree = bintree_new(node_compare, &field_size);
|
bintree_t *tree;
|
||||||
|
uint64_t item_count = 0;
|
||||||
|
int rval = -1;
|
||||||
|
|
||||||
|
if (libretrodb_find_index(db, name, &idx) >= 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree = bintree_new(node_compare, &field_size);
|
||||||
|
|
||||||
item.type = RDT_NULL;
|
item.type = RDT_NULL;
|
||||||
|
|
||||||
|
@ -466,7 +479,8 @@ int libretrodb_create_index(libretrodb_t *db,
|
||||||
|
|
||||||
/* Field not found in item? */
|
/* Field not found in item? */
|
||||||
if (!(field = rmsgpack_dom_value_map_value(&item, &key)))
|
if (!(field = rmsgpack_dom_value_map_value(&item, &key)))
|
||||||
goto clean;
|
//goto clean;
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Field is not binary? */
|
/* Field is not binary? */
|
||||||
if (field->type != RDT_BINARY)
|
if (field->type != RDT_BINARY)
|
||||||
|
@ -487,7 +501,7 @@ int libretrodb_create_index(libretrodb_t *db,
|
||||||
|
|
||||||
memcpy(buff, field->val.binary.buff, field_size);
|
memcpy(buff, field->val.binary.buff, field_size);
|
||||||
|
|
||||||
buff_u64 = (uint64_t *)buff + field_size;
|
buff_u64 = (uint64_t *)(buff + field_size);
|
||||||
|
|
||||||
memcpy(buff_u64, &item_loc, sizeof(uint64_t));
|
memcpy(buff_u64, &item_loc, sizeof(uint64_t));
|
||||||
|
|
||||||
|
@ -497,31 +511,36 @@ int libretrodb_create_index(libretrodb_t *db,
|
||||||
rmsgpack_dom_value_print(field);
|
rmsgpack_dom_value_print(field);
|
||||||
goto clean;
|
goto clean;
|
||||||
}
|
}
|
||||||
|
item_count++;
|
||||||
buff = NULL;
|
buff = NULL;
|
||||||
rmsgpack_dom_value_free(&item);
|
rmsgpack_dom_value_free(&item);
|
||||||
item_loc = filestream_tell(db->fd);
|
item_loc = filestream_tell(cur.fd);
|
||||||
}
|
}
|
||||||
|
rval = 0;
|
||||||
|
|
||||||
filestream_seek(db->fd, 0, RETRO_VFS_SEEK_POSITION_END);
|
filestream_seek(db->fd, 0, RETRO_VFS_SEEK_POSITION_END);
|
||||||
|
|
||||||
strlcpy(idx.name, name, sizeof(idx.name));
|
strlcpy(idx.name, name, sizeof(idx.name));
|
||||||
|
|
||||||
idx.key_size = field_size;
|
idx.key_size = field_size;
|
||||||
idx.next = db->count * (field_size + sizeof(uint64_t));
|
idx.next = item_count * (field_size + sizeof(uint64_t));
|
||||||
|
idx.count = item_count;
|
||||||
/* Write index header */
|
/* Write index header */
|
||||||
rmsgpack_write_map_header(db->fd, 3);
|
rmsgpack_write_map_header(db->fd, 4);
|
||||||
rmsgpack_write_string(db->fd, "name", STRLEN_CONST("name"));
|
rmsgpack_write_string(db->fd, "name", STRLEN_CONST("name"));
|
||||||
rmsgpack_write_string(db->fd, idx.name, (uint32_t)strlen(idx.name));
|
rmsgpack_write_string(db->fd, idx.name, (uint32_t)strlen(idx.name));
|
||||||
rmsgpack_write_string(db->fd, "key_size", (uint32_t)STRLEN_CONST("key_size"));
|
rmsgpack_write_string(db->fd, "key_size", (uint32_t)STRLEN_CONST("key_size"));
|
||||||
rmsgpack_write_uint (db->fd, idx.key_size);
|
rmsgpack_write_uint (db->fd, idx.key_size);
|
||||||
rmsgpack_write_string(db->fd, "next", STRLEN_CONST("next"));
|
rmsgpack_write_string(db->fd, "next", STRLEN_CONST("next"));
|
||||||
rmsgpack_write_uint (db->fd, idx.next);
|
rmsgpack_write_uint (db->fd, idx.next);
|
||||||
|
rmsgpack_write_string(db->fd, "count", STRLEN_CONST("count"));
|
||||||
|
rmsgpack_write_uint (db->fd, idx.count);
|
||||||
|
|
||||||
nictx.db = db;
|
nictx.db = db;
|
||||||
nictx.idx = &idx;
|
nictx.idx = &idx;
|
||||||
bintree_iterate(tree->root, node_iter, &nictx);
|
bintree_iterate(tree->root, node_iter, &nictx);
|
||||||
|
|
||||||
|
filestream_flush(db->fd);
|
||||||
clean:
|
clean:
|
||||||
rmsgpack_dom_value_free(&item);
|
rmsgpack_dom_value_free(&item);
|
||||||
if (buff)
|
if (buff)
|
||||||
|
@ -531,7 +550,7 @@ clean:
|
||||||
if (tree && tree->root)
|
if (tree && tree->root)
|
||||||
bintree_free(tree->root);
|
bintree_free(tree->root);
|
||||||
free(tree);
|
free(tree);
|
||||||
return 0;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
libretrodb_cursor_t *libretrodb_cursor_new(void)
|
libretrodb_cursor_t *libretrodb_cursor_new(void)
|
||||||
|
|
Loading…
Reference in New Issue