Ejemplo n.º 1
0
/*{{{ GET request */
static void fileio_read_on_get_cb (HttpConnection *con, void *ctx, gboolean success,
    const gchar *buf, size_t buf_len,
    G_GNUC_UNUSED struct evkeyvalq *headers)
{
    FileReadData *rdata = (FileReadData *) ctx;
    const char *versioning_header = NULL;

    // release HttpConnection
    http_connection_release (con);

    if (!success) {
        LOG_err (FIO_LOG, INO_CON_H"Failed to get file from server !", INO_T (rdata->ino), con);
        rdata->on_buffer_read_cb (rdata->ctx, FALSE, NULL, 0);
        g_free (rdata);
        return;
    }

    // store it in the local cache
    cache_mng_store_file_buf (application_get_cache_mng (rdata->fop->app),
        rdata->ino, buf_len, rdata->request_offset, (unsigned char *) buf,
        NULL, NULL);

    // update version ID
    versioning_header = http_find_header (headers, "x-amz-version-id");
    if (versioning_header) {
        cache_mng_update_version_id (application_get_cache_mng (rdata->fop->app), rdata->ino, versioning_header);
    }

    LOG_debug (FIO_LOG, INO_H"Storing [%"G_GUINT64_FORMAT" %zu]", INO_T(rdata->ino), rdata->request_offset, buf_len);

    // and read it
    fileio_read_get_buf (rdata);
}
Ejemplo n.º 2
0
static void fileio_read_get_buf (FileReadData *rdata)
{
    if ((guint64)rdata->off >= rdata->fop->file_size) {
        // requested range is outsize the file size
        LOG_debug (FIO_LOG, INO_H"requested size is beyond the file size!", INO_T (rdata->ino));
        fileio_read_on_cache_cb (NULL, 0, TRUE, rdata);
        return;
    }

    // set new request size:
    // 1. file must have some size
    // 2. offset must be less than the file size
    // 3. offset + size is greater than the file size
    if (rdata->fop->file_size > 0 &&
        rdata->off >= 0 &&
        rdata->fop->file_size > (guint64)rdata->off &&
        (guint64) (rdata->off + rdata->size) > rdata->fop->file_size)
    {
        rdata->size = rdata->fop->file_size - rdata->off;
    // special case, when zero-size file is requested
    } else if (rdata->fop->file_size == 0) {
        rdata->size = 0;
    } else {
        // request size and offset are ok
    }

    LOG_debug (FIO_LOG, INO_H"requesting [%"OFF_FMT": %"G_GUINT64_FORMAT"], file size: %"G_GUINT64_FORMAT,
        INO_T (rdata->ino), rdata->off, rdata->size, rdata->fop->file_size);

    cache_mng_retrieve_file_buf (application_get_cache_mng (rdata->fop->app),
        rdata->ino, rdata->size, rdata->off,
        fileio_read_on_cache_cb, rdata);
}
Ejemplo n.º 3
0
// buffer is sent
static void fileio_write_on_send_cb (HttpConnection *con, void *ctx, gboolean success,
    G_GNUC_UNUSED const gchar *buf, G_GNUC_UNUSED size_t buf_len,
    G_GNUC_UNUSED struct evkeyvalq *headers)
{
    FileWriteData *wdata = (FileWriteData *) ctx;
    const char *versioning_header;

    http_connection_release (con);

    if (!success) {
        LOG_err (FIO_LOG, INO_CON_H"Failed to send bufer to server !", INO_T (wdata->ino), con);
        wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, FALSE, 0);
        g_free (wdata);
        return;
    }

    versioning_header = http_find_header (headers, "x-amz-version-id");
    if (versioning_header) {
        cache_mng_update_version_id (application_get_cache_mng (wdata->fop->app),
            wdata->ino, versioning_header);
    }

    // empty part buffer
    evbuffer_drain (wdata->fop->write_buf, -1);

    // done sending part
    wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, TRUE, wdata->buf_size);
    g_free (wdata);
}
Ejemplo n.º 4
0
// file is sent
static void fileio_release_on_part_sent_cb (HttpConnection *con, void *ctx, gboolean success,
    G_GNUC_UNUSED const gchar *buf, G_GNUC_UNUSED size_t buf_len,
    G_GNUC_UNUSED struct evkeyvalq *headers)
{
    FileIO *fop = (FileIO *) ctx;
    const gchar *versioning_header;

    http_connection_release (con);

    if (!success) {
        LOG_err (FIO_LOG, INO_CON_H"Failed to send bufer to server !", INO_T (fop->ino), con);
        fileio_destroy (fop);
        return;
    }

    versioning_header = http_find_header (headers, "x-amz-version-id");
    if (versioning_header) {
        cache_mng_update_version_id (application_get_cache_mng (fop->app),
            fop->ino, versioning_header);
    }
    // if it's a multi part upload - Complete Multipart Upload
    if (fop->multipart_initiated) {
        fileio_release_complete_multipart (fop);

    // or we are done
    } else {
        fileio_release_update_headers (fop);
        //fileio_destroy (fop);
    }
}
Ejemplo n.º 5
0
// multipart is sent
static void fileio_release_on_complete_cb (HttpConnection *con, void *ctx, gboolean success,
    G_GNUC_UNUSED const gchar *buf, G_GNUC_UNUSED size_t buf_len,
    G_GNUC_UNUSED struct evkeyvalq *headers)
{
    FileIO *fop = (FileIO *) ctx;
    const gchar *versioning_header;

    http_connection_release (con);

    if (!success) {
        LOG_err (FIO_LOG, INO_CON_H"Failed to send Multipart data to the server !", INO_T (fop->ino), con);
        fileio_destroy (fop);
        return;
    }

    versioning_header = http_find_header (headers, "x-amz-version-id");
    if (versioning_header) {
        cache_mng_update_version_id (application_get_cache_mng (fop->app),
            fop->ino, versioning_header);
    }

    // done
    LOG_debug (FIO_LOG, INO_CON_H"Multipart Upload is done !", INO_T (fop->ino), con);

    // fileio_destroy (fop);
    fileio_release_update_headers (fop);
}
Ejemplo n.º 6
0
void fileio_write_buffer (FileIO *fop,
    const char *buf, size_t buf_size, off_t off, fuse_ino_t ino,
    FileIO_on_buffer_written_cb on_buffer_written_cb, gpointer ctx)
{
    FileWriteData *wdata;

    // XXX: allow only sequentially write
    // current written bytes should be always match offset
    if (off >= 0 && fop->current_size != (guint64)off) {
        LOG_err (FIO_LOG, INO_H"Write call with offset %"OFF_FMT" is not allowed !", INO_T (ino), off);
        on_buffer_written_cb (fop, ctx, FALSE, 0);
        return;
    }

    // add data to output buffer
    evbuffer_add (fop->write_buf, buf, buf_size);
    fop->current_size += buf_size;

    LOG_debug (FIO_LOG, INO_H"Write buf size: %zd", INO_T (ino), evbuffer_get_length (fop->write_buf));

    // CacheMng
    cache_mng_store_file_buf (application_get_cache_mng (fop->app),
        ino, buf_size, off, (unsigned char *) buf,
        NULL, NULL);

    // if current write buffer exceeds "part_size" - this is a multipart upload
    if (evbuffer_get_length (fop->write_buf) >= conf_get_uint (application_get_conf (fop->app), "s3.part_size")) {
        // init helper struct
        wdata = g_new0 (FileWriteData, 1);
        wdata->fop = fop;
        wdata->buf_size = buf_size;
        wdata->off = off;
        wdata->ino = ino;
        wdata->on_buffer_written_cb = on_buffer_written_cb;
        wdata->ctx = ctx;

        // init multipart upload
        if (!fop->multipart_initiated) {
            fileio_write_init_multipart (wdata);

        // else send the current part
        } else {
            fileio_write_send_part (wdata);
        }

    // or just notify client that we are ready for more data
    } else {
        on_buffer_written_cb (fop, ctx, TRUE, buf_size);
    }
}
Ejemplo n.º 7
0
static void stat_srv_on_stats_cb (struct evhttp_request *req, void *ctx)
{
    StatSrv *stat_srv = (StatSrv *) ctx;
    struct evbuffer *evb = NULL;
    gint ref = 0;
    GString *str;
    struct evhttp_uri *uri;
    guint32 total_inodes, file_num, dir_num;
    guint64 read_ops, write_ops, readdir_ops, lookup_ops;
    guint32 cache_entries;
    guint64 total_cache_size, cache_hits, cache_miss;
    struct tm *cur_p;
    struct tm cur;
    time_t now;
    char ts[50];

    uri = evhttp_uri_parse (evhttp_request_get_uri (req));
    LOG_debug (STAT_LOG, "Incoming request: %s from %s:%d", 
        evhttp_request_get_uri (req), req->remote_host, req->remote_port);

    if (uri) {
        const gchar *query;
        
        query = evhttp_uri_get_query (uri);
        if (query) {
            const gchar *refresh = NULL;
            struct evkeyvalq q_params;
            
            TAILQ_INIT (&q_params);
            evhttp_parse_query_str (query, &q_params);
            refresh = http_find_header (&q_params, "refresh");
            if (refresh)
                ref = atoi (refresh);

            evhttp_clear_headers (&q_params);
        }
        evhttp_uri_free (uri);
    }

    str = g_string_new (NULL);
    
    now = time (NULL);
    localtime_r (&now, &cur);
    cur_p = &cur;
    if (!strftime (ts, sizeof (ts), "%H:%M:%S", cur_p))
        ts[0] = '\0';

    g_string_append_printf (str, "RioFS version: %s Uptime: %u sec, Now: %s, Log level: %d, Dir cache time: %u sec<BR>", 
        VERSION, (guint32)(now - stat_srv->boot_time), ts, log_level,
        conf_get_uint (application_get_conf (stat_srv->app), "filesystem.dir_cache_max_time"));

    // DirTree
    dir_tree_get_stats (application_get_dir_tree (stat_srv->app), &total_inodes, &file_num, &dir_num);
    g_string_append_printf (str, "<BR>DirTree: <BR>-Total inodes: %u, Total files: %u, Total directories: %u<BR>",
        total_inodes, file_num, dir_num);

    // Fuse
    rfuse_get_stats (application_get_rfuse (stat_srv->app), &read_ops, &write_ops, &readdir_ops, &lookup_ops);
    g_string_append_printf (str, "<BR>Fuse: <BR>-Read ops: %"G_GUINT64_FORMAT", Write ops: %"G_GUINT64_FORMAT
        ", Readdir ops: %"G_GUINT64_FORMAT", Lookup ops: %"G_GUINT64_FORMAT"<BR>",
        read_ops, write_ops, readdir_ops, lookup_ops);

    // CacheMng
    cache_mng_get_stats (application_get_cache_mng (stat_srv->app), &cache_entries, &total_cache_size, &cache_hits, &cache_miss);
    g_string_append_printf (str, "<BR>CacheMng: <BR>-Total entries: %"G_GUINT32_FORMAT", Total cache size: %"G_GUINT64_FORMAT
        " bytes, Cache hits: %"G_GUINT64_FORMAT", Cache misses: %"G_GUINT64_FORMAT" <BR>", 
        cache_entries, total_cache_size, cache_hits, cache_miss);
    
    g_string_append_printf (str, "<BR>Read workers (%d): <BR>", 
        client_pool_get_client_count (application_get_read_client_pool (stat_srv->app)));
    client_pool_get_client_stats_info (application_get_read_client_pool (stat_srv->app), str, &print_format_http);
    
    g_string_append_printf (str, "<BR>Write workers (%d): <BR>",
        client_pool_get_client_count (application_get_write_client_pool (stat_srv->app)));
    client_pool_get_client_stats_info (application_get_write_client_pool (stat_srv->app), str, &print_format_http);
    
    g_string_append_printf (str, "<BR>Op workers (%d): <BR>",
        client_pool_get_client_count (application_get_ops_client_pool (stat_srv->app)));
    client_pool_get_client_stats_info (application_get_ops_client_pool (stat_srv->app), str, &print_format_http);

    g_string_append_printf (str, "<BR><BR>Operation history (%u max items): <BR>",
        conf_get_uint (application_get_conf (stat_srv->app), "statistics.history_size"));
    g_queue_foreach (stat_srv->q_op_history, (GFunc) stat_srv_print_history_item, str);

    evb = evbuffer_new ();

    evbuffer_add_printf (evb, "<HTTP>");
    if (ref) {
        evbuffer_add_printf (evb, "<HEAD><meta http-equiv=\"refresh\" content=\"%d\"></HEAD>", ref);
    }
    evbuffer_add_printf (evb, "<BODY>");
    evbuffer_add (evb, str->str, str->len);
    evbuffer_add_printf (evb, "</BODY></HTTP>");
    evhttp_send_reply (req, HTTP_OK, "OK", evb);
    evbuffer_free (evb);

    g_string_free (str, TRUE);
}
Ejemplo n.º 8
0
static void fileio_read_on_head_cb (HttpConnection *con, void *ctx, gboolean success,
    G_GNUC_UNUSED const gchar *buf, G_GNUC_UNUSED size_t buf_len,
    struct evkeyvalq *headers)
{
    FileReadData *rdata = (FileReadData *) ctx;
    const char *content_len_header;
    DirTree *dtree;

    // release HttpConnection
    http_connection_release (con);

    if (!success) {
        LOG_err (FIO_LOG, INO_CON_H"Failed to get HEAD from server !", INO_T (rdata->ino), con);
        rdata->on_buffer_read_cb (rdata->ctx, FALSE, NULL, 0);
        g_free (rdata);
        return;
    }

    rdata->fop->head_req_sent = TRUE;
    // update DirTree
    dtree = application_get_dir_tree (rdata->fop->app);
    dir_tree_set_entry_exist (dtree, rdata->ino);

    // consistency checking:

    // 1. check local and remote file sizes
    content_len_header = http_find_header (headers, "Content-Length");
    if (content_len_header) {
        guint64 local_size = 0;
        gint64 size = 0;

        size = strtoll ((char *)content_len_header, NULL, 10);
        if (size < 0) {
            LOG_err (FIO_LOG, INO_CON_H"Header contains incorrect file size!", INO_T (rdata->ino), con);
            size = 0;
        }

        rdata->fop->file_size = size;
        LOG_debug (FIO_LOG, INO_H"Remote file size: %"G_GUINT64_FORMAT, INO_T (rdata->ino), rdata->fop->file_size);

        local_size = cache_mng_get_file_length (application_get_cache_mng (rdata->fop->app), rdata->ino);
        if (local_size != rdata->fop->file_size) {
            LOG_debug (FIO_LOG, INO_H"Local and remote file sizes do not match, invalidating local cached file!",
                INO_T (rdata->ino));
            cache_mng_remove_file (application_get_cache_mng (rdata->fop->app), rdata->ino);
        }
    }

    // 2. use one of the following ways to check that local and remote files are identical
    // if versioning is enabled: compare version IDs
    // if bucket has versioning disabled: compare MD5 sums
    if (conf_get_boolean (application_get_conf (rdata->fop->app), "s3.versioning")) {
        const char *versioning_header = http_find_header (headers, "x-amz-version-id");
        if (versioning_header) {
            const gchar *local_version_id = cache_mng_get_version_id (application_get_cache_mng (rdata->fop->app), rdata->ino);
            if (local_version_id && !strcmp (local_version_id, versioning_header)) {
                LOG_debug (FIO_LOG, INO_H"Both version IDs match, using local cached file!", INO_T (rdata->ino));
            } else {
                LOG_debug (FIO_LOG, INO_H"Version IDs do not match, invalidating local cached file!: %s %s",
                    INO_T (rdata->ino), local_version_id, versioning_header);
                cache_mng_remove_file (application_get_cache_mng (rdata->fop->app), rdata->ino);
            }

        // header was not found
        } else {
            LOG_debug (FIO_LOG, INO_H"Versioning header was not found, invalidating local cached file!", INO_T (rdata->ino));
            cache_mng_remove_file (application_get_cache_mng (rdata->fop->app), rdata->ino);
        }

    //check for MD5
    } else  {
        const char *md5_header = http_find_header (headers, "x-amz-meta-md5");
        if (md5_header) {
            gchar *md5str = NULL;

            // at this point we have both remote and local MD5 sums
            if (cache_mng_get_md5 (application_get_cache_mng (rdata->fop->app), rdata->ino, &md5str)) {
                if (!strncmp (md5_header, md5str, 32)) {
                    LOG_debug (FIO_LOG, INO_H"MD5 sums match, using local cached file!", INO_T (rdata->ino));
                } else {
                    LOG_debug (FIO_LOG, INO_H"MD5 sums do not match, invalidating local cached file!", INO_T (rdata->ino));
                    cache_mng_remove_file (application_get_cache_mng (rdata->fop->app), rdata->ino);
                }
            } else {
                LOG_debug (FIO_LOG, INO_H"Failed to get local MD5 sum, invalidating local cached file!", INO_T (rdata->ino));
                cache_mng_remove_file (application_get_cache_mng (rdata->fop->app), rdata->ino);
            }

            if (md5str)
                g_free (md5str);

        // header was not found
        } else {
            LOG_debug (FIO_LOG, INO_H"MD5 sum header was not found, invalidating local cached file!", INO_T (rdata->ino));
            cache_mng_remove_file (application_get_cache_mng (rdata->fop->app), rdata->ino);
        }
    }

    // resume downloading file
    fileio_read_get_buf (rdata);
}