Beispiel #1
0
void server_evbase_init()
{
    server.evconf = event_config_new();
    event_config_avoid_method(server.evconf, "select");
    event_config_avoid_method(server.evconf, "poll");
    server.evbase = event_base_new_with_config(server.evconf);
}
void
select_feature_test()
{
    struct event_config *config = event_config_new();
    event_config_avoid_method (config, "poll");
    event_config_avoid_method (config, "epoll");

    struct event_base *base = event_base_new_with_config (config);
    print_features(base);
    event_base_free(base);
}
Beispiel #3
0
EventBase::EventBase(const char* method)
{
    // enable locking for libevent structure
    if (evthread_use_pthreads())
    {
        throw std::exception();
    }

#ifdef DEBUG
    evthread_enable_lock_debuging();
    event_enable_debug_mode();
#endif

    struct event_config *config;
    config = event_config_new();

    int i = 0;
    const char** availMethods = event_get_supported_methods();

    for (i = 0; availMethods[i] != NULL; i++)
    {
        if (strcmp(availMethods[i], method)) {
            event_config_avoid_method(config, availMethods[i]);
        }
    }
    base_ = event_base_new_with_config(config);

    if (!base_)
    {
        throw BadBaseException();
    }
    event_base_get_method(base_);
    event_config_free(config);
}
bool IOEventLoop::EnsureInit() {
  if (ebase_ == nullptr) {
    event_config* cfg = event_config_new();
    if (cfg != nullptr) {
      if (use_precise_timer_) {
        event_config_set_flag(cfg, EVENT_BASE_FLAG_PRECISE_TIMER);
      }
      if (event_config_avoid_method(cfg, "epoll") != 0) {
        LOG(ERROR) << "event_config_avoid_method";
        return false;
      }
      ebase_ = event_base_new_with_config(cfg);
      // perf event files support reporting available data via poll methods. However, it doesn't
      // work well with epoll. Because perf_poll() in kernel/events/core.c uses a report and reset
      // way to report poll events. If perf_poll() is called twice, it may return POLLIN for the
      // first time, and no events for the second time. And epoll may call perf_poll() more than
      // once to confirm events. A failed situation is below:
      // When profiling SimpleperfExampleOfKotlin on Pixel device with `-g --duration 10`, the
      // kernel fills up the buffer before we call epoll_ctl(EPOLL_CTL_ADD). Then the POLLIN event
      // is returned when calling epoll_ctl(), while no events are returned when calling
      // epoll_wait(). As a result, simpleperf doesn't receive any poll wakeup events.
      if (strcmp(event_base_get_method(ebase_), "poll") != 0) {
        LOG(ERROR) << "event_base_get_method isn't poll: " << event_base_get_method(ebase_);
        return false;
      }
      event_config_free(cfg);
    }
    if (ebase_ == nullptr) {
      LOG(ERROR) << "failed to create event_base";
      return false;
    }
  }
  return true;
}
Beispiel #5
0
void EventLoop::initialize()
{
  // We need to initialize Libevent differently depending on the
  // operating system threading support.
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
  if (evthread_use_pthreads() < 0) {
    LOG(FATAL) << "Failed to initialize, evthread_use_pthreads";
  }
#elif defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED)
  if (evthread_use_windows_threads() < 0) {
    LOG(FATAL) << "Failed to initialize, evthread_use_windows_threads";
  }
#else
#error "Libevent must be compiled with either pthread or Windows thread support"
#endif

  // This enables debugging of libevent calls. We can remove this
  // when the implementation settles and after we gain confidence.
  event_enable_debug_mode();

  // TODO(jmlvanre): Allow support for 'epoll' once SSL related
  // issues are resolved.
  struct event_config* config = event_config_new();
  event_config_avoid_method(config, "epoll");

  base = event_base_new_with_config(config);

  if (base == NULL) {
    LOG(FATAL) << "Failed to initialize, event_base_new";
  }
}
Beispiel #6
0
struct event_base* server_event_base_init()
{
    struct event_config *config = event_config_new();
    event_config_avoid_method(config, "select");
    event_config_avoid_method(config, "poll");
    struct event_base *base = event_base_new_with_config(config);
    event_config_free(config);

    if(base == NULL)
    {
        log_err(__FILE__, __LINE__, "Cannot initialize event_base. error : %s", evutil_socket_error_to_string(errno));
        return NULL;
    }

    return base;
}
Beispiel #7
0
int opal_event_init(void)
{
    char **includes=NULL;
    bool dumpit=false;
    int i, j;

    if (opal_output_get_verbosity(opal_event_base_framework.framework_output) > 4) {
        event_enable_debug_mode();
        dumpit = true;
    }

    if (NULL == event_module_include) {
        /* Shouldn't happen, but... */
        event_module_include = strdup("select");
    }
    includes = opal_argv_split(event_module_include,',');

    /* get a configuration object */
    config = event_config_new();
    /* cycle thru the available subsystems */
    for (i = 0 ; NULL != eventops[i] ; ++i) {
        /* if this module isn't included in the given ones,
         * then exclude it
         */
        dumpit = true;
        for (j=0; NULL != includes[j]; j++) {
            if (0 == strcmp("all", includes[j]) ||
                0 == strcmp(eventops[i]->name, includes[j])) {
                dumpit = false;
                break;
            }
        }
        if (dumpit) {
            event_config_avoid_method(config, eventops[i]->name);
        }
    }
    opal_argv_free(includes);

    return OPAL_SUCCESS;
}
Beispiel #8
0
int main(int argc, char* argv[])
{

#if 1
    // For debug with segment fault
    struct sigaction sa;
    sa.sa_handler = backtrace_info;
    sigaction(SIGSEGV, &sa, NULL);

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

#endif

    int opt_g = 0;
    memset(&cltopt, 0, sizeof(CLT_OPT));

    cltopt.C_TYPE = C_USR;
    while( (opt_g = getopt(argc, argv, "Dh")) != -1 )
    {
        switch(opt_g)
        {
            case 'D':
                cltopt.C_TYPE = C_DAEMON;
                break;
            case 'h':
            default:
                usage();
                exit(EXIT_SUCCESS);
        }
    }

    if(load_settings_client(&cltopt) == RET_NO)
    {
        st_d_error("加载配置文件settings.json出错!");
        exit(EXIT_FAILURE);
    }

    OpenSSL_add_ssl_algorithms();
    SSL_load_error_strings();
    SSL_library_init();     //SSL_library_init() always returns "1"

    //int sd_id128_from_string(const char *s, sd_id128_t *ret);
    sd_id128_get_machine(&cltopt.mach_uuid);
    gethostname(cltopt.hostname, sizeof(cltopt.hostname)); 
    st_d_print("CURRENT MACH_ID:%s, HOSTNAME:%s", SD_ID128_CONST_STR(cltopt.mach_uuid), 
               cltopt.hostname);

    if (cltopt.C_TYPE == C_DAEMON) 
    {
        cltopt.session_uuid = cltopt.mach_uuid;
        st_d_print("PLEASE REMEMEBER SET MACH_ID FOR USER TYPE!");
    }

    dump_clt_opts(&cltopt);

    /*带配置产生event_base对象*/
    struct event_config *cfg;
    cfg = event_config_new();
    event_config_avoid_method(cfg, "select");   //避免使用select
    event_config_require_features(cfg, EV_FEATURE_ET);  //使用边沿触发类型
    base = event_base_new_with_config(cfg);
    event_config_free(cfg);
    st_d_print("当前复用Event模式: %s", event_base_get_method(base)); // epoll

    /*连接服务器*/
    int srv_fd = socket(AF_INET, SOCK_STREAM, 0);
    unsigned int optval = 1;
    setsockopt(srv_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法

    if(sc_connect_srv(srv_fd) != RET_YES) 
    {
        SYS_ABORT("连接服务器失败!");
    }

    if(cltopt.C_TYPE == C_DAEMON) 
    {
        if (sc_daemon_init_srv(srv_fd) != RET_YES) 
            SYS_ABORT("(Daemon) 服务器返回错误!");
    }
    else
    {
        if (sc_usr_init_srv(srv_fd) != RET_YES) 
            SYS_ABORT("(Usr) 服务器返回错误!");
    }

    st_d_print("客户端连接服务器OK!");

    /**
     * USR 建立本地Listen侦听套接字
     */

    if (cltopt.C_TYPE == C_USR)
    {
        int i = 0;
        for (i=0; i<MAX_PORT_NUM; i++)
        {
            if (cltopt.maps[i].usrport) 
            {
                struct evconnlistener *listener;
                struct sockaddr_in sin;
                memset(&sin, 0, sizeof(sin));
                sin.sin_family = AF_INET;
                sin.sin_addr.s_addr = htonl(0);
                sin.sin_port = htons(cltopt.maps[i].usrport); /* Port Num */

                listener = evconnlistener_new_bind(base, accept_conn_cb, &cltopt.maps[i],
                        LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1/*backlog 连接无限制*/,
                        (struct sockaddr*)&sin, sizeof(sin));

                if (!listener) 
                {
                    st_d_error("[USR]创建侦听套接字失败 %d:%d", 
                               cltopt.maps[i].usrport, cltopt.maps[i].daemonport); 
                    continue;
                }
                evconnlistener_set_error_cb(listener, accept_error_cb);

                st_d_print("[USR]创建侦听套接字 %d:%d OK", 
                               cltopt.maps[i].usrport, cltopt.maps[i].daemonport); 
            }
            else
                break;
        }
    }
    
    encrypt_init(SD_ID128_CONST_STR(cltopt.mach_uuid), cltopt.enc_key);

    if (cltopt.C_TYPE == C_DAEMON && cltopt.ss5_port ) 
    {
        /**
         * 目前只考虑将sockets5代理使用线程池来处理,其它的端口暴露 
         * 基本都是长连接,不单独处理 
         */
        cltopt.thread_num = 5;

        cltopt.main_thread_id = pthread_self(); 
        cltopt.thread_objs = (P_THREAD_OBJ)calloc(sizeof(THREAD_OBJ), cltopt.thread_num);
        if (!cltopt.thread_objs) 
        {
            SYS_ABORT("申请THREAD_OBJ出错");
        }


        sc_create_ss5_worker_threads(cltopt.thread_num, cltopt.thread_objs); 

        st_d_print("[DAEMON]创建sockets5代理端口:%d", cltopt.ss5_port); 

        struct evconnlistener *listener;
        struct sockaddr_in sin;
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = htonl(0);
        sin.sin_port = htons(cltopt.ss5_port); /* Port Num */

        listener = evconnlistener_new_bind(base, ss5_accept_conn_cb, NULL,
                LEV_OPT_LEAVE_SOCKETS_BLOCKING/* 阻塞 */|LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 
                -1/*backlog 连接无限制*/,
                (struct sockaddr*)&sin, sizeof(sin));

        if (!listener) 
        {
            st_d_error("[DAEMON]sockets5代理创建侦听套接字失败 %d", cltopt.ss5_port); 
            exit(EXIT_FAILURE); 
        }
        evconnlistener_set_error_cb(listener, accept_error_cb);

        st_d_print("[DAEMON]sockets5代理创建侦听套接字OK %d", cltopt.ss5_port); 

    }



    if (cltopt.C_TYPE == C_DAEMON && cltopt.dns_port) 
    {
        st_d_print("[DAEMON]创建DNS代理端口:%d", cltopt.dns_port); 
        if (cltopt.dns_port != 53) 
        {
            st_d_print("[DAEMON]请注意标准DNS侦听#53端口!");
        }

        int dns_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (dns_socket < 0 )
        {
            st_d_error("Create DNS socket error!");
            exit(EXIT_FAILURE);
        }

        unsigned int optval = 1;
        setsockopt(dns_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法
        setsockopt(dns_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
        evutil_make_socket_closeonexec(dns_socket);
        evutil_make_socket_nonblocking(dns_socket);

        struct sockaddr_in sin;
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = htonl(0);
        sin.sin_port = htons(cltopt.dns_port); /* Port Num */

        if (bind(dns_socket, (struct sockaddr *)&sin, sizeof(sin)))
        {
            st_d_error("Bind DNS socket error!");
            exit(EXIT_FAILURE);
        }

        cltopt.dns_transid_port_map = (unsigned short*)malloc(sizeof(unsigned short) * 0xFFFF);
        if (!cltopt.dns_transid_port_map) 
        {
            st_d_error("Malloc for requestid-port failed!");
            exit(EXIT_FAILURE);
        }

        P_PORTTRANS p_trans = sc_create_trans(cltopt.dns_port); 
        if (!p_trans)
        {
            st_d_error("本地无空闲TRANS!");
            exit(EXIT_FAILURE);
        }
        p_trans->is_enc = 1;
        p_trans->l_port = cltopt.dns_port;
        encrypt_ctx_init(&p_trans->ctx_enc, p_trans->l_port, cltopt.enc_key, 1); 
        encrypt_ctx_init(&p_trans->ctx_dec, p_trans->l_port, cltopt.enc_key, 0);
        // 建立DNS UDP事件侦听
        p_trans->extra_ev = event_new(base, dns_socket, EV_READ | EV_PERSIST, 
                                      dns_client_to_proxy_cb, p_trans);


        int dns_srv_fd = socket(AF_INET, SOCK_STREAM, 0);
        if(sc_connect_srv(dns_srv_fd) != RET_YES) 
        {
            SYS_ABORT("连接服务器失败!");
        }

        sc_daemon_dns_init_srv(dns_srv_fd, p_trans->l_port, 12333);
        evutil_make_socket_nonblocking(dns_srv_fd);

        // later enabled
        //event_add(p_trans->extra_ev, NULL) != 0);

        p_trans->srv_bev = bufferevent_socket_new(base, dns_srv_fd, BEV_OPT_CLOSE_ON_FREE);
        bufferevent_setcb(p_trans->srv_bev, dns_bufferread_cb_enc, NULL, dns_bufferevent_cb, p_trans);

        st_d_print("[DAEMON]DNS代理创建侦听套接字OK %d", cltopt.dns_port); 
    }

    sc_set_eventcb_srv(srv_fd, base); 

    /**
     * Main Loop Here
     */

    event_base_loop(base, 0);
    event_base_free(base);
    st_d_print("程序退出!!!!");
    return 0;
}
 static bool HHVM_METHOD(EventConfig, avoidMethod, const String& method)
 {
     InternalResourceData *event_config_resource_data = FETCH_RESOURCE(this_, InternalResourceData, s_event_config);
     return event_config_avoid_method((event_config_t *) event_config_resource_data->getInternalResourceData(), method.c_str()) == 0?true:false;
 }
Beispiel #10
0
int
tnt_fork(int imsg_fds[2]) {
    pid_t pid;
    struct imsgbuf ibuf;
    struct imsg_data data;
    struct passwd *pw;
    struct event_base *evbase = NULL;
    struct event *sigterm = NULL;
    struct event *sigint = NULL;
    struct event *imsg_event = NULL;
    struct server server;
    struct event_config *evcfg;

    switch ((pid = fork())) {
        case -1:
            log_err(TNT_OSERR, "fork");
            break;
        case 0:
            tnt_setproctitle("[unpriv]");
            log_set_prefix("unpriv");
            break;
        default:
            tnt_setproctitle("[priv]");
            log_set_prefix("priv");
            return pid;
    }

    if ((pw = getpwnam(TNETACLE_USER)) == NULL) {
        log_errx(1, "unknown user " TNETACLE_USER);
        return TNT_NOUSER;
    }

    /*Allocate the event config*/
    evcfg = event_config_new();

    /* Initialize the OpenSSL library */
    SSL_library_init();
    SSL_load_error_strings();
    /* We MUST have entropy, or else there's no point to crypto. */
    if (!RAND_poll())
    {
        log_errx(TNT_SOFTWARE, "[INIT] failed to find an entropy source");
        /* never returns */
    }

    if (serv_opts.encryption)
        server.server_ctx = evssl_init();
    else
        server.server_ctx = NULL;

    tnt_priv_drop(pw);

#if defined(Darwin)
    /* It's sad isn't it ?*/
    event_config_avoid_method(evcfg, "kqueue");
    event_config_avoid_method(evcfg, "poll");
    event_config_avoid_method(evcfg, "devpoll");
    if ((evbase = event_base_new_with_config(evcfg)) == NULL) {
        log_err(1, "libevent");
    }
#else
    if ((evbase = event_base_new_with_config(evcfg)) == NULL) {
        log_err(1, "libevent");
    }
#endif

    sigterm = event_new(evbase, SIGTERM, EV_SIGNAL, &chld_sighdlr, evbase);
    sigint = event_new(evbase, SIGINT, EV_SIGNAL, &chld_sighdlr, evbase);

    signal(SIGPIPE, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    signal(SIGCHLD, SIG_DFL);

    if (server_init(&server, evbase) == -1)
        log_errx(1, "failed to init the server socket");

    data.ibuf = &ibuf;
    data.evbase = evbase;
    data.server = &server;
    imsg_event = init_pipe_endpoint(imsg_fds, &data);

    event_add(sigterm, NULL);
    event_add(sigint, NULL);
    event_add(imsg_event, NULL);

    log_info("tnetacle ready");

    /* Immediately request the creation of a tun interface */
    imsg_compose(&ibuf, IMSG_CREATE_DEV, 0, 0, -1, NULL, 0);

    log_info("starting event loop");
    event_base_dispatch(evbase);

    /* cleanely exit */
    msgbuf_write(&ibuf.w);
    msgbuf_clear(&ibuf.w);

    /* Shutdown the server */
    server_delete(&server);

    /*
     * It may look like we freed this one twice,
     * once here and once in tnetacled.c but this is not the case.
     * Please don't erase this !
     */

    event_free(sigterm);
    event_free(sigint);
    close(event_get_fd(imsg_event));
    event_free(imsg_event);
    event_base_free(evbase);
    event_config_free(evcfg);

    log_info("tnetacle exiting");
    exit(TNT_OK);
}
Beispiel #11
0
/*{{{ 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;
}