Ejemplo n.º 1
0
/**
Create S3HttpClient object.
method: HTTP method: GET, PUT, etc
url: string which contains S3 server's URL

Returns: new S3HttpClient object
or NULL if failed
 */
gpointer s3http_client_create (Application *app)
{
    S3HttpClient *http;

    http = g_new0 (S3HttpClient, 1);
    http->app = app;
    http->evbase = application_get_evbase (app);
    http->dns_base = application_get_dnsbase (app);
    http->is_acquired = FALSE;
  
    // default state
    http->connection_state = S3C_disconnected;
    
    http->output_buffer = evbuffer_new ();
    http->input_buffer = evbuffer_new ();
    
    http->bev = NULL;
    http->http_uri = NULL;
    http->l_input_headers = NULL;
    http->l_output_headers = NULL;

    s3http_client_request_reset (http);

    return (gpointer) http;
}
Ejemplo n.º 2
0
// create S3HttpConnection object
// establish HTTP connections to S3
gpointer s3http_connection_create (Application *app)
{
    S3HttpConnection *con;
    int port;
    AppConf *conf;

    con = g_new0 (S3HttpConnection, 1);
    if (!con) {
        LOG_err (CON_LOG, "Failed to create S3HttpConnection !");
        return NULL;
    }
    
    conf = application_get_conf (app);
    con->app = app;
    con->bucket_name = g_strdup (application_get_bucket_name (app));

    con->is_acquired = FALSE;

    port = application_get_port (app);
    // if no port is specified, libevent returns -1
    if (port == -1) {
        port = conf->http_port;
    }

    LOG_debug (CON_LOG, "Connecting to %s:%d", 
        application_get_host (app),
        port
    );

    // XXX: implement SSL
    con->evcon = evhttp_connection_base_new (
        application_get_evbase (app),
        application_get_dnsbase (app),
        application_get_host (app),
        port
    );

    if (!con->evcon) {
        LOG_err (CON_LOG, "Failed to create evhttp_connection !");
        return NULL;
    }
    
    evhttp_connection_set_timeout (con->evcon, conf->timeout);
    evhttp_connection_set_retries (con->evcon, conf->retries);

    evhttp_connection_set_closecb (con->evcon, s3http_connection_on_close, con);

    return (gpointer)con;
}
Ejemplo n.º 3
0
// retrieve file buffer from local storage
// if success == TRUE then "buf" contains "size" bytes of data
void cache_mng_retrieve_file_buf (CacheMng *cmng, fuse_ino_t ino, size_t size, off_t off, 
    cache_mng_on_retrieve_file_buf_cb on_retrieve_file_buf_cb, void *ctx)
{
    struct _CacheContext *context;
    struct _CacheEntry *entry;

    context = cache_context_create (size, ctx);
    context->cb.retrieve_cb = on_retrieve_file_buf_cb;
    entry = g_hash_table_lookup (cmng->h_entries, GUINT_TO_POINTER (ino));

    if (entry && range_contain (entry->avail_range, off, off + size)) {
        int fd;
        ssize_t res;
        char path[PATH_MAX];

        if (ino != entry->ino) {
            LOG_err (CMNG_LOG, "Requested inode doesn't match hashed key!");
            if (context->cb.retrieve_cb)
                context->cb.retrieve_cb (NULL, 0, FALSE, context->user_ctx);
            cache_context_destroy (context);
            return;
        }

        cache_mng_file_name (cmng, path, sizeof (path), ino);
        fd = open (path, O_RDONLY);

        context->buf = g_malloc (size);
        res = pread (fd, context->buf, size, off);
        close (fd);
        context->success = (res == (ssize_t) size);
        if (!context->success) {
            g_free (context->buf);
            context->buf = NULL;
        }

        // move entry to the front of q_lru
        g_queue_unlink (cmng->q_lru, entry->ll_lru);
        g_queue_push_head_link (cmng->q_lru, entry->ll_lru);
    } else {
        LOG_debug (CMNG_LOG, "Entry isn't found or doesn't contain requested range: %"INO_FMT, INO ino);
    }

    context->ev = event_new (application_get_evbase (cmng->app), -1,  0,
                    cache_read_cb, context);
    // fire this event at once
    event_active (context->ev, 0, 0);
    event_add (context->ev, NULL);
}
Ejemplo n.º 4
0
StatSrv *stat_srv_create (Application *app)
{
    StatSrv *stat_srv;
    
    stat_srv = g_new0 (StatSrv, 1);
    stat_srv->app = app;
    stat_srv->q_op_history = g_queue_new ();
    stat_srv->boot_time = time (NULL);

    // stats server is disabled
    if (!conf_get_boolean (application_get_conf (stat_srv->app), "statistics.enabled")) {
        return stat_srv;
    }

    stat_srv->http = evhttp_new (application_get_evbase (app));
    if (!stat_srv->http) {
        LOG_err (STAT_LOG, "Failed to create statistics server !");
        return NULL;
    }

    // bind
    if (evhttp_bind_socket (stat_srv->http, 
        conf_get_string (application_get_conf (stat_srv->app), "statistics.host"),
        conf_get_int (application_get_conf (stat_srv->app), "statistics.port")) == -1) {
        LOG_err (STAT_LOG, "Failed to bind statistics server to  %s:%d",
            conf_get_string (application_get_conf (stat_srv->app), "statistics.host"),
            conf_get_int (application_get_conf (stat_srv->app), "statistics.port")
        );
        return NULL;
    }

    // install handlers
    evhttp_set_cb (stat_srv->http, conf_get_string (application_get_conf (stat_srv->app), "statistics.stats_path"), stat_srv_on_stats_cb, stat_srv);
    evhttp_set_gencb (stat_srv->http, stat_srv_on_gen_cb, stat_srv);

    return stat_srv;
}
Ejemplo n.º 5
0
// creates connection pool object
// create client_count clients
// return NULL if error
S3ClientPool *s3client_pool_create (Application *app, 
    gint client_count,
    S3ClientPool_client_create client_create, 
    S3ClientPool_client_destroy client_destroy, 
    S3ClientPool_client_set_on_released_cb client_set_on_released_cb,
    S3ClientPool_client_check_rediness client_check_rediness)
{
    S3ClientPool *pool;
    gint i;
    PoolClient *pc;
    AppConf *conf;

    conf = application_get_conf (app);

    pool = g_new0 (S3ClientPool, 1);
    pool->app = app;
    pool->evbase = application_get_evbase (app);
    pool->dns_base = application_get_dnsbase (app);
    pool->l_clients = NULL;
    pool->q_requests = g_queue_new ();
    pool->max_requests = conf->max_requests_per_pool;
   
    for (i = 0; i < client_count; i++) {
        pc = g_new0 (PoolClient, 1);
        pc->pool = pool;
        pc->client = client_create (app);
        pc->client_check_rediness = client_check_rediness;
        pc->client_destroy = client_destroy;
        // add to the list
        pool->l_clients = g_list_append (pool->l_clients, pc);
        // add callback
        client_set_on_released_cb (pc->client, s3client_pool_on_client_released, pc);
    }

    return pool;
}
Ejemplo n.º 6
0
// store file buffer into local storage
// if success == TRUE then "buf" successfuly stored on disc
void cache_mng_store_file_buf (CacheMng *cmng, fuse_ino_t ino, size_t size, off_t off, unsigned char *buf,
    cache_mng_on_store_file_buf_cb on_store_file_buf_cb, void *ctx)
{
    struct _CacheContext *context;
    struct _CacheEntry *entry;
    ssize_t res;
    int fd;
    char path[PATH_MAX];
    guint64 old_length, new_length;
    guint64 range_size;
    time_t now;

    range_size = (guint64)(off + size);

    // limit the number of cache checks
    now = time (NULL);
    if (cmng->check_time < now && now - cmng->check_time >= 10) {
        // remove data until we have at least size bytes of max_size left
        while (cmng->max_size < cmng->size + size && g_queue_peek_tail (cmng->q_lru)) {
            entry = (struct _CacheEntry *) g_queue_peek_tail (cmng->q_lru);

            cache_mng_remove_file (cmng, entry->ino);
        }
        cmng->check_time = now;
    }

    context = cache_context_create (size, ctx);
    context->cb.store_cb = on_store_file_buf_cb;

    cache_mng_file_name (cmng, path, sizeof (path), ino);
    fd = open (path, O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (fd < 0) {
        LOG_err (CMNG_LOG, INO_H"Failed to create / open file for writing! Path: %s", INO_T (ino), path);
        if (context->cb.store_cb)
            context->cb.store_cb (FALSE, context->user_ctx);
        cache_context_destroy (context);
        return;
    }
    res = pwrite(fd, buf, size, off);
    close (fd);

    entry = g_hash_table_lookup (cmng->h_entries, GUINT_TO_POINTER (ino));

    if (!entry) {
        entry = cache_entry_create (ino);
        g_queue_push_head (cmng->q_lru, entry);
        entry->ll_lru = g_queue_peek_head_link (cmng->q_lru);
        g_hash_table_insert (cmng->h_entries, GUINT_TO_POINTER (ino), entry);
    }

    old_length = range_length (entry->avail_range);
    range_add (entry->avail_range, off, range_size);
    new_length = range_length (entry->avail_range);
    if (new_length >= old_length)
        cmng->size += new_length - old_length;
    else {
        LOG_err (CMNG_LOG, INO_H"New length is less than the old length !: %"G_GUINT64_FORMAT" <= %"G_GUINT64_FORMAT, 
            INO_T (ino), new_length, old_length);
    }
    
    // update modification time
    entry->modification_time = time (NULL);
   
    context->success = (res == (ssize_t) size);

    LOG_debug (CMNG_LOG, INO_H"Written [%"OFF_FMT":%zu] bytes, result: %s", 
        INO_T (ino), off, size, context->success ? "OK" : "Failed");

    context->ev = event_new (application_get_evbase (cmng->app), -1,  0,
                    cache_write_cb, context);
    // fire this event at once
    event_active (context->ev, 0, 0);
    event_add (context->ev, NULL);
}