Apache Module Deveope
Memory Mangement
Ref: http://www.apachetutor.org/dev/pools
mytype* myvar = apr_palloc(pool, sizeof(mytype)) ;
char* result = apr_psprintf(pool, fmt, ...) ;
mytype* myvar = malloc(sizeof(mytype)) ;
apr_pool_cleanup_register(pool, myvar, free, apr_pool_cleanup_null) ;
FILE* f = fopen(filename, "r") ;
apr_pool_cleanup_register(pool, f, fclose, apr_pool_cleanup_null) ;
Avoid Double Free
void poolclassCleanup(void* ptr) { delete (poolclass*)ptr ; }
class poolclass {
private:
apr_pool_t* pool ;
public:
poolclass(apr_pool_t* p) : pool(p) {
apr_pool_cleanup_register(pool, (void*)this,
poolclassCleanup, apr_pool_cleanup_null) ;
}
virtual ~poolclass() {
apr_pool_cleanup_kill(pool, (void*)this, poolclassCleanup) ;
}
} ;
Connection Pooling
Ref: http://www.apachetutor.org/dev/reslist
// 构造器
static apr_status_t mysqlpool_construct(
void** db, void* params, apr_pool_t* pool
) {
svr_cfg* svr = (svr_cfg*) params ;
MYSQL* sql = NULL ;
sql = mysql_init(sql) ;
if ( sql == NULL ) {
ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, pool, "mysql_init failed") ;
return APR_EGENERAL ;
}
*db = mysql_real_connect(sql, svr->host, svr->user, svr->pass,
svr->db, svr->port, svr->sock, 0) ;
if ( ! *db ) {
ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, pool, "MySQL Error: %s",
mysql_error(sql) ) ;
return APR_EGENERAL ;
}
return APR_SUCCESS ;
}
// 析构器
static apr_status_t mysqlpool_destruct(
void* sql, void* params, apr_pool_t* pool
)
{
mysql_close((MYSQL*)sql) ;
return APR_SUCCESS ;
}
// 创建连接池
static int setup_db_pool(
apr_pool_t* p,
apr_pool_t* plog,
apr_pool_t* ptemp,
server_rec* s
){
svr_cfg* svr = (svr_cfg*)
ap_get_module_config(s->module_config, &mysql_pool_module) ;
if ( apr_reslist_create(&svr->dbpool,
svr->nmin,
svr->nkeep,
svr->nmax,
svr->exptime,
mysqlpool_construct, // 构造器
mysqlpool_destruct, // 析构器
svr, p) != APR_SUCCESS ) {
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s,
"MySQLPool: failed to initialise");
return 500 ;
}
// 注册清理函数
apr_pool_cleanup_register(p, svr->dbpool,
(void*)apr_reslist_destroy,
apr_pool_cleanup_null) ;
return OK ;
}
给应该用程序提供接口。
MYSQL* mysql_acquire(request_rec* r, unsigned int flags) {
mysql_request* req = (mysql_request*)
ap_get_module_config(r->request_config, &mysql_module) ;
if ( ! req ) { /* use pool if and only if we haven't already got one */
svr_cfg* svr = (svr_cfg*)
ap_get_module_config(r->server->module_config, &mysql_module) ;
req = (mysql_request*) apr_palloc(r->pool, sizeof(mysql_request) ) ;
req->flags = flags ;
req->dbpool = svr->dbpool ;
if ( apr_reslist_acquire(svr->dbpool, (void**)&req->sql)
!= APR_SUCCESS ) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Failed to acquire MySQL connection from pool") ;
return NULL ;
}
if ( mysql_ping(req->sql) != 0 ) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "MySQL: %s",
mysql_error(req->sql) ) ;
apr_reslist_invalidate(svr->dbpool, req->sql) ;
return NULL ;
}
ap_set_module_config(r->request_config, &mysql_module, req) ;
apr_pool_cleanup_register(r->pool, req,
mysql_release, apr_pool_cleanup_null) ;
} else {
req->flags |= flags ; /* ensure all required cleanups happen */
}
return req->sql ;
}