You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
4.8 KiB
C
211 lines
4.8 KiB
C
#include "hash_index.h"
|
|
|
|
// Submodules
|
|
#include "collections/array.h"
|
|
#include "json/json.h"
|
|
#include "json/layout.h"
|
|
#include "sha256/sha256.h"
|
|
|
|
// Stdlib
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <unistd.h>
|
|
|
|
//#define DEBUG
|
|
|
|
#ifdef DEBUG
|
|
#define DEBUG_printf printf
|
|
#define DEBUG_fflush fflush
|
|
#else
|
|
#define DEBUG_printf(...)
|
|
#define DEBUG_fflush(...)
|
|
#endif
|
|
|
|
struct hash_index_entry
|
|
{
|
|
char* key;
|
|
int val;
|
|
};
|
|
|
|
extern struct json_field_type hash_index_entry_type;
|
|
#define OBJ_TYPE struct hash_index_entry
|
|
static struct json_object_field hash_index_entry_layout[] = {
|
|
JSON_FIELD_STRING( key, true ),
|
|
JSON_FIELD_INTEGER( val, true ),
|
|
JSON_FIELD_END
|
|
};
|
|
#undef OBJ_TYPE
|
|
|
|
static void hash_index_entry_free( struct hash_index_entry* e )
|
|
{
|
|
if( !e ) { return; }
|
|
|
|
free(e->key);
|
|
free(e);
|
|
}
|
|
|
|
JSON_FIELD_TYPE_OBJECT_LAYOUT_WITH_DEFAULTS( hash_index_entry );
|
|
|
|
struct hash_index
|
|
{
|
|
struct {
|
|
struct hash_index_entry** items;
|
|
int count;
|
|
} entries;
|
|
};
|
|
|
|
static void hash_index_free_composite( struct hash_index* hi )
|
|
{
|
|
for( int i = 0; i < hi->entries.count; ++i ) {
|
|
struct hash_index_entry* entry = hi->entries.items[i];
|
|
hash_index_entry_free(entry);
|
|
}
|
|
free(hi->entries.items);
|
|
}
|
|
|
|
#define OBJ_TYPE struct hash_index
|
|
static struct json_object_field hash_index_layout[] = {
|
|
JSON_FIELD_ARRAY_OF_TYPE( entries, true, hash_index_entry_type ),
|
|
JSON_FIELD_END,
|
|
};
|
|
#undef OBJ_TYPE
|
|
|
|
bool hash_index_set( const char* index, const char* key, int value )
|
|
{
|
|
char hash[65] = "";
|
|
sha256_easy_hash_hex( key, strlen(key), hash );
|
|
hash[5] = '\0';
|
|
|
|
char filename[512];
|
|
snprintf( filename, 512, "%s/%s.json", index, hash );
|
|
|
|
struct hash_index hi;
|
|
memset( &hi, 0, sizeof(hi) );
|
|
json_read_object_layout_from_file( filename, hash_index_layout, &hi );
|
|
|
|
// Overwrite existing entries
|
|
for( int i = 0; i < hi.entries.count; ++i ) {
|
|
struct hash_index_entry* entry = hi.entries.items[i];
|
|
DEBUG_printf( "\tentry[%d] = { .key = %s, .val = %d }\n", i, entry->key, entry->val );
|
|
|
|
if( 0 == strcmp( entry->key, key ) ) {
|
|
entry->val = value;
|
|
goto exists;
|
|
}
|
|
}
|
|
|
|
DEBUG_printf( "appending\n" );
|
|
struct hash_index_entry* new_entry = NULL;
|
|
new_entry = malloc(sizeof(*new_entry));
|
|
memset(new_entry,0,sizeof(*new_entry));
|
|
new_entry->key = strdup(key);
|
|
new_entry->val = value;
|
|
array_append( &hi.entries, sizeof(new_entry), &new_entry );
|
|
exists:
|
|
json_write_object_layout_to_file( filename, "\t", hash_index_layout, &hi );
|
|
|
|
hash_index_free_composite( &hi );
|
|
return true;
|
|
}
|
|
bool hash_index_remove( const char* index, const char* key )
|
|
{
|
|
char hash[65] = "";
|
|
sha256_easy_hash_hex( key, strlen(key), hash );
|
|
hash[5] = '\0';
|
|
|
|
char filename[512];
|
|
snprintf( filename, 512, "%s/%s.json", index, hash );
|
|
|
|
struct hash_index hi;
|
|
memset( &hi, 0, sizeof(hi) );
|
|
json_read_object_layout_from_file( filename, hash_index_layout, &hi );
|
|
|
|
// Remove entry if it already exists
|
|
for( int i = 0; i < hi.entries.count; ++i ) {
|
|
struct hash_index_entry* entry = hi.entries.items[i];
|
|
DEBUG_printf( "\tentry[%d] = { .key = %s, .val = %d }\n", i, entry->key, entry->val );
|
|
|
|
if( 0 == strcmp( entry->key, key ) ) {
|
|
hash_index_entry_free( hi.entries.items[i] );
|
|
hi.entries.items[i] = hi.entries.items[ hi.entries.count - 1 ];
|
|
hi.entries.count -= 1;
|
|
goto exists;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
exists:
|
|
if( hi.entries.count == 0 ) {
|
|
unlink(filename);
|
|
return true;
|
|
}
|
|
|
|
json_write_object_layout_to_file( filename, "\t", hash_index_layout, &hi );
|
|
|
|
hash_index_free_composite( &hi );
|
|
return true;
|
|
}
|
|
|
|
|
|
bool hash_index_get( const char* index, const char* key, int* value )
|
|
{
|
|
char hash[65] = "";
|
|
sha256_easy_hash_hex( key, strlen(key), hash );
|
|
hash[5] = '\0';
|
|
|
|
char filename[512];
|
|
snprintf( filename, 512, "%s/%s.json", index, hash );
|
|
|
|
struct hash_index hi;
|
|
memset( &hi, 0, sizeof(hi) );
|
|
if( !json_read_object_layout_from_file( filename, hash_index_layout, &hi ) ) {
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
for( int i = 0; i < hi.entries.count; ++i ) {
|
|
struct hash_index_entry* entry = hi.entries.items[i];
|
|
printf( "\tentry[%d] = %p{ .uri = %s, .account_id = %d }\n", i, entry, entry->key, entry->val );
|
|
}
|
|
//*/
|
|
|
|
bool found = false;
|
|
*value = -1;
|
|
for( int i = 0; i < hi.entries.count; ++i ) {
|
|
struct hash_index_entry* entry = hi.entries.items[i];
|
|
if( 0 == strcmp(entry->key,key) ) {
|
|
*value = entry->val;
|
|
found = true;
|
|
}
|
|
}
|
|
|
|
hash_index_free_composite(&hi);
|
|
|
|
return found;
|
|
}
|
|
|
|
char* ffdb_hash_get_key( const char* index, int slot, int offset )
|
|
{
|
|
char* result = NULL;
|
|
char filename[512];
|
|
snprintf( filename,512, "%s/%05x.json", index, slot );
|
|
|
|
struct hash_index hi;
|
|
memset( &hi, 0, sizeof(hi) );
|
|
if( !json_read_object_layout_from_file( filename, hash_index_layout, &hi ) ) {
|
|
goto failed;
|
|
}
|
|
|
|
if( offset >= hi.entries.count ) { goto failed; }
|
|
|
|
result = strdup( hi.entries.items[offset]->key );
|
|
cleanup:
|
|
hash_index_free_composite( &hi );
|
|
return result;
|
|
failed:
|
|
free(result);
|
|
result = NULL;
|
|
goto cleanup;
|
|
}
|
|
|