Implement flushing of file blocks to Amazon S3.
[bluesky.git] / 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.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 /* Create and return a new reference-counted string.  The reference count is
20  * initially one.  The newly-returned string takes ownership of the memory
21  * pointed at by data, and will call g_free on it when the reference count
22  * drops to zero. */
23 BlueSkyRCStr *bluesky_string_new(gpointer data, gsize len)
24 {
25     BlueSkyRCStr *string = g_new(BlueSkyRCStr, 1);
26     string->data = data;
27     string->len = len;
28     g_atomic_int_set(&string->refcount, 1);
29     return string;
30 }
31
32 void bluesky_string_ref(BlueSkyRCStr *string)
33 {
34     g_atomic_int_inc(&string->refcount);
35 }
36
37 void bluesky_string_unref(BlueSkyRCStr *string)
38 {
39     if (g_atomic_int_dec_and_test(&string->refcount)) {
40         g_free(string->data);
41         g_free(string);
42     }
43 }
44
45 /* Duplicate and return a new reference-counted string, containing a copy of
46  * the original data, with a reference count of 1.  As an optimization, if the
47  * passed-in string already has a reference count of 1, the original is
48  * returned.   Can be used to make a mutable copy of a shared string. */
49 BlueSkyRCStr *bluesky_string_dup(BlueSkyRCStr *string)
50 {
51     if (g_atomic_int_dec_and_test(&string->refcount)) {
52         /* There are no other shared copies, so return this one. */
53         g_atomic_int_inc(&string->refcount);
54         return string;
55     } else {
56         return bluesky_string_new(g_memdup(string->data, string->len),
57                                   string->len);
58     }
59 }
60
61 /* Simple in-memory data store for test purposes. */
62 typedef struct {
63     GMutex *lock;
64
65     /* TODO: A hashtable isn't optimal for list queries... */
66     GHashTable *store;
67 } MemStore;
68
69 MemStore *memstore_new()
70 {
71     MemStore *store = g_new(MemStore, 1);
72     store->lock = g_mutex_new();
73     store->store = g_hash_table_new_full(g_str_hash, g_str_equal,
74                                          g_free,
75                                          (GDestroyNotify)bluesky_string_unref);
76
77     return store;
78 }
79
80 BlueSkyRCStr *memstore_get(MemStore *store, const gchar *key)
81 {
82     BlueSkyRCStr *s = g_hash_table_lookup(store->store, key);
83     if (s != NULL)
84         bluesky_string_ref(s);
85     return s;
86 }
87
88 void memstore_put(MemStore *store, const gchar *key, BlueSkyRCStr *val)
89 {
90     bluesky_string_ref(val);
91     g_hash_table_insert(store->store, g_strdup(key), val);
92 }