X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Fstore.c;h=52cc6b356d5116f5d3d881b07ff36ddab5979c5d;hb=bc90f29d0c20f85e77761dbf2c43aec96848af36;hp=9b509e6b4327aaea115153f33ab41c10634f3cbf;hpb=70fdd2326239a9a5e02b3c3699d2588d5fee48fa;p=bluesky.git diff --git a/bluesky/store.c b/bluesky/store.c index 9b509e6..52cc6b3 100644 --- a/bluesky/store.c +++ b/bluesky/store.c @@ -10,63 +10,58 @@ #include #include -#include "bluesky.h" +#include "bluesky-private.h" /* Interaction with cloud storage. We expose very simple GET/PUT style * interface, which different backends can implement. Available backends * (will) include Amazon S3 and a simple local store for testing purposes. */ -/* Create and return a new reference-counted string. The reference count is - * initially one. The newly-returned string takes ownership of the memory - * pointed at by data, and will call g_free on it when the reference count - * drops to zero. */ -BlueSkyRCStr *bluesky_string_new(gpointer data, gsize len) +struct _BlueSkyStore { + const BlueSkyStoreImplementation *impl; + gpointer handle; +}; + +GHashTable *store_implementations; + +void bluesky_store_register(const BlueSkyStoreImplementation *impl, + const gchar *name) { - BlueSkyRCStr *string = g_new(BlueSkyRCStr, 1); - string->data = data; - string->len = len; - g_atomic_int_set(&string->refcount, 1); - return string; + g_hash_table_insert(store_implementations, g_strdup(name), (gpointer)impl); } -void bluesky_string_ref(BlueSkyRCStr *string) +BlueSkyStore *bluesky_store_new(const gchar *type) { - if (string == NULL) - return; + const BlueSkyStoreImplementation *impl; - g_atomic_int_inc(&string->refcount); + impl = g_hash_table_lookup(store_implementations, type); + if (impl == NULL) + return NULL; + + gpointer handle = impl->create(); + if (handle == NULL) + return NULL; + + BlueSkyStore *store = g_new(BlueSkyStore, 1); + store->impl = impl; + store->handle = handle; + return store; } -void bluesky_string_unref(BlueSkyRCStr *string) +void bluesky_store_free(BlueSkyStore *store) { - if (string == NULL) - return; - - if (g_atomic_int_dec_and_test(&string->refcount)) { - g_free(string->data); - g_free(string); - } + store->impl->destroy(store->handle); + g_free(store); } -/* Duplicate and return a new reference-counted string, containing a copy of - * the original data, with a reference count of 1. As an optimization, if the - * passed-in string already has a reference count of 1, the original is - * returned. Can be used to make a mutable copy of a shared string. For this - * to truly be safe, it is probably needed that there be some type of lock - * protecting access to the string. */ -BlueSkyRCStr *bluesky_string_dup(BlueSkyRCStr *string) +BlueSkyRCStr *bluesky_store_get(BlueSkyStore *store, const gchar *key) { - if (string == NULL) - return NULL; + return store->impl->get(store->handle, key); +} - if (g_atomic_int_dec_and_test(&string->refcount)) { - /* There are no other shared copies, so return this one. */ - g_atomic_int_inc(&string->refcount); - return string; - } else { - return bluesky_string_new(g_memdup(string->data, string->len), - string->len); - } +void bluesky_store_put(BlueSkyStore *store, + const gchar *key, BlueSkyRCStr *val) +{ + store->impl->put(store->handle, key, val); } /* Simple in-memory data store for test purposes. */ @@ -77,7 +72,7 @@ typedef struct { GHashTable *store; } MemStore; -MemStore *memstore_new() +static gpointer memstore_create() { MemStore *store = g_new(MemStore, 1); store->lock = g_mutex_new(); @@ -85,19 +80,75 @@ MemStore *memstore_new() g_free, (GDestroyNotify)bluesky_string_unref); - return store; + return (gpointer)store; } -BlueSkyRCStr *memstore_get(MemStore *store, const gchar *key) +static void memstore_destroy(gpointer store) { + /* TODO */ +} + +static BlueSkyRCStr *memstore_get(gpointer st, const gchar *key) +{ + MemStore *store = (MemStore *)st; BlueSkyRCStr *s = g_hash_table_lookup(store->store, key); if (s != NULL) bluesky_string_ref(s); return s; } -void memstore_put(MemStore *store, const gchar *key, BlueSkyRCStr *val) +static void memstore_put(gpointer s, const gchar *key, BlueSkyRCStr *val) { + MemStore *store = (MemStore *)s; bluesky_string_ref(val); g_hash_table_insert(store->store, g_strdup(key), val); } + +static BlueSkyStoreImplementation memstore_impl = { + .create = memstore_create, + .destroy = memstore_destroy, + .get = memstore_get, + .put = memstore_put, +}; + +/* Store implementation which writes data as files to disk. */ +static gpointer filestore_create() +{ + return GINT_TO_POINTER(1); +} + +static void filestore_destroy() +{ +} + +static BlueSkyRCStr *filestore_get(gpointer s, const gchar *key) +{ + gchar *contents = NULL; + gsize length; + GError *error = NULL; + + g_file_get_contents(key, &contents, &length, &error); + if (contents == NULL) + return NULL; + + return bluesky_string_new(contents, length); +} + +static void filestore_put(gpointer s, const gchar *key, BlueSkyRCStr *val) +{ + g_file_set_contents(key, val->data, val->len, NULL); +} + +static BlueSkyStoreImplementation filestore_impl = { + .create = filestore_create, + .destroy = filestore_destroy, + .get = filestore_get, + .put = filestore_put, +}; + +void bluesky_store_init() +{ + store_implementations = g_hash_table_new(g_str_hash, g_str_equal); + bluesky_store_register(&memstore_impl, "mem"); + bluesky_store_register(&filestore_impl, "file"); +}