コード例 #1
0
ファイル: stat_srv.c プロジェクト: bhrobinson/riofs
void stats_srv_add_op_history (StatSrv *stat_srv, const gchar *str)
{
    // stats server is disabled
    if (!conf_get_boolean (application_get_conf (stat_srv->app), "statistics.enabled"))
        return;

    // maintain queue size
    while (g_queue_get_length (stat_srv->q_op_history) + 1 >= conf_get_uint (application_get_conf (stat_srv->app), "statistics.history_size")) {
        gchar *tmp = g_queue_pop_tail (stat_srv->q_op_history);
        g_free (tmp);
    }

    g_queue_push_head (stat_srv->q_op_history, g_strdup (str));
}
コード例 #2
0
ファイル: file_io_ops.c プロジェクト: Nimain/riofs
static void fileio_release_update_headers (FileIO *fop)
{
    // update MD5 headers only if versioning is disabled
    if (conf_get_boolean (application_get_conf (fop->app), "s3.versioning")) {
        LOG_debug (FIO_LOG, INO_H"File uploaded !", INO_T (fop->ino));
        fileio_destroy (fop);
    } else {
        if (!client_pool_get_client (application_get_write_client_pool (fop->app),
            fileio_release_on_update_headers_con_cb, fop)) {
            LOG_err (FIO_LOG, INO_H"Failed to get HTTP client !", INO_T (fop->ino));
            fileio_destroy (fop);
            return;
        }
    }
}
コード例 #3
0
ファイル: stat_srv.c プロジェクト: bhrobinson/riofs
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;
}
コード例 #4
0
ファイル: main.c プロジェクト: skoobe/riofs
/*{{{ main */
int main (int argc, char *argv[])
{
    Application *app;
    gboolean verbose = FALSE;
    gboolean version = FALSE;
    GError *error = NULL;
    GOptionContext *context;
    gchar **s_params = NULL;
    gchar **s_config = NULL;
    gboolean foreground = FALSE;
    gchar conf_str[1023];
    struct stat st;
    gchar **cache_dir = NULL;
    gchar **s_fuse_opts = NULL;
    gchar **s_log_file = NULL;
    guint32 part_size = 0;
    gboolean disable_syslog = FALSE;
    gboolean disable_stats = FALSE;
    gboolean force_head_requests = FALSE;
    gint uid = -1;
    gint gid = -1;
    gint fmode = -1;
    gint dmode = -1;

    struct event_config *ev_config;

    srand (time (NULL));
    app = g_new0 (Application, 1);
    app->conf_path = g_build_filename (SYSCONFDIR, "riofs.conf.xml", NULL);
    g_snprintf (conf_str, sizeof (conf_str), "Path to configuration file. Default: %s", app->conf_path);

    GOptionEntry entries[] = {
        { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &s_params, NULL, NULL },
        { "config", 'c', 0, G_OPTION_ARG_FILENAME_ARRAY, &s_config, conf_str, NULL},

        { "uid", 0, 0, G_OPTION_ARG_INT, &uid, "Set UID of filesystem owner.", NULL },
        { "gid", 0, 0, G_OPTION_ARG_INT, &gid, "Set GID of filesystem owner.", NULL },
        { "fmode", 0, 0, G_OPTION_ARG_INT, &fmode, "Set mode for all files.", NULL },
        { "dmode", 0, 0, G_OPTION_ARG_INT, &dmode, "Set mode for all directories.", NULL },

        { "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Flag. Do not daemonize process.", NULL },
        { "cache-dir", 0, 0, G_OPTION_ARG_STRING_ARRAY, &cache_dir, "Set cache directory.", NULL },
        { "fuse-options", 'o', 0, G_OPTION_ARG_STRING_ARRAY, &s_fuse_opts, "Fuse options.", "\"opt[,opt...]\"" },
        { "disable-syslog", 0, 0, G_OPTION_ARG_NONE, &disable_syslog, "Flag. Disable logging to syslog.", NULL },
        { "disable-stats", 0, 0, G_OPTION_ARG_NONE, &disable_stats, "Flag. Disable Statistics HTTP interface.", NULL },
        { "part-size", 0, 0, G_OPTION_ARG_INT, &part_size, "Set file part size (in bytes).", NULL },
        { "log-file", 'l', 0, G_OPTION_ARG_STRING_ARRAY, &s_log_file, "File to write output.", NULL },
        { "force-head-requests", 0, 0, G_OPTION_ARG_NONE, &force_head_requests, "Flag. Send HEAD request for each file.", NULL },
        { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output.", NULL },
        { "version", 'V', 0, G_OPTION_ARG_NONE, &version, "Show application version and exit.", NULL },
        { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
    };

    // init libraries
    CRYPTO_set_mem_functions (g_malloc0, g_realloc, g_free);
    ENGINE_load_builtin_engines ();
    ENGINE_register_all_complete ();
    ERR_load_crypto_strings ();
    OpenSSL_add_all_algorithms ();
#ifdef SSL_ENABLED
    SSL_load_error_strings ();
    SSL_library_init ();
#endif
    g_random_set_seed (time (NULL));

    // init main app structure
    ev_config = event_config_new ();

#if defined(__APPLE__)
    // method select is the preferred method on OS X. kqueue and poll are not supported.
    event_config_avoid_method (ev_config, "kqueue");
    event_config_avoid_method (ev_config, "poll");
#endif

    app->evbase = event_base_new_with_config (ev_config);
    event_config_free (ev_config);

    if (!app->evbase) {
        LOG_err (APP_LOG, "Failed to create event base !");
        application_destroy (app);
        return -1;
    }

    app->dns_base = evdns_base_new (app->evbase, 1);
    if (!app->dns_base) {
        LOG_err (APP_LOG, "Failed to create DNS base !");
        application_destroy (app);
        return -1;
    }

    app->f_log = NULL;
    app->log_file_name = NULL;

/*{{{ cmd line args */

    // parse command line options
    context = g_option_context_new ("[bucketname] [mountpoint]");
    g_option_context_add_main_entries (context, entries, NULL);
    g_option_context_set_description (context, "Please set both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables!");
    if (!g_option_context_parse (context, &argc, &argv, &error)) {
        g_fprintf (stderr, "Failed to parse command line options: %s\n", error->message);
        application_destroy (app);
        g_option_context_free (context);
        return -1;
    }
    g_option_context_free (context);

        // check if --version is specified
    if (version) {
        g_fprintf (stdout, "RioFS File System v%s\n", VERSION);
        g_fprintf (stdout, "Copyright (C) 2012-2014 Paul Ionkin <*****@*****.**>\n");
        g_fprintf (stdout, "Copyright (C) 2012-2014 Skoobe GmbH. All rights reserved.\n");
        g_fprintf (stdout, "Libraries:\n");
        g_fprintf (stdout, " GLib: %d.%d.%d   libevent: %s  fuse: %d.%d",
                GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
                LIBEVENT_VERSION,
                FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION
        );
#if defined(__APPLE__) || defined(__FreeBSD__) || !defined(__GLIBC__)
        g_fprintf (stdout, "\n");
#else
        g_fprintf (stdout, "  glibc: %s\n", gnu_get_libc_version ());
#endif
        g_fprintf (stdout, "Features:\n");
        g_fprintf (stdout, " libevent backend method: %s\n", event_base_get_method(app->evbase));
#ifdef SSL_ENABLED
        g_fprintf (stdout, " SSL enabled\n");
#endif
        /*
        {
            int i;
            const char **methods = event_get_supported_methods ();

            g_fprintf (stdout, " Available libevent backend methods:\n");
            for (i = 0; methods[i] != NULL; ++i) {
                g_fprintf (stdout, "  %s\n", methods[i]);
            }
        }
        */

        return 0;
    }

    if (!s_params || g_strv_length (s_params) != 2) {
        LOG_err (APP_LOG, "Wrong number of provided arguments!\nTry `%s --help' for more information.", argv[0]);
        application_destroy (app);
        return -1;
    }

    if (verbose)
        log_level = LOG_debug;
    else
        log_level = LOG_msg;

/*}}}*/

/*{{{ parse config file */

    // user provided alternative config path
    if (s_config && g_strv_length (s_config) > 0) {
        g_free (app->conf_path);
        app->conf_path = g_strdup (s_config[0]);
        g_strfreev (s_config);
    }

    app->conf = conf_create ();
    if (access (app->conf_path, R_OK) == 0) {
        LOG_debug (APP_LOG, "Using config file: %s", app->conf_path);

        if (!conf_parse_file (app->conf, app->conf_path)) {
            LOG_err (APP_LOG, "Failed to parse configuration file: %s", app->conf_path);
            application_destroy (app);
            return -1;
        }

    } else {
        LOG_err (APP_LOG, "Configuration file is not found !");
        application_destroy (app);
        return -1;
    }

    if (!conf_check_keys (app->conf, conf_keys_str, conf_keys_len)) {
        LOG_err (APP_LOG, "Configuration file is missing keys, please re-check your configuration file: %s", app->conf_path);
        application_destroy (app);
        return -1;
    }

    if (disable_syslog) {
        conf_set_boolean (app->conf, "log.use_syslog", FALSE);
    }
    // update logging settings
    logger_set_syslog (conf_get_boolean (app->conf, "log.use_syslog"));
    logger_set_color (conf_get_boolean (app->conf, "log.use_color"));

    if (cache_dir && g_strv_length (cache_dir) > 0) {
        conf_set_string (app->conf, "filesystem.cache_dir", cache_dir[0]);
        g_strfreev (cache_dir);
    }

    if (!verbose)
        log_level = conf_get_int (app->conf, "log.level");

    if (uid >= 0)
        conf_set_int (app->conf, "filesystem.uid", uid);

    if (gid >= 0)
        conf_set_int (app->conf, "filesystem.gid", gid);

    if (fmode >= 0)
        conf_set_int (app->conf, "filesystem.file_mode", fmode);

    if (dmode >= 0)
        conf_set_int (app->conf, "filesystem.dir_mode", dmode);

/*}}}*/

    // try to get access parameters from the environment
    if (getenv ("AWS_ACCESS_KEY_ID")) {
        conf_set_string (app->conf, "s3.access_key_id", getenv ("AWS_ACCESS_KEY_ID"));
    // else check if it's set it the config file
    } else {
        if (!conf_node_exists (app->conf, "s3.access_key_id")) {
            LOG_err (APP_LOG, "Environment variables are not set!\nTry `%s --help' for more information.", argv[0]);
            application_destroy (app);
            return -1;
        }
    }
    if (getenv ("AWS_SECRET_ACCESS_KEY")) {
        conf_set_string (app->conf, "s3.secret_access_key", getenv ("AWS_SECRET_ACCESS_KEY"));
    } else {
        if (!conf_node_exists (app->conf, "s3.secret_access_key")) {
            LOG_err (APP_LOG, "Environment variables are not set!\nTry `%s --help' for more information.", argv[0]);
            application_destroy (app);
            return -1;
        }
    }

    // check if both strings are set
    if (!conf_get_string (app->conf, "s3.access_key_id") || !conf_get_string (app->conf, "s3.secret_access_key")) {
        LOG_err (APP_LOG, "Environment variables are not set!\nTry `%s --help' for more information.", argv[0]);
        application_destroy (app);
        return -1;
    }


    // foreground is set
    if (foreground)
        conf_set_boolean (app->conf, "app.foreground", foreground);

    if (part_size)
        conf_set_uint (app->conf, "s3.part_size", part_size);

    if (disable_stats)
        conf_set_boolean (app->conf, "statistics.enabled", FALSE);

    if (force_head_requests)
        conf_set_boolean (app->conf, "s3.force_head_requests_on_lookup", TRUE);
    else
        conf_set_boolean (app->conf, "s3.force_head_requests_on_lookup", FALSE);

    conf_set_string (app->conf, "s3.bucket_name", s_params[0]);
    if (!application_set_url (app, conf_get_string (app->conf, "s3.endpoint"))) {
        application_destroy (app);
        return -1;
    }

    if (s_fuse_opts && g_strv_length (s_fuse_opts) > 0) {
        app->fuse_opts = g_strdup (s_fuse_opts[0]);
        g_strfreev (s_fuse_opts);
    }

    if (s_log_file  && g_strv_length (s_log_file) > 0) {
        app->log_file_name = g_strdup (s_log_file[0]);
        app->f_log = fopen (s_log_file[0], "a+");
        if (!app->f_log) {
            LOG_err (APP_LOG, "Failed to open log file: %s Error: %s", s_log_file[0], strerror (errno));
            application_destroy (app);
            return -1;
        }

        LOG_debug (APP_LOG, "Using %s for storing application logs.", s_log_file[0]);
        logger_set_file (app->f_log);
        g_strfreev (s_log_file);
    }

    conf_set_string (app->conf, "app.mountpoint", s_params[1]);

    // check if directory exists
    if (stat (conf_get_string (app->conf, "app.mountpoint"), &st) == -1) {
        LOG_err (APP_LOG, "Mountpoint %s does not exist! Please check directory permissions!",
            conf_get_string (app->conf, "app.mountpoint"));
        application_destroy (app);
        return -1;
    }
    // check if it's a directory
    if (!S_ISDIR (st.st_mode)) {
        LOG_err (APP_LOG, "Mountpoint %s is not a directory!", conf_get_string (app->conf, "app.mountpoint"));
        application_destroy (app);
        return -1;
    }

    g_strfreev (s_params);

#ifdef SSL_ENABLED
    app->ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
    if (!app->ssl_ctx) {
        LOG_err (APP_LOG, "Failed to initialize SSL engine !");
        application_exit (app);
        return -1;
    }
    SSL_CTX_set_options (app->ssl_ctx, SSL_OP_ALL);
#endif

#ifdef MAGIC_ENABLED
    app->magic_ctx = magic_open(MAGIC_MIME_TYPE);
    if (!app->magic_ctx) {
        LOG_err(APP_LOG, "Failed to initialize magic library\n");
        return -1;
    }
    if (magic_load(app->magic_ctx, NULL)) {
        LOG_err(APP_LOG, "Failed to load magic database: %s\n", magic_error(app->magic_ctx));
        magic_close(app->magic_ctx);
        return -1;
    }
#endif

    app->stat_srv = stat_srv_create (app);
    if (!app->stat_srv) {
        application_exit (app);
        return -1;
    }

    // perform the initial request to get  bucket ACL (handles redirect as well)
    app->service_con = http_connection_create (app);
    if (!app->service_con)  {
        application_destroy (app);
        return -1;
    }
    bucket_client_get (app->service_con, "/?acl", application_on_bucket_acl_cb, app);

    // start the loop
    event_base_dispatch (app->evbase);

    application_destroy (app);

    return 0;
}
コード例 #5
0
ファイル: main.c プロジェクト: skoobe/riofs
/*{{{ application_finish_initialization_and_run */
static gint application_finish_initialization_and_run (Application *app)
{
    struct sigaction sigact;

/*{{{ create Pools */
    // create ClientPool for reading operations
    app->read_client_pool = client_pool_create (app, conf_get_int (app->conf, "pool.readers"),
        http_connection_create,
        http_connection_destroy,
        http_connection_set_on_released_cb,
        http_connection_check_rediness,
        http_connection_get_stats_info_caption,
        http_connection_get_stats_info_data
        );
    if (!app->read_client_pool) {
        LOG_err (APP_LOG, "Failed to create ClientPool !");
        application_exit (app);
        return -1;
    }

    // create ClientPool for writing operations
    app->write_client_pool = client_pool_create (app, conf_get_int (app->conf, "pool.writers"),
        http_connection_create,
        http_connection_destroy,
        http_connection_set_on_released_cb,
        http_connection_check_rediness,
        http_connection_get_stats_info_caption,
        http_connection_get_stats_info_data
        );
    if (!app->write_client_pool) {
        LOG_err (APP_LOG, "Failed to create ClientPool !");
        application_exit (app);
        return -1;
    }

    // create ClientPool for various operations
    app->ops_client_pool = client_pool_create (app, conf_get_int (app->conf, "pool.operations"),
        http_connection_create,
        http_connection_destroy,
        http_connection_set_on_released_cb,
        http_connection_check_rediness,
        http_connection_get_stats_info_caption,
        http_connection_get_stats_info_data
        );
    if (!app->ops_client_pool) {
        LOG_err (APP_LOG, "Failed to create ClientPool !");
        application_exit (app);
        return -1;
    }
/*}}}*/

/*{{{ CacheMng */
    app->cmng = cache_mng_create (app);
    if (!app->cmng) {
        LOG_err (APP_LOG, "Failed to create CacheMng !");
        application_exit (app);
        return -1;
    }
/*}}}*/

/*{{{ DirTree*/
    app->dir_tree = dir_tree_create (app);
    if (!app->dir_tree) {
        LOG_err (APP_LOG, "Failed to create DirTree !");
        application_exit (app);
        return -1;
    }
/*}}}*/

/*{{{ FUSE*/
    app->rfuse = rfuse_new (app, conf_get_string (app->conf, "app.mountpoint"), app->fuse_opts);
    if (!app->rfuse) {
        LOG_err (APP_LOG, "Failed to create FUSE fs ! Mount point: %s", conf_get_string (app->conf, "app.mountpoint"));
        application_exit (app);
        return -1;
    }
/*}}}*/

  // set global App variable
    _app = app;

/*{{{ signal handlers*/
    // SIGINT
    app->sigint_ev = evsignal_new (app->evbase, SIGINT, sigint_cb, app);
    event_add (app->sigint_ev, NULL);
    // SIGSEGV
    sigact.sa_sigaction = sigsegv_cb;
    sigact.sa_flags = (int)SA_RESETHAND | SA_SIGINFO;
    sigemptyset (&sigact.sa_mask);
    if (sigaction (SIGSEGV, &sigact, (struct sigaction *) NULL) != 0) {
        LOG_err (APP_LOG, "error setting signal handler for %d (%s)\n", SIGSEGV, strsignal(SIGSEGV));
        application_exit (app);
        return 1;
    }
    // SIGTERM
    app->sigterm_ev = evsignal_new (app->evbase, SIGTERM, sigterm_cb, app);
    event_add (app->sigterm_ev, NULL);
    // SIGABRT
    sigact.sa_sigaction = sigsegv_cb;
    sigact.sa_flags = (int)SA_RESETHAND | SA_SIGINFO;
    sigemptyset (&sigact.sa_mask);
    if (sigaction (SIGABRT, &sigact, (struct sigaction *) NULL) != 0) {
        LOG_err (APP_LOG, "error setting signal handler for %d (%s)\n", SIGABRT, strsignal(SIGABRT));
        application_exit (app);
        return 1;
    }
    // SIGPIPE
    app->sigpipe_ev = evsignal_new (app->evbase, SIGPIPE, sigpipe_cb, app);
    event_add (app->sigpipe_ev, NULL);

    // SIGUSR1
    app->sigusr1_ev = evsignal_new (app->evbase, SIGUSR1, sigusr1_cb, app);
    event_add (app->sigusr1_ev, NULL);

    // SIGUSR2
    app->sigusr2_ev = evsignal_new (app->evbase, SIGUSR2, sigusr2_cb, app);
    event_add (app->sigusr2_ev, NULL);

/*}}}*/

    if (!conf_get_boolean (app->conf, "app.foreground"))
        fuse_daemonize (0);

    return 0;
}
コード例 #6
0
ファイル: file_io_ops.c プロジェクト: Nimain/riofs
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);
}