From: Michael Vrable Date: Tue, 26 Oct 2010 16:27:56 +0000 (-0700) Subject: Add support for byterange requests in the storage layer. X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=commitdiff_plain;h=d9bdc90da5c143d76cf3efd3c39b9bd190fb3741 Add support for byterange requests in the storage layer. --- diff --git a/bluesky/bluesky-private.h b/bluesky/bluesky-private.h index 2598772..1574a54 100644 --- a/bluesky/bluesky-private.h +++ b/bluesky/bluesky-private.h @@ -116,6 +116,14 @@ struct BlueSkyStoreAsync { gchar *key; /* Key to read/write */ BlueSkyRCStr *data; /* Data read/to write */ + /* For range requests on reads: starting byte offset and length; len 0 + * implies reading to the end of the object. At completion, the backend + * should set range_done if a range read was made; if not set the entire + * object was read and the storage layer will select out just the + * appropriate bytes. */ + size_t start, len; + gboolean range_done; + int result; /* Result code; 0 for success. */ struct BlueSkyNotifierList *notifiers; gint notifier_count; diff --git a/bluesky/store-s3.c b/bluesky/store-s3.c index 4735de4..03f497b 100644 --- a/bluesky/store-s3.c +++ b/bluesky/store-s3.c @@ -102,8 +102,9 @@ static void s3store_task(gpointer a, gpointer s) handler.responseHandler.completeCallback = s3store_response_callback; handler.getObjectDataCallback = s3store_get_handler; - S3_get_object(&store->bucket, async->key, NULL, 0, 0, NULL, - &handler, &info); + S3_get_object(&store->bucket, async->key, NULL, + async->start, async->len, NULL, &handler, &info); + async->range_done = TRUE; if (info.success) { async->data = bluesky_string_new_from_gstring(info.buf); diff --git a/bluesky/store.c b/bluesky/store.c index c2bb95e..5d9dc43 100644 --- a/bluesky/store.c +++ b/bluesky/store.c @@ -105,6 +105,8 @@ 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; @@ -218,6 +220,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);