link_directories(/home/mvrable/scratch/libs3-1.4/build/lib)
-add_library(bluesky SHARED crypto.c dir.c file.c inode.c serialize.c store.c s3store.c)
+add_library(bluesky SHARED
+ crypto.c dir.c file.c init.c inode.c serialize.c store.c s3store.c)
add_executable(bluesky-test main.c)
set(CMAKE_C_FLAGS "-std=gnu99 ${CMAKE_C_FLAGS}")
extern "C" {
#endif
-struct S3Store;
+void bluesky_init(void);
/* Reference-counted blocks of memory, used for passing data in and out of
* storage backends and in other places. */
BlueSkyRCStr *bluesky_crypt_encrypt(BlueSkyRCStr *in, const uint8_t *key);
BlueSkyRCStr *bluesky_crypt_decrypt(BlueSkyRCStr *in, const uint8_t *key);
+/* Storage interface. This presents a key-value store abstraction, and can
+ * have multiple implementations: in-memory, on-disk, in-cloud. */
+typedef struct {
+ /* Create a new store instance and return a handle to it. */
+ gpointer (*create)();
+
+ /* Clean up any resources used by this store. */
+ void (*destroy)(gpointer store);
+
+ /* Fetch an item with the given name, or return NULL if not found. */
+ BlueSkyRCStr * (*get)(gpointer store, const gchar *key);
+
+ /* Store an item to the given key name. */
+ void (*put)(gpointer store, const gchar *key, BlueSkyRCStr *val);
+} BlueSkyStoreImplementation;
+
+void bluesky_store_register(const BlueSkyStoreImplementation *impl,
+ const gchar *name);
+
+struct _BlueSkyStore;
+typedef struct _BlueSkyStore BlueSkyStore;
+
+void bluesky_store_init();
+BlueSkyStore *bluesky_store_new(const gchar *type);
+void bluesky_store_free(BlueSkyStore *store);
+BlueSkyRCStr *bluesky_store_get(BlueSkyStore *store, const gchar *key);
+void bluesky_store_put(BlueSkyStore *store,
+ const gchar *key, BlueSkyRCStr *val);
+
/* File types. The numeric values are chosen to match with those used in
* NFSv3. */
typedef enum {
GHashTable *inodes; /* Cached inodes */
uint64_t next_inum; /* Next available inode for allocation */
- struct S3Store *store;
+ BlueSkyStore *store;
uint8_t *encryption_key;
} BlueSkyFS;
void bluesky_file_read(BlueSkyInode *inode, uint64_t offset,
char *buf, gint len);
-struct S3Store *s3store_new();
-BlueSkyRCStr *s3store_get(struct S3Store *store, const gchar *key);
-void s3store_put(struct S3Store *store, const gchar *key, BlueSkyRCStr *val);
-
#ifdef __cplusplus
}
#endif
return;
g_print("Fetching block from %s\n", block->ref);
- BlueSkyRCStr *string = s3store_get(fs->store, block->ref);
+ BlueSkyRCStr *string = bluesky_store_get(fs->store, block->ref);
bluesky_string_unref(block->data);
block->data = bluesky_crypt_decrypt(string, fs->encryption_key);
gchar *name = g_strdup(g_checksum_get_string(csum));
g_print("Flushing block as %s\n", name);
- s3store_put(fs->store, name, data);
+ bluesky_store_put(fs->store, name, data);
g_free(block->ref);
block->ref = name;
--- /dev/null
+/* Blue Sky: File Systems in the Cloud
+ *
+ * Copyright (C) 2009 The Regents of the University of California
+ * Written by Michael Vrable <mvrable@cs.ucsd.edu>
+ *
+ * TODO: Licensing
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <string.h>
+
+#include "bluesky.h"
+
+/* BlueSky library initialization. */
+
+void bluesky_store_init_s3(void);
+
+/* Initialize the BlueSky library and dependent libraries. */
+void bluesky_init(void)
+{
+ g_thread_init(NULL);
+ bluesky_crypt_init();
+
+ bluesky_store_init();
+ bluesky_store_init_s3();
+}
fs->inodes = g_hash_table_new(bluesky_fs_key_hash_func,
bluesky_fs_key_equal_func);
fs->next_inum = BLUESKY_ROOT_INUM + 1;
- fs->store = s3store_new();
+ fs->store = bluesky_store_new("file");
return fs;
}
/* Interface to Amazon S3 storage. */
/* Simple in-memory data store for test purposes. */
-struct S3Store {
+typedef struct {
S3BucketContext bucket;
-};
+} S3Store;
-struct S3Store *s3store_new()
+static gpointer s3store_new()
{
- struct S3Store *store = g_new(struct S3Store, 1);
+ S3Store *store = g_new(S3Store, 1);
store->bucket.bucketName = "mvrable-bluesky";
store->bucket.protocol = S3ProtocolHTTP;
store->bucket.uriStyle = S3UriStylePath;
return store;
}
+static void s3store_destroy(gpointer store)
+{
+ g_free(store);
+}
+
struct get_info {
gchar *buf;
gint offset;
return S3StatusOK;
}
-void s3store_response_callback(S3Status status,
+static void s3store_response_callback(S3Status status,
const S3ErrorDetails *errorDetails,
void *callbackData)
{
}
}
-BlueSkyRCStr *s3store_get(struct S3Store *store, const gchar *key)
+static BlueSkyRCStr *s3store_get(gpointer s, const gchar *key)
{
+ S3Store *store = (S3Store *)s;
+
struct get_info info;
info.buf = (char *)g_malloc0(BLUESKY_BLOCK_SIZE);
info.offset = 0;
return bluesky_string_new(info.buf, BLUESKY_BLOCK_SIZE);
}
-void s3store_put(struct S3Store *store, const gchar *key, BlueSkyRCStr *val)
+static void s3store_put(gpointer s, const gchar *key, BlueSkyRCStr *val)
{
+ S3Store *store = (S3Store *)s;
+
struct put_info info;
info.val = val;
info.offset = 0;
S3_put_object(&store->bucket, key, val->len, NULL, NULL,
&handler, &info);
}
+
+static BlueSkyStoreImplementation store_impl = {
+ .create = s3store_new,
+ .destroy = s3store_destroy,
+ .get = s3store_get,
+ .put = s3store_put,
+};
+
+void bluesky_store_init_s3(void)
+{
+ S3_initialize(NULL, S3_INIT_ALL);
+ bluesky_store_register(&store_impl, "s3");
+}
* interface, which different backends can implement. Available backends
* (will) include Amazon S3 and a simple local store for testing purposes. */
+struct _BlueSkyStore {
+ const BlueSkyStoreImplementation *impl;
+ gpointer handle;
+};
+
+GHashTable *store_implementations;
+
+void bluesky_store_register(const BlueSkyStoreImplementation *impl,
+ const gchar *name)
+{
+ g_hash_table_insert(store_implementations, g_strdup(name), (gpointer)impl);
+}
+
+BlueSkyStore *bluesky_store_new(const gchar *type)
+{
+ const BlueSkyStoreImplementation *impl;
+
+ 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_store_free(BlueSkyStore *store)
+{
+ store->impl->destroy(store->handle);
+ g_free(store);
+}
+
+BlueSkyRCStr *bluesky_store_get(BlueSkyStore *store, const gchar *key)
+{
+ return store->impl->get(store->handle, key);
+}
+
+void bluesky_store_put(BlueSkyStore *store,
+ const gchar *key, BlueSkyRCStr *val)
+{
+ store->impl->put(store->handle, key, val);
+}
+
/* 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
GHashTable *store;
} MemStore;
-MemStore *memstore_new()
+static gpointer memstore_create()
{
MemStore *store = g_new(MemStore, 1);
store->lock = g_mutex_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;
+
+ 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");
+}
int main(int argc, char *argv[])
{
int i;
- g_thread_init(NULL);
- bluesky_crypt_init();
+ bluesky_init();
register_rpc();
bluesky_crypt_random_bytes(filesystem_key, sizeof(filesystem_key));
}
printf("\n");
- S3_initialize(NULL, S3_INIT_ALL);
-
fs = bluesky_new_fs("export");
fs->encryption_key = filesystem_key;