X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmysql%2Fmysql.c;h=098213b3358a40787ece6227d2e175bd7e859128;hb=67bbd4de1105d5afe7aec48d1ecd7a7da9d1043a;hp=0fc98308c0622d2dec47e3258d1504bb006fa7f6;hpb=3343e64659d6e8ff5ed6a74faac7226e55fc1c55;p=oweals%2Fgnunet.git diff --git a/src/mysql/mysql.c b/src/mysql/mysql.c index 0fc98308c..098213b33 100644 --- a/src/mysql/mysql.c +++ b/src/mysql/mysql.c @@ -53,12 +53,12 @@ */ struct GNUNET_MYSQL_Context { - + /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; - + /** * Our section. */ @@ -125,11 +125,12 @@ struct GNUNET_MYSQL_StatementHandle * Obtain the location of ".my.cnf". * * @param cfg our configuration + * @param section the section * @return NULL on error */ static char * get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *section) + const char *section) { char *cnffile; char *home_dir; @@ -147,12 +148,10 @@ get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_ERROR, "mysql", "getpwuid"); return NULL; } - if (GNUNET_YES == - GNUNET_CONFIGURATION_have_value (cfg, section, "CONFIG")) + if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, section, "CONFIG")) { GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_filename (cfg, - section, + GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG", &cnffile)); configured = GNUNET_YES; @@ -171,17 +170,16 @@ get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_free (home_dir); configured = GNUNET_NO; #endif - GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, - "mysql", - _("Trying to use file `%s' for MySQL configuration.\n"), cnffile); + GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql", + _("Trying to use file `%s' for MySQL configuration.\n"), + cnffile); if ((0 != STAT (cnffile, &st)) || (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode))) { if (configured == GNUNET_YES) - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, - "mysql", - _("Could not access file `%s': %s\n"), cnffile, - STRERROR (errno)); + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", + _("Could not access file `%s': %s\n"), cnffile, + STRERROR (errno)); GNUNET_free (cnffile); return NULL; } @@ -222,55 +220,45 @@ iopen (struct GNUNET_MYSQL_Context *mc) mysql_options (mc->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout); mysql_dbname = NULL; if (GNUNET_YES == - GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, - "DATABASE")) + GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "DATABASE")) GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (mc->cfg, - mc->section, + GNUNET_CONFIGURATION_get_value_string (mc->cfg, mc->section, "DATABASE", &mysql_dbname)); else mysql_dbname = GNUNET_strdup ("gnunet"); mysql_user = NULL; if (GNUNET_YES == - GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, - "USER")) + GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "USER")) { GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (mc->cfg, - mc->section, + GNUNET_CONFIGURATION_get_value_string (mc->cfg, mc->section, "USER", &mysql_user)); } mysql_password = NULL; if (GNUNET_YES == - GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, - "PASSWORD")) + GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "PASSWORD")) { GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (mc->cfg, - mc->section, + GNUNET_CONFIGURATION_get_value_string (mc->cfg, mc->section, "PASSWORD", &mysql_password)); } mysql_server = NULL; if (GNUNET_YES == - GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, - "HOST")) + GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "HOST")) { GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (mc->cfg, - mc->section, + GNUNET_CONFIGURATION_get_value_string (mc->cfg, mc->section, "HOST", &mysql_server)); } mysql_port = 0; if (GNUNET_YES == - GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, - "PORT")) + GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "PORT")) { GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (mc->cfg, - mc->section, + GNUNET_CONFIGURATION_get_value_number (mc->cfg, mc->section, "PORT", &mysql_port)); } @@ -300,7 +288,7 @@ iopen (struct GNUNET_MYSQL_Context *mc) */ struct GNUNET_MYSQL_Context * GNUNET_MYSQL_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *section) + const char *section) { struct GNUNET_MYSQL_Context *mc; @@ -308,19 +296,19 @@ GNUNET_MYSQL_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg, mc->cfg = cfg; mc->section = section; mc->cnffile = get_my_cnf_path (cfg, section); - + return mc; } /** * Close database connection and all prepared statements (we got a DB - * disconnect error). + * error). * * @param mc mysql context */ -static void -iclose (struct GNUNET_MYSQL_Context *mc) +void +GNUNET_MYSQL_statements_invalidate (struct GNUNET_MYSQL_Context *mc) { struct GNUNET_MYSQL_StatementHandle *sh; @@ -343,7 +331,7 @@ iclose (struct GNUNET_MYSQL_Context *mc) /** * Destroy a mysql context. Also frees all associated prepared statements. - * + * * @param mc context to destroy */ void @@ -351,7 +339,7 @@ GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc) { struct GNUNET_MYSQL_StatementHandle *sh; - iclose (mc); + GNUNET_MYSQL_statements_invalidate (mc); while (NULL != (sh = mc->shead)) { GNUNET_CONTAINER_DLL_remove (mc->shead, mc->stail, sh); @@ -359,6 +347,7 @@ GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc) GNUNET_free (sh); } GNUNET_free (mc); + mysql_library_end (); } @@ -372,7 +361,7 @@ GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc) */ struct GNUNET_MYSQL_StatementHandle * GNUNET_MYSQL_statement_prepare (struct GNUNET_MYSQL_Context *mc, - const char *query) + const char *query) { struct GNUNET_MYSQL_StatementHandle *sh; @@ -392,8 +381,7 @@ GNUNET_MYSQL_statement_prepare (struct GNUNET_MYSQL_Context *mc, * GNUNET_SYSERR if there was a problem */ int -GNUNET_MYSQL_statement_run (struct GNUNET_MYSQL_Context *mc, - const char *sql) +GNUNET_MYSQL_statement_run (struct GNUNET_MYSQL_Context *mc, const char *sql) { if ((NULL == mc->dbf) && (GNUNET_OK != iopen (mc))) return GNUNET_SYSERR; @@ -401,7 +389,7 @@ GNUNET_MYSQL_statement_run (struct GNUNET_MYSQL_Context *mc, if (mysql_error (mc->dbf)[0]) { LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", mc); - iclose (mc); + GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } return GNUNET_OK; @@ -426,7 +414,7 @@ prepare_statement (struct GNUNET_MYSQL_Context *mc, sh->statement = mysql_stmt_init (mc->dbf); if (NULL == sh->statement) { - iclose (mc); + GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } if (0 != mysql_stmt_prepare (sh->statement, sh->query, strlen (sh->query))) @@ -434,7 +422,7 @@ prepare_statement (struct GNUNET_MYSQL_Context *mc, LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", mc); mysql_stmt_close (sh->statement); sh->statement = NULL; - iclose (mc); + GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } sh->valid = GNUNET_YES; @@ -442,6 +430,24 @@ prepare_statement (struct GNUNET_MYSQL_Context *mc, } +/** + * Get internal handle for a prepared statement. This function should rarely + * be used, and if, with caution! On failures during the interaction with + * the handle, you must call 'GNUNET_MYSQL_statements_invalidate'! + * + * @param mc mysql context + * @param sh prepared statement to introspect + * @return MySQL statement handle, NULL on error + */ +MYSQL_STMT * +GNUNET_MYSQL_statement_get_stmt (struct GNUNET_MYSQL_Context * mc, + struct GNUNET_MYSQL_StatementHandle * sh) +{ + (void) prepare_statement (mc, sh); + return sh->statement; +} + + /** * Bind the parameters for the given MySQL statement * and run it. @@ -452,9 +458,8 @@ prepare_statement (struct GNUNET_MYSQL_Context *mc, * @return GNUNET_SYSERR on error, GNUNET_OK on success */ static int -init_params (struct GNUNET_MYSQL_Context *mc, - struct GNUNET_MYSQL_StatementHandle *sh, - va_list ap) +init_params (struct GNUNET_MYSQL_Context *mc, + struct GNUNET_MYSQL_StatementHandle *sh, va_list ap) { MYSQL_BIND qbind[MAX_PARAM]; unsigned int pc; @@ -513,112 +518,145 @@ init_params (struct GNUNET_MYSQL_Context *mc, } if (mysql_stmt_bind_param (sh->statement, qbind)) { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, - "mysql", - _("`%s' failed at %s:%d with error: %s\n"), - "mysql_stmt_bind_param", __FILE__, __LINE__, - mysql_stmt_error (sh->statement)); - iclose (mc); + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", + _("`%s' failed at %s:%d with error: %s\n"), + "mysql_stmt_bind_param", __FILE__, __LINE__, + mysql_stmt_error (sh->statement)); + GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } if (mysql_stmt_execute (sh->statement)) { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, - "mysql", - _("`%s' failed at %s:%d with error: %s\n"), - "mysql_stmt_execute", __FILE__, __LINE__, - mysql_stmt_error (sh->statement)); - iclose (mc); + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", + _("`%s' failed at %s:%d with error: %s\n"), + "mysql_stmt_execute", __FILE__, __LINE__, + mysql_stmt_error (sh->statement)); + GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } return GNUNET_OK; } + /** * Run a prepared SELECT statement. * * @param mc mysql context - * @param sh handle to SELECT statment + * @param s statement to run * @param result_size number of elements in results array * @param results pointer to already initialized MYSQL_BIND * array (of sufficient size) for passing results * @param processor function to call on each result * @param processor_cls extra argument to processor - * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective + * @param ap pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective * values (size + buffer-reference for pointers); terminated * with "-1" * @return GNUNET_SYSERR on error, otherwise * the number of successfully affected (or queried) rows */ int -GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, - struct GNUNET_MYSQL_StatementHandle *sh, - unsigned int result_size, MYSQL_BIND * results, - GNUNET_MYSQL_DataProcessor processor, - void *processor_cls, ...) +GNUNET_MYSQL_statement_run_prepared_select_va (struct GNUNET_MYSQL_Context *mc, + struct + GNUNET_MYSQL_StatementHandle *s, + unsigned int result_size, + MYSQL_BIND * results, + GNUNET_MYSQL_DataProcessor + processor, void *processor_cls, + va_list ap) { - va_list ap; int ret; unsigned int rsize; int total; - if (GNUNET_OK != prepare_statement (mc, sh)) + if (GNUNET_OK != prepare_statement (mc, s)) { GNUNET_break (0); return GNUNET_SYSERR; } - va_start (ap, processor_cls); - if (GNUNET_OK != init_params (mc, sh, ap)) + if (GNUNET_OK != init_params (mc, s, ap)) { GNUNET_break (0); - va_end (ap); return GNUNET_SYSERR; } - va_end (ap); - rsize = mysql_stmt_field_count (sh->statement); + rsize = mysql_stmt_field_count (s->statement); if (rsize > result_size) { GNUNET_break (0); return GNUNET_SYSERR; } - if (mysql_stmt_bind_result (sh->statement, results)) + if (mysql_stmt_bind_result (s->statement, results)) { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, - "mysql", - _("`%s' failed at %s:%d with error: %s\n"), - "mysql_stmt_bind_result", __FILE__, __LINE__, - mysql_stmt_error (sh->statement)); - iclose (mc); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("`%s' failed at %s:%d with error: %s\n"), + "mysql_stmt_bind_result", __FILE__, __LINE__, + mysql_stmt_error (s->statement)); + GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } total = 0; while (1) { - ret = mysql_stmt_fetch (sh->statement); + ret = mysql_stmt_fetch (s->statement); if (ret == MYSQL_NO_DATA) break; if (ret != 0) { - GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, - "mysql", - _("`%s' failed at %s:%d with error: %s\n"), - "mysql_stmt_fetch", __FILE__, __LINE__, - mysql_stmt_error (sh->statement)); - iclose (mc); + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", + _("`%s' failed at %s:%d with error: %s\n"), + "mysql_stmt_fetch", __FILE__, __LINE__, + mysql_stmt_error (s->statement)); + GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } - if (processor != NULL) - if (GNUNET_OK != processor (processor_cls, rsize, results)) - break; total++; + if ((NULL == processor) || + (GNUNET_OK != processor (processor_cls, rsize, results))) + break; } - mysql_stmt_reset (sh->statement); + mysql_stmt_reset (s->statement); return total; } +/** + * Run a prepared SELECT statement. + * + * @param mc mysql context + * @param sh handle to SELECT statment + * @param result_size number of elements in results array + * @param results pointer to already initialized MYSQL_BIND + * array (of sufficient size) for passing results + * @param processor function to call on each result + * @param processor_cls extra argument to processor + * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective + * values (size + buffer-reference for pointers); terminated + * with "-1" + * @return GNUNET_SYSERR on error, otherwise + * the number of successfully affected (or queried) rows + */ +int +GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, + struct GNUNET_MYSQL_StatementHandle + *sh, unsigned int result_size, + MYSQL_BIND * results, + GNUNET_MYSQL_DataProcessor + processor, void *processor_cls, ...) +{ + va_list ap; + int ret; + + va_start (ap, processor_cls); + ret = + GNUNET_MYSQL_statement_run_prepared_select_va (mc, sh, result_size, + results, processor, + processor_cls, ap); + va_end (ap); + return ret; +} + + /** * Run a prepared statement that does NOT produce results. * @@ -634,8 +672,8 @@ GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, */ int GNUNET_MYSQL_statement_run_prepared (struct GNUNET_MYSQL_Context *mc, - struct GNUNET_MYSQL_StatementHandle *sh, - unsigned long long *insert_id, ...) + struct GNUNET_MYSQL_StatementHandle *sh, + unsigned long long *insert_id, ...) { va_list ap; int affected; @@ -658,4 +696,3 @@ GNUNET_MYSQL_statement_run_prepared (struct GNUNET_MYSQL_Context *mc, /* end of mysql.c */ -