/* 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));
* 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,
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) { \
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);
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
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;
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;
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)
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;
}