Do not pad the final block of a file with zeroes.
[bluesky.git] / bluesky / store.c
1 /* Blue Sky: File Systems in the Cloud
2  *
3  * Copyright (C) 2009  The Regents of the University of California
4  * Written by Michael Vrable <mvrable@cs.ucsd.edu>
5  *
6  * TODO: Licensing
7  */
8
9 #include <stdint.h>
10 #include <glib.h>
11 #include <string.h>
12
13 #include "bluesky-private.h"
14
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. */
18
19 struct _BlueSkyStore {
20     const BlueSkyStoreImplementation *impl;
21     gpointer handle;
22 };
23
24 GHashTable *store_implementations;
25
26 void bluesky_store_register(const BlueSkyStoreImplementation *impl,
27                             const gchar *name)
28 {
29     g_hash_table_insert(store_implementations, g_strdup(name), (gpointer)impl);
30 }
31
32 BlueSkyStore *bluesky_store_new(const gchar *type)
33 {
34     const BlueSkyStoreImplementation *impl;
35
36     impl = g_hash_table_lookup(store_implementations, type);
37     if (impl == NULL)
38         return NULL;
39
40     gpointer handle = impl->create();
41     if (handle == NULL)
42         return NULL;
43
44     BlueSkyStore *store = g_new(BlueSkyStore, 1);
45     store->impl = impl;
46     store->handle = handle;
47     return store;
48 }
49
50 void bluesky_store_free(BlueSkyStore *store)
51 {
52     store->impl->destroy(store->handle);
53     g_free(store);
54 }
55
56 BlueSkyRCStr *bluesky_store_get(BlueSkyStore *store, const gchar *key)
57 {
58     return store->impl->get(store->handle, key);
59 }
60
61 void bluesky_store_put(BlueSkyStore *store,
62                        const gchar *key, BlueSkyRCStr *val)
63 {
64     store->impl->put(store->handle, key, val);
65 }
66
67 /* Simple in-memory data store for test purposes. */
68 typedef struct {
69     GMutex *lock;
70
71     /* TODO: A hashtable isn't optimal for list queries... */
72     GHashTable *store;
73 } MemStore;
74
75 static gpointer memstore_create()
76 {
77     MemStore *store = g_new(MemStore, 1);
78     store->lock = g_mutex_new();
79     store->store = g_hash_table_new_full(g_str_hash, g_str_equal,
80                                          g_free,
81                                          (GDestroyNotify)bluesky_string_unref);
82
83     return (gpointer)store;
84 }
85
86 static void memstore_destroy(gpointer store)
87 {
88     /* TODO */
89 }
90
91 static BlueSkyRCStr *memstore_get(gpointer st, const gchar *key)
92 {
93     MemStore *store = (MemStore *)st;
94     BlueSkyRCStr *s = g_hash_table_lookup(store->store, key);
95     if (s != NULL)
96         bluesky_string_ref(s);
97     return s;
98 }
99
100 static void memstore_put(gpointer s, const gchar *key, BlueSkyRCStr *val)
101 {
102     MemStore *store = (MemStore *)s;
103     bluesky_string_ref(val);
104     g_hash_table_insert(store->store, g_strdup(key), val);
105 }
106
107 static BlueSkyStoreImplementation memstore_impl = {
108     .create = memstore_create,
109     .destroy = memstore_destroy,
110     .get = memstore_get,
111     .put = memstore_put,
112 };
113
114 /* Store implementation which writes data as files to disk. */
115 static gpointer filestore_create()
116 {
117     return GINT_TO_POINTER(1);
118 }
119
120 static void filestore_destroy()
121 {
122 }
123
124 static BlueSkyRCStr *filestore_get(gpointer s, const gchar *key)
125 {
126     gchar *contents = NULL;
127     gsize length;
128     GError *error = NULL;
129
130     g_file_get_contents(key, &contents, &length, &error);
131     if (contents == NULL)
132         return NULL;
133
134     return bluesky_string_new(contents, length);
135 }
136
137 static void filestore_put(gpointer s, const gchar *key, BlueSkyRCStr *val)
138 {
139     g_file_set_contents(key, val->data, val->len, NULL);
140 }
141
142 static BlueSkyStoreImplementation filestore_impl = {
143     .create = filestore_create,
144     .destroy = filestore_destroy,
145     .get = filestore_get,
146     .put = filestore_put,
147 };
148
149 void bluesky_store_init()
150 {
151     store_implementations = g_hash_table_new(g_str_hash, g_str_equal);
152     bluesky_store_register(&memstore_impl, "mem");
153     bluesky_store_register(&filestore_impl, "file");
154 }