⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_dbd.c

📁 linux网络服务器工具
💻 C
📖 第 1 页 / 共 2 页
字号:
    apr_status_t rv;    rv = apr_pool_create(&rec_pool, pool);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server,                     "DBD: Failed to create memory pool");        return rv;    }    rec = apr_pcalloc(rec_pool, sizeof(ap_dbd_t));    rec->pool = rec_pool;    /* The driver is loaded at config time now, so this just checks a hash.     * If that changes, the driver DSO could be registered to unload against     * our pool, which is probably not what we want.  Error checking isn't     * necessary now, but in case that changes in the future ...     */    rv = apr_dbd_get_driver(rec->pool, cfg->name, &rec->driver);    if (rv != APR_SUCCESS) {        switch (rv) {        case APR_ENOTIMPL:            ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,                         "DBD: driver for %s not available", cfg->name);            break;        case APR_EDSOOPEN:            ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,                         "DBD: can't find driver for %s", cfg->name);            break;        case APR_ESYMNOTFOUND:            ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,                         "DBD: driver for %s is invalid or corrupted",                         cfg->name);            break;        default:            ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,                         "DBD: mod_dbd not compatible with APR in get_driver");            break;        }        apr_pool_destroy(rec->pool);        return rv;    }    rv = apr_dbd_open(rec->driver, rec->pool, cfg->params, &rec->handle);    if (rv != APR_SUCCESS) {        switch (rv) {        case APR_EGENERAL:            ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,                         "DBD: Can't connect to %s", cfg->name);            break;        default:            ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,                         "DBD: mod_dbd not compatible with APR in open");            break;        }        apr_pool_destroy(rec->pool);        return rv;    }    apr_pool_cleanup_register(rec->pool, rec, dbd_close,                              apr_pool_cleanup_null);    /* we use a sub-pool for the prepared statements for each connection so     * that they will be cleaned up first, before the connection is closed     */    rv = apr_pool_create(&prepared_pool, rec->pool);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server,                     "DBD: Failed to create memory pool");        apr_pool_destroy(rec->pool);        return rv;    }    rv = dbd_prepared_init(prepared_pool, cfg, rec);    if (rv != APR_SUCCESS) {        const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv);        ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,                     "DBD: failed to prepare SQL statements: %s",                     (errmsg ? errmsg : "[???]"));        apr_pool_destroy(rec->pool);        return rv;    }    *data_ptr = rec;    return APR_SUCCESS;}#if APR_HAS_THREADSstatic apr_status_t dbd_destroy(void *data){    dbd_group_t *group = data;    group->destroyed = 1;    return APR_SUCCESS;}static apr_status_t dbd_setup(server_rec *s, dbd_group_t *group){    dbd_cfg_t *cfg = group->cfg;    apr_status_t rv;    /* We create the reslist using a sub-pool of the pool passed to our     * child_init hook.  No other threads can be here because we're     * either in the child_init phase or dbd_setup_lock() acquired our mutex.     * No other threads will use this sub-pool after this, except via     * reslist calls, which have an internal mutex.     *     * We need to short-circuit the cleanup registered internally by     * apr_reslist_create().  We do this by registering dbd_destroy()     * as a cleanup afterwards, so that it will run before the reslist's     * internal cleanup.     *     * If we didn't do this, then we could free memory twice when the pool     * was destroyed.  When apr_pool_destroy() runs, it first destroys all     * all the per-connection sub-pools created in dbd_construct(), and     * then it runs the reslist's cleanup.  The cleanup calls dbd_destruct()     * on each resource, which would then attempt to destroy the sub-pools     * a second time.     */    rv = apr_reslist_create(&group->reslist,                            cfg->nmin, cfg->nkeep, cfg->nmax,                            apr_time_from_sec(cfg->exptime),                            dbd_construct, dbd_destruct, group,                            group->pool);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,                     "DBD: failed to initialise");        return rv;    }    apr_pool_cleanup_register(group->pool, group, dbd_destroy,                              apr_pool_cleanup_null);    return APR_SUCCESS;}#endifstatic apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s){    dbd_group_t *group;    apr_status_t rv = APR_SUCCESS;    for (group = group_list; group; group = group->next) {        apr_status_t rv2;        rv2 = apr_pool_create(&group->pool, pool);        if (rv2 != APR_SUCCESS) {            ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s,                         "DBD: Failed to create reslist cleanup memory pool");            return rv2;        }#if APR_HAS_THREADS        rv2 = dbd_setup(s, group);        if (rv2 == APR_SUCCESS) {            continue;        }        else if (rv == APR_SUCCESS) {            rv = rv2;        }        /* we failed, so create a mutex so that subsequent competing callers         * to ap_dbd_open can serialize themselves while they retry         */        rv2 = apr_thread_mutex_create(&group->mutex,                                      APR_THREAD_MUTEX_DEFAULT, pool);        if (rv2 != APR_SUCCESS) {             ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s,                          "DBD: Failed to create thread mutex");             return rv2;        }#endif    }    return rv;}#if APR_HAS_THREADSstatic apr_status_t dbd_setup_lock(server_rec *s, dbd_group_t *group){    apr_status_t rv = APR_SUCCESS, rv2;    /* several threads could be here at the same time, all trying to     * initialize the reslist because dbd_setup_init failed to do so     */    if (!group->mutex) {        /* we already logged an error when the mutex couldn't be created */        return APR_EGENERAL;    }    rv2 = apr_thread_mutex_lock(group->mutex);    if (rv2 != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,                     "DBD: Failed to acquire thread mutex");        return rv2;    }    if (!group->reslist) {        rv = dbd_setup(s, group);    }    rv2 = apr_thread_mutex_unlock(group->mutex);    if (rv2 != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,                     "DBD: Failed to release thread mutex");        if (rv == APR_SUCCESS) {            rv = rv2;        }    }    return rv;}#endif/* Functions we export for modules to use:        - open acquires a connection from the pool (opens one if necessary)        - close releases it back in to the pool*/DBD_DECLARE_NONSTD(void) ap_dbd_close(server_rec *s, ap_dbd_t *rec){    svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);    if (!svr->cfg->persist) {        apr_pool_destroy(rec->pool);    }#if APR_HAS_THREADS    else {        apr_reslist_release(svr->group->reslist, rec);    }#endif}static apr_status_t dbd_check(apr_pool_t *pool, server_rec *s, ap_dbd_t *rec){    svr_cfg *svr;    apr_status_t rv = apr_dbd_check_conn(rec->driver, pool, rec->handle);    const char *errmsg;    if ((rv == APR_SUCCESS) || (rv == APR_ENOTIMPL)) {        return APR_SUCCESS;    }    errmsg = apr_dbd_error(rec->driver, rec->handle, rv);    if (!errmsg) {        errmsg = "(unknown)";    }    svr = ap_get_module_config(s->module_config, &dbd_module);    ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,                 "DBD [%s] Error: %s", svr->cfg->name, errmsg);    return rv;}DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s){    svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);    dbd_group_t *group = svr->group;    dbd_cfg_t *cfg = svr->cfg;    ap_dbd_t *rec = NULL;#if APR_HAS_THREADS    apr_status_t rv;#endif    /* If nothing is configured, we shouldn't be here */    if (cfg->name == no_dbdriver) {        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "DBD: not configured");        return NULL;    }    if (!cfg->persist) {        /* Return a once-only connection */        group = apr_pcalloc(pool, sizeof(dbd_group_t));        group->cfg = cfg;        dbd_construct((void*) &rec, group, pool);        return rec;    }#if APR_HAS_THREADS    if (!group->reslist) {        if (dbd_setup_lock(s, group) != APR_SUCCESS) {            return NULL;        }    }    rv = apr_reslist_acquire(group->reslist, (void*) &rec);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,                     "Failed to acquire DBD connection from pool!");        return NULL;    }    if (dbd_check(pool, s, rec) != APR_SUCCESS) {        apr_reslist_invalidate(group->reslist, rec);        return NULL;    }#else    /* If we have a persistent connection and it's good, we'll use it;     * since this is non-threaded, we can update without a mutex     */    rec = group->rec;    if (rec) {        if (dbd_check(pool, s, rec) != APR_SUCCESS) {            apr_pool_destroy(rec->pool);            rec = NULL;        }    }    /* We don't have a connection right now, so we'll open one */    if (!rec) {        dbd_construct((void*) &rec, group, group->pool);        group->rec = rec;    }#endif    return rec;}#if APR_HAS_THREADStypedef struct {    ap_dbd_t *rec;    apr_reslist_t *reslist;} dbd_acquire_t;static apr_status_t dbd_release(void *data){    dbd_acquire_t *acq = data;    apr_reslist_release(acq->reslist, acq->rec);    return APR_SUCCESS;}DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r){    dbd_acquire_t *acq;    while (!ap_is_initial_req(r)) {        if (r->prev) {            r = r->prev;        }        else if (r->main) {            r = r->main;        }    }    acq = ap_get_module_config(r->request_config, &dbd_module);    if (!acq) {        acq = apr_palloc(r->pool, sizeof(dbd_acquire_t));        acq->rec = ap_dbd_open(r->pool, r->server);        if (acq->rec) {            svr_cfg *svr = ap_get_module_config(r->server->module_config,                                                &dbd_module);            ap_set_module_config(r->request_config, &dbd_module, acq);            if (svr->cfg->persist) {                acq->reslist = svr->group->reslist;                apr_pool_cleanup_register(r->pool, acq, dbd_release,                                          apr_pool_cleanup_null);            }        }    }    return acq->rec;}DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c){    dbd_acquire_t *acq = ap_get_module_config(c->conn_config, &dbd_module);    if (!acq) {        acq = apr_palloc(c->pool, sizeof(dbd_acquire_t));        acq->rec = ap_dbd_open(c->pool, c->base_server);        if (acq->rec) {            svr_cfg *svr = ap_get_module_config(c->base_server->module_config,                                                &dbd_module);            ap_set_module_config(c->conn_config, &dbd_module, acq);            if (svr->cfg->persist) {                acq->reslist = svr->group->reslist;                apr_pool_cleanup_register(c->pool, acq, dbd_release,                                          apr_pool_cleanup_null);            }        }    }    return acq->rec;}#elseDBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r){    ap_dbd_t *rec;    while (!ap_is_initial_req(r)) {        if (r->prev) {            r = r->prev;        }        else if (r->main) {            r = r->main;        }    }    rec = ap_get_module_config(r->request_config, &dbd_module);    if (!rec) {        rec = ap_dbd_open(r->pool, r->server);        if (rec) {            ap_set_module_config(r->request_config, &dbd_module, rec);        }    }    return rec;}DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c){    ap_dbd_t *rec = ap_get_module_config(c->conn_config, &dbd_module);    if (!rec) {        rec = ap_dbd_open(c->pool, c->base_server);        if (rec) {            ap_set_module_config(c->conn_config, &dbd_module, rec);        }    }    return rec;}#endifstatic void dbd_hooks(apr_pool_t *pool){    ap_hook_pre_config(dbd_pre_config, NULL, NULL, APR_HOOK_MIDDLE);    ap_hook_post_config(dbd_post_config, NULL, NULL, APR_HOOK_MIDDLE);    ap_hook_child_init((void*)dbd_setup_init, NULL, NULL, APR_HOOK_MIDDLE);    APR_REGISTER_OPTIONAL_FN(ap_dbd_prepare);    APR_REGISTER_OPTIONAL_FN(ap_dbd_open);    APR_REGISTER_OPTIONAL_FN(ap_dbd_close);    APR_REGISTER_OPTIONAL_FN(ap_dbd_acquire);    APR_REGISTER_OPTIONAL_FN(ap_dbd_cacquire);    apr_dbd_init(pool);}module AP_MODULE_DECLARE_DATA dbd_module = {    STANDARD20_MODULE_STUFF,    NULL,    NULL,    create_dbd_config,    merge_dbd_config,    dbd_cmds,    dbd_hooks};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -