From: Michael Vrable Date: Fri, 25 Feb 2011 00:52:46 +0000 (-0800) Subject: Add a CURL connection pool to the Azure backend. X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=commitdiff_plain;h=719b660a3081cc1431c5dee8385b3e9785af2dd9 Add a CURL connection pool to the Azure backend. This will allow HTTP connections to be re-used. --- diff --git a/bluesky/store-azure.c b/bluesky/store-azure.c index 176d38b..00ff481 100644 --- a/bluesky/store-azure.c +++ b/bluesky/store-azure.c @@ -29,13 +29,46 @@ static const char *signature_headers[] = { /* Prototype Windows Azure backend for BlueSky. This is intended to be * minimally functional, but could use additional work for production use. */ +#define MAX_IDLE_CONNECTIONS 8 + typedef struct { GThreadPool *thread_pool; char *account, *container; uint8_t *key; size_t key_len; + + /* A pool of available idle connections that could be used. */ + GQueue *curl_pool; + GMutex *curl_pool_lock; } AzureStore; +static CURL *get_connection(AzureStore *store) +{ + CURL *curl = NULL; + + g_mutex_lock(store->curl_pool_lock); + if (!g_queue_is_empty(store->curl_pool)) { + curl = (CURL *)(g_queue_pop_head(store->curl_pool)); + } + g_mutex_unlock(store->curl_pool_lock); + + if (curl == NULL) + curl = curl_easy_init(); + + return curl; +} + +static void put_connection(AzureStore *store, CURL *curl) +{ + g_mutex_lock(store->curl_pool_lock); + g_queue_push_head(store->curl_pool, curl); + while (g_queue_get_length(store->curl_pool) > MAX_IDLE_CONNECTIONS) { + curl = (CURL *)(g_queue_pop_tail(store->curl_pool)); + curl_easy_cleanup(curl); + } + g_mutex_unlock(store->curl_pool_lock); +} + static void get_extra_headers(gchar *key, gchar *value, GList **headers) { key = g_ascii_strdown(key, strlen(key)); @@ -151,6 +184,7 @@ static void azure_compute_signature(AzureStore *store, * sent. This will compute an Azure authentication signature before sending * the request. */ static BlueSkyRCStr *submit_request(AzureStore *store, + CURL *curl, const char *method, const char *path, GHashTable *headers, @@ -177,7 +211,6 @@ static BlueSkyRCStr *submit_request(AzureStore *store, azure_compute_signature(store, headers, method, path); CURLcode status; - CURL *curl = curl_easy_init(); #define curl_easy_setopt_safe(opt, val) \ if ((status = curl_easy_setopt(curl, (opt), (val))) != CURLE_OK) { \ @@ -247,7 +280,7 @@ static BlueSkyRCStr *submit_request(AzureStore *store, cleanup: if (result != NULL && result_body != NULL) g_string_free(result_body, TRUE); - curl_easy_cleanup(curl); + curl_easy_reset(curl); curl_slist_free_all(curl_headers); g_free(uri); @@ -266,6 +299,7 @@ static void azurestore_task(gpointer a, gpointer s) g_free, g_free); BlueSkyRCStr *result = NULL; + CURL *curl = get_connection(store); if (async->op == STORE_OP_GET) { /* FIXME: We ought to check that the response returned the requested @@ -282,7 +316,7 @@ static void azurestore_task(gpointer a, gpointer s) g_strdup_printf("%zd-", async->start)); async->range_done = TRUE; } - result = submit_request(store, "GET", async->key, headers, NULL); + result = submit_request(store, curl, "GET", async->key, headers, NULL); if (result != NULL) { async->data = result; async->result = 0; @@ -294,7 +328,7 @@ static void azurestore_task(gpointer a, gpointer s) g_hash_table_insert(headers, g_strdup("Transfer-Encoding"), g_strdup("")); - result = submit_request(store, "PUT", async->key, + result = submit_request(store, curl, "PUT", async->key, headers, async->data); if (result != NULL) { async->result = 0; @@ -305,6 +339,7 @@ static void azurestore_task(gpointer a, gpointer s) bluesky_store_async_mark_complete(async); bluesky_store_async_unref(async); g_hash_table_unref(headers); + put_connection(store, curl); } static gpointer azurestore_new(const gchar *path) @@ -325,6 +360,9 @@ static gpointer azurestore_new(const gchar *path) g_print("Initializing Azure with account %s, container %s\n", store->account, store->container); + store->curl_pool = g_queue_new(); + store->curl_pool_lock = g_mutex_new(); + return store; }