X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Fstore.c;h=ac9bc96f7b21603805bdfc25dae4bb56304f3c32;hb=8ff0fd08d6e1cc97cdb7e94b7cd97dc28c29e674;hp=5cc475efcdbd2dc7c8ae0a08cc4b947a5f0641cb;hpb=4e24d47abcb5b0e97ab13afc8f97f8fdcab14843;p=bluesky.git diff --git a/bluesky/store.c b/bluesky/store.c index 5cc475e..ac9bc96 100644 --- a/bluesky/store.c +++ b/bluesky/store.c @@ -3,7 +3,29 @@ * Copyright (C) 2009 The Regents of the University of California * Written by Michael Vrable * - * TODO: Licensing + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include @@ -17,7 +39,7 @@ * (will) include Amazon S3 and a simple local store for testing purposes. * Operations may be performed asynchronously. */ -struct _BlueSkyStore { +struct BlueSkyStore { const BlueSkyStoreImplementation *impl; gpointer handle; @@ -87,6 +109,11 @@ void bluesky_store_free(BlueSkyStore *store) g_free(store); } +char *bluesky_store_lookup_last(BlueSkyStore *store, const char *prefix) +{ + return store->impl->lookup_last(store->handle, prefix); +} + BlueSkyStoreAsync *bluesky_store_async_new(BlueSkyStore *store) { BlueSkyStoreAsync *async; @@ -100,11 +127,14 @@ BlueSkyStoreAsync *bluesky_store_async_new(BlueSkyStore *store) async->op = STORE_OP_NONE; async->key = NULL; async->data = NULL; + async->start = async->len = 0; + async->range_done = FALSE; async->result = -1; async->notifiers = NULL; async->notifier_count = 0; async->barrier = NULL; async->store_private = NULL; + async->profile = NULL; return async; } @@ -213,6 +243,29 @@ void bluesky_store_async_mark_complete(BlueSkyStoreAsync *async) g_mutex_unlock(async->store->lock); } + /* If the request was a range request but the backend read the entire + * object, select out the appropriate bytes. */ + if (async->op == STORE_OP_GET + && !async->range_done + && async->result == 0 + && async->data != NULL) { + if (async->start != 0 || async->len != 0) { + /* If the caller requesteda read outside the object, return an + * error. */ + if (async->start + async->len > async->data->len) { + g_warning("Range request outside object boundaries!\n"); + async->result = -1; + } else { + if (async->len == 0) + async->len = async->data->len - async->start; + BlueSkyRCStr *newstr = bluesky_string_new(g_memdup(&async->data->data[async->start], async->len), async->len); + bluesky_string_unref(async->data); + async->data = newstr; + async->range_done = TRUE; + } + } + } + async->status = ASYNC_COMPLETE; g_cond_broadcast(async->completion_cond); @@ -225,6 +278,18 @@ void bluesky_store_async_mark_complete(BlueSkyStoreAsync *async) g_thread_pool_push(notifier_thread_pool, nl, NULL); } + if (async->profile) { + bluesky_profile_add_event( + async->profile, + g_strdup_printf("%s for %s complete", + async->op == STORE_OP_GET ? "GET" + : async->op == STORE_OP_PUT ? "PUT" + : async->op == STORE_OP_DELETE ? "DELETE" + : async->op == STORE_OP_BARRIER ? "BARRIER" : "???", + async->key) + ); + } + if (bluesky_verbose) { g_log("bluesky/store", G_LOG_LEVEL_DEBUG, "[%p] complete: elapsed = %"PRIi64" ns, latency = %"PRIi64" ns", @@ -250,6 +315,18 @@ void bluesky_store_async_submit(BlueSkyStoreAsync *async) // processing was started, if there could be a delay from submission time. async->exec_time = bluesky_now_hires(); + if (async->profile) { + bluesky_profile_add_event( + async->profile, + g_strdup_printf("Start %s for %s", + async->op == STORE_OP_GET ? "GET" + : async->op == STORE_OP_PUT ? "PUT" + : async->op == STORE_OP_DELETE ? "DELETE" + : async->op == STORE_OP_BARRIER ? "BARRIER" : "???", + async->key) + ); + } + if (bluesky_verbose) { g_log("bluesky/store", G_LOG_LEVEL_DEBUG, "[%p] submit: %s %s", async, @@ -494,11 +571,35 @@ static void filestore_cleanup(gpointer store, BlueSkyStoreAsync *async) { } +static char *filestore_lookup_last(gpointer store, const char *prefix) +{ + char *last = NULL; + GDir *dir = g_dir_open(".", 0, NULL); + if (dir == NULL) { + g_warning("Unable to open directory for listing"); + return NULL; + } + + const gchar *file; + while ((file = g_dir_read_name(dir)) != NULL) { + if (strncmp(file, prefix, strlen(prefix)) == 0) { + if (last == NULL || strcmp(file, last) > 0) { + g_free(last); + last = g_strdup(file); + } + } + } + g_dir_close(dir); + + return last; +} + static BlueSkyStoreImplementation filestore_impl = { .create = filestore_create, .destroy = filestore_destroy, .submit = filestore_submit, .cleanup = filestore_cleanup, + .lookup_last = filestore_lookup_last, }; /* A store implementation which simply discards all data, for testing. */