diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-06-22 11:45:34 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-06-22 11:45:34 +0300 |
commit | ee18ef999d5cc87cc23455147924f96e7a91d3fa (patch) | |
tree | 91a255f8cf6e799f71d59f6ef5795f4f4a5282a2 | |
parent | b20b5cf9d52808f6f84971f2851046fb5248bd14 (diff) | |
download | smap-ee18ef999d5cc87cc23455147924f96e7a91d3fa.tar.gz smap-ee18ef999d5cc87cc23455147924f96e7a91d3fa.tar.bz2 |
Provide a default MySQL database.
* modules/mysql/mysql.c (mysql_db): Rename to mod_mysql_db.
New fields: flags, refcnt.
(def_db): New static.
(moddb_handle, moddb_positive_reply)
(moddb_negative_reply, opendb, closedb)
(freedb): New functions.
(mod_init): More options.
(mod_init_db): New option defaultdb.
(mod_free_db): Use freedb
(mod_open): Use opendb.
(mod_close): Use closedb.
(do_query, do_positive_reply, flush_result)
(mod_query): Use moddb_* accessors to get pointers to
MYSQL structure, positive and negative replies.
-rw-r--r-- | modules/mysql/mysql.c | 258 |
1 files changed, 177 insertions, 81 deletions
diff --git a/modules/mysql/mysql.c b/modules/mysql/mysql.c index 49331ad..6215872 100644 --- a/modules/mysql/mysql.c +++ b/modules/mysql/mysql.c @@ -31,13 +31,13 @@ #include <smap/stream.h> #include <smap/wordsplit.h> -static size_t dbgid; - -static char *def_positive_reply = "OK"; -static char *def_negative_reply = "NOTFOUND"; -static char *def_onerror_reply = NULL; +#define MDB_INIT 0x01 +#define MDB_OPEN 0x02 +#define MDB_DEFDB 0x04 -struct mysql_db { +struct mod_mysql_db { + int flags; + unsigned refcnt; MYSQL mysql; const char *name; char *config_file; @@ -55,29 +55,160 @@ struct mysql_db { char *onerror_reply; }; -int +static size_t dbgid; +static struct mod_mysql_db def_db; + +static MYSQL * +moddb_handle(struct mod_mysql_db *db) +{ + if (db->flags & MDB_DEFDB) + return &def_db.mysql; + return &db->mysql; +} + +static const char * +moddb_positive_reply(struct mod_mysql_db *db) +{ + return db->positive_reply ? + db->positive_reply : + (def_db.positive_reply ? def_db.positive_reply : "OK"); +} + +static const char * +moddb_negative_reply(struct mod_mysql_db *db) +{ + return db->negative_reply ? + db->negative_reply : + (def_db.negative_reply ? def_db.negative_reply : "NOTFOUND"); +} + +static int +opendb(struct mod_mysql_db *db) +{ + if (db->flags & MDB_OPEN) { + db->refcnt++; + return 0; + } + + if (!(db->flags & MDB_INIT)) { + smap_error("%s: module settings do not include opendb flag", + db->name); + return 1; + } + + if (!mysql_init(&db->mysql)) { + smap_error("%s: not enough memory", db->name); + return 1; + } + + if (db->config_file) + mysql_options(&db->mysql, MYSQL_READ_DEFAULT_FILE, + db->config_file); + if (db->config_group) + mysql_options (&db->mysql, MYSQL_READ_DEFAULT_GROUP, + db->config_group); + + if (db->ssl_ca) + mysql_ssl_set (&db->mysql, NULL, NULL, db->ssl_ca, + NULL, NULL); + + if (!mysql_real_connect(&db->mysql, + db->host, + db->user, + db->password, + db->database, + db->port, + db->socket, CLIENT_MULTI_RESULTS)) { + smap_error("%s: failed to connect to database, error: %s", + db->name, mysql_error(&db->mysql)); + mysql_close(&db->mysql); + return 1; + } + db->refcnt++; + db->flags |= MDB_OPEN; + return 0; +} + +static void +closedb(struct mod_mysql_db *db) +{ + if ((db->flags & MDB_OPEN) && --db->refcnt == 0) { + mysql_close(&db->mysql); + db->flags &= ~MDB_OPEN; + } +} + +static void +freedb(struct mod_mysql_db *db) +{ + free(db->config_file); + free(db->config_group); + free(db->ssl_ca); + free(db->host); + free(db->user); + free(db->password); + free(db->database); + free(db->socket); + free(db->template); + free(db->positive_reply); + free(db->negative_reply); + free(db->onerror_reply); +} + +static int mod_init(int argc, char **argv) { + int rc; + int opendb = 0; + dbgid = smap_debug_alloc("mysql"); - static struct smap_option init_option[] = { + struct smap_option init_option[] = { + { SMAP_OPTSTR(open), smap_opt_bool, + &opendb }, + { SMAP_OPTSTR(config-file), smap_opt_string, + &def_db.config_file }, + { SMAP_OPTSTR(config-group), smap_opt_string, + &def_db.config_group }, + { SMAP_OPTSTR(ssl-ca), smap_opt_string, + &def_db.ssl_ca }, + { SMAP_OPTSTR(host), smap_opt_string, + &def_db.host }, + { SMAP_OPTSTR(user), smap_opt_string, + &def_db.user }, + { SMAP_OPTSTR(password), smap_opt_string, + &def_db.password }, + { SMAP_OPTSTR(database), smap_opt_string, + &def_db.database }, + { SMAP_OPTSTR(port), smap_opt_long, + &def_db.port }, + { SMAP_OPTSTR(socket), smap_opt_string, + &def_db.socket }, + + { SMAP_OPTSTR(query), smap_opt_string, + &def_db.template }, { SMAP_OPTSTR(positive-reply), smap_opt_string, - &def_positive_reply }, + &def_db.positive_reply }, { SMAP_OPTSTR(negative-reply), smap_opt_string, - &def_negative_reply }, + &def_db.negative_reply }, { SMAP_OPTSTR(onerror-reply), smap_opt_string, - &def_onerror_reply }, + &def_db.onerror_reply }, { NULL } }; - return smap_parseopt(init_option, argc, argv, 0, NULL); + rc = smap_parseopt(init_option, argc, argv, 0, NULL); + if (rc) + return rc; + if (opendb) + def_db.flags = MDB_INIT; + return 0; } static smap_database_t mod_init_db(const char *dbid, int argc, char **argv) { - struct mysql_db *db; - char *positive_reply = def_positive_reply; - char *negative_reply = def_negative_reply; - char *onerror_reply = def_onerror_reply; + struct mod_mysql_db *db; + char *positive_reply = NULL; + char *negative_reply = NULL; + char *onerror_reply = NULL; char *query = NULL; char *config_file = NULL; char *config_group = NULL; @@ -88,7 +219,10 @@ mod_init_db(const char *dbid, int argc, char **argv) char *database = NULL; long port = 0; char *socket = NULL; + int flags = 0; struct smap_option init_option[] = { + { SMAP_OPTSTR(defaultdb), smap_opt_bitmask, + &flags, { MDB_DEFDB } }, { SMAP_OPTSTR(config-file), smap_opt_string, &config_file }, { SMAP_OPTSTR(config-group), smap_opt_string, @@ -122,16 +256,13 @@ mod_init_db(const char *dbid, int argc, char **argv) if (smap_parseopt(init_option, argc, argv, 0, NULL)) return NULL; - if (!query) { - smap_error("%s: query must be specified", dbid); - return NULL; - } - db = calloc(1, sizeof(*db)); if (!db) { smap_error("%s: not enough memory", dbid); return NULL; } + + db->flags = MDB_INIT | flags; db->name = dbid; db->config_file = config_file; db->config_group = config_group; @@ -153,21 +284,8 @@ mod_init_db(const char *dbid, int argc, char **argv) static int mod_free_db(smap_database_t dbp) { - struct mysql_db *db = (struct mysql_db *)dbp; - free(db->config_file); - free(db->config_group); - free(db->ssl_ca); - free(db->host); - free(db->user); - free(db->password); - free(db->database); - free(db->socket); - free(db->template); - /* FIXME: - free(db->positive_replyy); - free(db->negative_reply); - free(db->onerror_reply); - */ + struct mod_mysql_db *db = (struct mod_mysql_db *)dbp; + freedb(db); free(db); return 0; } @@ -175,44 +293,19 @@ mod_free_db(smap_database_t dbp) static int mod_open(smap_database_t dbp) { - struct mysql_db *db = (struct mysql_db *)dbp; - - if (!mysql_init(&db->mysql)) { - smap_error("%s: not enough memory", db->name); - return 1; - } - - if (db->config_file) - mysql_options(&db->mysql, MYSQL_READ_DEFAULT_FILE, - db->config_file); - if (db->config_group) - mysql_options (&db->mysql, MYSQL_READ_DEFAULT_GROUP, - db->config_group); - - if (db->ssl_ca) - mysql_ssl_set (&db->mysql, NULL, NULL, db->ssl_ca, - NULL, NULL); - - if (!mysql_real_connect(&db->mysql, - db->host, - db->user, - db->password, - db->database, - db->port, - db->socket, CLIENT_MULTI_RESULTS)) { - smap_error("%s: failed to connect to database, error: %s", - db->name, mysql_error(&db->mysql)); - mysql_close(&db->mysql); - return 1; - } - return 0; + struct mod_mysql_db *db = (struct mod_mysql_db *)dbp; + if (db->flags & MDB_DEFDB) + return opendb(&def_db); + return opendb(db); } static int mod_close(smap_database_t dbp) { - struct mysql_db *db = (struct mysql_db *)dbp; - mysql_close(&db->mysql); + struct mod_mysql_db *db = (struct mod_mysql_db *)dbp; + if (db->flags & MDB_DEFDB) + closedb(&def_db); + closedb(db); return 0; } @@ -280,10 +373,11 @@ create_query_env(const char *map, const char *key, } int -do_query(struct mysql_db *db, char **env, MYSQL_RES **pres) +do_query(struct mod_mysql_db *db, char **env, MYSQL_RES **pres) { struct wordsplit ws; int rc; + MYSQL *mysql = moddb_handle(db); MYSQL_RES *result; ws.ws_env = (const char **) env; @@ -300,7 +394,7 @@ do_query(struct mysql_db *db, char **env, MYSQL_RES **pres) smap_debug(dbgid, 1, ("running query: %s", ws.ws_wordv[0])); - rc = mysql_query(&db->mysql, ws.ws_wordv[0]); + rc = mysql_query(mysql, ws.ws_wordv[0]); if (rc) { smap_error("%s: query failed: %s", @@ -312,7 +406,7 @@ do_query(struct mysql_db *db, char **env, MYSQL_RES **pres) if (rc) return 1; - *pres = mysql_store_result(&db->mysql); + *pres = mysql_store_result(mysql); return 0; } @@ -343,7 +437,7 @@ send_reply(smap_stream_t ostr, const char *template, char **env) } static int -do_positive_reply(struct mysql_db *db, +do_positive_reply(struct mod_mysql_db *db, smap_stream_t ostr, char ***penv, MYSQL_RES *result) @@ -378,18 +472,19 @@ do_positive_reply(struct mysql_db *db, } env[i + j] = NULL; - return send_reply(ostr, db->positive_reply, env); + return send_reply(ostr, moddb_positive_reply(db), env); } /* Consume additional result sets */ static void -flush_result(struct mysql_db *db) +flush_result(struct mod_mysql_db *db) { - while (mysql_next_result(&db->mysql) == 0) { - MYSQL_RES *result = mysql_store_result(&db->mysql); + MYSQL *mysql = moddb_handle(db); + while (mysql_next_result(mysql) == 0) { + MYSQL_RES *result = mysql_store_result(mysql); if (!result) break; - if (mysql_field_count(&db->mysql)) + if (mysql_field_count(mysql)) while (mysql_fetch_row(result)) ; mysql_free_result(result); @@ -402,7 +497,7 @@ mod_query(smap_database_t dbp, const char *map, const char *key, struct smap_conninfo const *conninfo) { - struct mysql_db *db = (struct mysql_db *)dbp; + struct mod_mysql_db *db = (struct mod_mysql_db *)dbp; MYSQL_RES *res; int rc; char **env; @@ -425,11 +520,12 @@ mod_query(smap_database_t dbp, if (nrow > 0) rc = do_positive_reply(db, ostr, &env, res); else - rc = send_reply(ostr, db->negative_reply, env); + rc = send_reply(ostr, moddb_negative_reply(db), + env); mysql_free_result(res); flush_result(db); } else - rc = send_reply(ostr, db->negative_reply, env); + rc = send_reply(ostr, moddb_negative_reply(db), env); free_env(env); return rc; } |