1 /* Blue Sky: File Systems in the Cloud
3 * Copyright (C) 2009 The Regents of the University of California
4 * Written by Michael Vrable <mvrable@cs.ucsd.edu>
15 /* Interaction with cloud storage. We expose very simple GET/PUT style
16 * interface, which different backends can implement. Available backends
17 * (will) include Amazon S3 and a simple local store for testing purposes. */
19 struct _BlueSkyStore {
20 const BlueSkyStoreImplementation *impl;
24 GHashTable *store_implementations;
26 void bluesky_store_register(const BlueSkyStoreImplementation *impl,
29 g_hash_table_insert(store_implementations, g_strdup(name), (gpointer)impl);
32 BlueSkyStore *bluesky_store_new(const gchar *type)
34 const BlueSkyStoreImplementation *impl;
36 impl = g_hash_table_lookup(store_implementations, type);
40 gpointer handle = impl->create();
44 BlueSkyStore *store = g_new(BlueSkyStore, 1);
46 store->handle = handle;
50 void bluesky_store_free(BlueSkyStore *store)
52 store->impl->destroy(store->handle);
56 BlueSkyRCStr *bluesky_store_get(BlueSkyStore *store, const gchar *key)
58 return store->impl->get(store->handle, key);
61 void bluesky_store_put(BlueSkyStore *store,
62 const gchar *key, BlueSkyRCStr *val)
64 store->impl->put(store->handle, key, val);
67 /* Create and return a new reference-counted string. The reference count is
68 * initially one. The newly-returned string takes ownership of the memory
69 * pointed at by data, and will call g_free on it when the reference count
71 BlueSkyRCStr *bluesky_string_new(gpointer data, gsize len)
73 BlueSkyRCStr *string = g_new(BlueSkyRCStr, 1);
76 g_atomic_int_set(&string->refcount, 1);
80 void bluesky_string_ref(BlueSkyRCStr *string)
85 g_atomic_int_inc(&string->refcount);
88 void bluesky_string_unref(BlueSkyRCStr *string)
93 if (g_atomic_int_dec_and_test(&string->refcount)) {
99 /* Duplicate and return a new reference-counted string, containing a copy of
100 * the original data, with a reference count of 1. As an optimization, if the
101 * passed-in string already has a reference count of 1, the original is
102 * returned. Can be used to make a mutable copy of a shared string. For this
103 * to truly be safe, it is probably needed that there be some type of lock
104 * protecting access to the string. */
105 BlueSkyRCStr *bluesky_string_dup(BlueSkyRCStr *string)
110 if (g_atomic_int_dec_and_test(&string->refcount)) {
111 /* There are no other shared copies, so return this one. */
112 g_atomic_int_inc(&string->refcount);
115 return bluesky_string_new(g_memdup(string->data, string->len),
120 /* Simple in-memory data store for test purposes. */
124 /* TODO: A hashtable isn't optimal for list queries... */
128 static gpointer memstore_create()
130 MemStore *store = g_new(MemStore, 1);
131 store->lock = g_mutex_new();
132 store->store = g_hash_table_new_full(g_str_hash, g_str_equal,
134 (GDestroyNotify)bluesky_string_unref);
136 return (gpointer)store;
139 static void memstore_destroy(gpointer store)
144 static BlueSkyRCStr *memstore_get(gpointer st, const gchar *key)
146 MemStore *store = (MemStore *)st;
147 BlueSkyRCStr *s = g_hash_table_lookup(store->store, key);
149 bluesky_string_ref(s);
153 static void memstore_put(gpointer s, const gchar *key, BlueSkyRCStr *val)
155 MemStore *store = (MemStore *)s;
156 bluesky_string_ref(val);
157 g_hash_table_insert(store->store, g_strdup(key), val);
160 static BlueSkyStoreImplementation memstore_impl = {
161 .create = memstore_create,
162 .destroy = memstore_destroy,
167 /* Store implementation which writes data as files to disk. */
168 static gpointer filestore_create()
170 return GINT_TO_POINTER(1);
173 static void filestore_destroy()
177 static BlueSkyRCStr *filestore_get(gpointer s, const gchar *key)
179 gchar *contents = NULL;
181 GError *error = NULL;
183 g_file_get_contents(key, &contents, &length, &error);
184 if (contents == NULL)
187 return bluesky_string_new(contents, length);
190 static void filestore_put(gpointer s, const gchar *key, BlueSkyRCStr *val)
192 g_file_set_contents(key, val->data, val->len, NULL);
195 static BlueSkyStoreImplementation filestore_impl = {
196 .create = filestore_create,
197 .destroy = filestore_destroy,
198 .get = filestore_get,
199 .put = filestore_put,
202 void bluesky_store_init()
204 store_implementations = g_hash_table_new(g_str_hash, g_str_equal);
205 bluesky_store_register(&memstore_impl, "mem");
206 bluesky_store_register(&filestore_impl, "file");