Fix index creation and lookup logic

This commit is contained in:
Joseph C. Osborn 2023-07-27 12:17:29 -07:00 committed by LibretroAdmin
parent f121847e00
commit 389ed2a5e3
1 changed files with 48 additions and 29 deletions

View File

@ -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)