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>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 /* A stacked storage implementation which tries to improve performance by
32 * duplicating GET requests. Create using a name like "multi:s3" and each GET
33 * request will be translated into two GET requests to the "s3" backend. The
34 * first to complete will have its results returned. */
41 #include "bluesky-private.h"
46 static gpointer multistore_new(const gchar *path)
48 BlueSkyStore *base = bluesky_store_new(path);
50 g_warning("Unable to create base store %s for multirequest stacking.",
57 static void multistore_destroy(gpointer store)
59 bluesky_store_free(store);
62 static void multistore_completion_handler(BlueSkyStoreAsync *async,
63 BlueSkyStoreAsync *top_async)
65 g_mutex_lock(top_async->lock);
67 /* This might be the second request to finish; in that case we don't do
69 if (top_async->status == ASYNC_RUNNING) {
70 if (top_async->op == STORE_OP_GET) {
71 bluesky_string_unref(top_async->data);
72 top_async->data = async->data;
73 bluesky_string_ref(top_async->data);
75 top_async->result = async->result;
76 bluesky_store_async_mark_complete(top_async);
79 g_mutex_unlock(top_async->lock);
80 bluesky_store_async_unref(top_async);
83 static void multistore_submit(gpointer store, BlueSkyStoreAsync *async)
85 BlueSkyStore *base = (BlueSkyStore *)store;
87 g_return_if_fail(async->status == ASYNC_NEW);
88 g_return_if_fail(async->op != STORE_OP_NONE);
92 async->status = ASYNC_RUNNING;
93 async->exec_time = bluesky_now_hires();
94 for (int i = 0; i < 2; i++) {
95 BlueSkyStoreAsync *a = bluesky_store_async_new(base);
97 a->key = g_strdup(async->key);
98 bluesky_store_async_ref(async);
99 bluesky_store_async_add_notifier(a, (GFunc)multistore_completion_handler, async);
100 bluesky_store_async_submit(a);
101 bluesky_store_async_unref(a);
107 async->status = ASYNC_RUNNING;
108 async->exec_time = bluesky_now_hires();
110 bluesky_store_async_ref(async);
111 BlueSkyStoreAsync *a = bluesky_store_async_new(base);
112 a->op = STORE_OP_PUT;
113 a->key = g_strdup(async->key);
114 a->data = async->data;
115 bluesky_string_ref(a->data);
116 bluesky_store_async_add_notifier(a, (GFunc)multistore_completion_handler, async);
117 bluesky_store_async_submit(a);
118 bluesky_store_async_unref(a);
123 g_warning("Uknown operation type for multistore: %d\n", async->op);
124 bluesky_store_async_mark_complete(async);
129 static char *multistore_lookup_last(gpointer store, const char *prefix)
131 BlueSkyStore *base = (BlueSkyStore *)store;
132 return bluesky_store_lookup_last(base, prefix);
135 static void multistore_cleanup(gpointer store, BlueSkyStoreAsync *async)
139 static BlueSkyStoreImplementation store_impl = {
140 .create = multistore_new,
141 .destroy = multistore_destroy,
142 .submit = multistore_submit,
143 .cleanup = multistore_cleanup,
144 .lookup_last = multistore_lookup_last,
147 void bluesky_store_init_multi(void)
149 bluesky_store_register(&store_impl, "multi");