From 719b660a3081cc1431c5dee8385b3e9785af2dd9 Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Thu, 24 Feb 2011 16:52:46 -0800 Subject: [PATCH] Add a CURL connection pool to the Azure backend. This will allow HTTP connections to be re-used. --- bluesky/store-azure.c | 46 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) 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; } -- 2.20.1