diff options
Diffstat (limited to 'src/datacache/plugin_datacache_mysql.c')
-rw-r--r-- | src/datacache/plugin_datacache_mysql.c | 573 |
1 files changed, 22 insertions, 551 deletions
diff --git a/src/datacache/plugin_datacache_mysql.c b/src/datacache/plugin_datacache_mysql.c index 9185c5ca1..2ececa797 100644 --- a/src/datacache/plugin_datacache_mysql.c +++ b/src/datacache/plugin_datacache_mysql.c | |||
@@ -80,6 +80,7 @@ | |||
80 | #include "platform.h" | 80 | #include "platform.h" |
81 | #include "gnunet_util_lib.h" | 81 | #include "gnunet_util_lib.h" |
82 | #include "gnunet_datacache_plugin.h" | 82 | #include "gnunet_datacache_plugin.h" |
83 | #include "gnunet_mysql_lib.h" | ||
83 | #include <mysql/mysql.h> | 84 | #include <mysql/mysql.h> |
84 | 85 | ||
85 | #define DEBUG_DATACACHE_MYSQL GNUNET_EXTRA_LOGGING | 86 | #define DEBUG_DATACACHE_MYSQL GNUNET_EXTRA_LOGGING |
@@ -90,12 +91,6 @@ | |||
90 | #define OVERHEAD ((4*2+4*2+8*2+8*2+sizeof(GNUNET_HashCode)*5+8)) | 91 | #define OVERHEAD ((4*2+4*2+8*2+8*2+sizeof(GNUNET_HashCode)*5+8)) |
91 | 92 | ||
92 | /** | 93 | /** |
93 | * Maximum number of supported parameters for a prepared | ||
94 | * statement. Increase if needed. | ||
95 | */ | ||
96 | #define MAX_PARAM 16 | ||
97 | |||
98 | /** | ||
99 | * Die with an error message that indicates | 94 | * Die with an error message that indicates |
100 | * a failure of the command 'cmd' with the message given | 95 | * a failure of the command 'cmd' with the message given |
101 | * by strerror(errno). | 96 | * by strerror(errno). |
@@ -109,20 +104,6 @@ | |||
109 | */ | 104 | */ |
110 | #define LOG_MYSQL(level, cmd, dbh) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); } while(0); | 105 | #define LOG_MYSQL(level, cmd, dbh) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); } while(0); |
111 | 106 | ||
112 | struct GNUNET_MysqlStatementHandle | ||
113 | { | ||
114 | struct GNUNET_MysqlStatementHandle *next; | ||
115 | |||
116 | struct GNUNET_MysqlStatementHandle *prev; | ||
117 | |||
118 | char *query; | ||
119 | |||
120 | MYSQL_STMT *statement; | ||
121 | |||
122 | int valid; | ||
123 | |||
124 | }; | ||
125 | |||
126 | 107 | ||
127 | /** | 108 | /** |
128 | * Context for all functions in this plugin. | 109 | * Context for all functions in this plugin. |
@@ -137,536 +118,32 @@ struct Plugin | |||
137 | /** | 118 | /** |
138 | * Handle to the mysql database. | 119 | * Handle to the mysql database. |
139 | */ | 120 | */ |
140 | MYSQL *dbf; | 121 | struct GNUNET_MYSQL_Context *mc; |
141 | |||
142 | struct GNUNET_MysqlStatementHandle *shead; | ||
143 | |||
144 | struct GNUNET_MysqlStatementHandle *stail; | ||
145 | |||
146 | /** | ||
147 | * Filename of "my.cnf" (msyql configuration). | ||
148 | */ | ||
149 | char *cnffile; | ||
150 | 122 | ||
151 | #define SELECT_VALUE_STMT "SELECT value,expire FROM gn080dstore FORCE INDEX (hashidx) WHERE hash=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?" | 123 | #define SELECT_VALUE_STMT "SELECT value,expire FROM gn080dstore FORCE INDEX (hashidx) WHERE hash=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?" |
152 | struct GNUNET_MysqlStatementHandle *select_value; | 124 | struct GNUNET_MYSQL_StatementHandle *select_value; |
153 | 125 | ||
154 | #define COUNT_VALUE_STMT "SELECT count(*) FROM gn080dstore FORCE INDEX (hashidx) WHERE hash=? AND type=? AND expire >= ?" | 126 | #define COUNT_VALUE_STMT "SELECT count(*) FROM gn080dstore FORCE INDEX (hashidx) WHERE hash=? AND type=? AND expire >= ?" |
155 | struct GNUNET_MysqlStatementHandle *count_value; | 127 | struct GNUNET_MYSQL_StatementHandle *count_value; |
156 | 128 | ||
157 | #define SELECT_OLD_VALUE_STMT "SELECT hash, vhash, type, value FROM gn080dstore FORCE INDEX (expireidx) ORDER BY puttime ASC LIMIT 1" | 129 | #define SELECT_OLD_VALUE_STMT "SELECT hash, vhash, type, value FROM gn080dstore FORCE INDEX (expireidx) ORDER BY puttime ASC LIMIT 1" |
158 | struct GNUNET_MysqlStatementHandle *select_old_value; | 130 | struct GNUNET_MYSQL_StatementHandle *select_old_value; |
159 | 131 | ||
160 | #define DELETE_VALUE_STMT "DELETE FROM gn080dstore WHERE hash = ? AND vhash = ? AND type = ? AND value = ?" | 132 | #define DELETE_VALUE_STMT "DELETE FROM gn080dstore WHERE hash = ? AND vhash = ? AND type = ? AND value = ?" |
161 | struct GNUNET_MysqlStatementHandle *delete_value; | 133 | struct GNUNET_MYSQL_StatementHandle *delete_value; |
162 | 134 | ||
163 | #define INSERT_VALUE_STMT "INSERT INTO gn080dstore (type, puttime, expire, hash, vhash, value) "\ | 135 | #define INSERT_VALUE_STMT "INSERT INTO gn080dstore (type, puttime, expire, hash, vhash, value) "\ |
164 | "VALUES (?, ?, ?, ?, ?, ?)" | 136 | "VALUES (?, ?, ?, ?, ?, ?)" |
165 | struct GNUNET_MysqlStatementHandle *insert_value; | 137 | struct GNUNET_MYSQL_StatementHandle *insert_value; |
166 | 138 | ||
167 | #define UPDATE_VALUE_STMT "UPDATE gn080dstore FORCE INDEX (allidx) SET puttime=?, expire=? "\ | 139 | #define UPDATE_VALUE_STMT "UPDATE gn080dstore FORCE INDEX (allidx) SET puttime=?, expire=? "\ |
168 | "WHERE hash=? AND vhash=? AND type=?" | 140 | "WHERE hash=? AND vhash=? AND type=?" |
169 | struct GNUNET_MysqlStatementHandle *update_value; | 141 | struct GNUNET_MYSQL_StatementHandle *update_value; |
170 | 142 | ||
171 | }; | 143 | }; |
172 | 144 | ||
173 | 145 | ||
174 | /** | 146 | /** |
175 | * Obtain the location of ".my.cnf". | ||
176 | * | ||
177 | * @param cfg our configuration | ||
178 | * @return NULL on error | ||
179 | */ | ||
180 | static char * | ||
181 | get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
182 | { | ||
183 | char *cnffile; | ||
184 | char *home_dir; | ||
185 | struct stat st; | ||
186 | |||
187 | #ifndef WINDOWS | ||
188 | struct passwd *pw; | ||
189 | #endif | ||
190 | int configured; | ||
191 | |||
192 | #ifndef WINDOWS | ||
193 | pw = getpwuid (getuid ()); | ||
194 | if (!pw) | ||
195 | { | ||
196 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "getpwuid"); | ||
197 | return NULL; | ||
198 | } | ||
199 | if (GNUNET_YES == | ||
200 | GNUNET_CONFIGURATION_have_value (cfg, "datacache-mysql", "CONFIG")) | ||
201 | { | ||
202 | GNUNET_assert (GNUNET_OK == | ||
203 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
204 | "datacache-mysql", | ||
205 | "CONFIG", | ||
206 | &cnffile)); | ||
207 | configured = GNUNET_YES; | ||
208 | } | ||
209 | else | ||
210 | { | ||
211 | home_dir = GNUNET_strdup (pw->pw_dir); | ||
212 | GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); | ||
213 | GNUNET_free (home_dir); | ||
214 | configured = GNUNET_NO; | ||
215 | } | ||
216 | #else | ||
217 | home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); | ||
218 | plibc_conv_to_win_path ("~/", home_dir); | ||
219 | GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); | ||
220 | GNUNET_free (home_dir); | ||
221 | configured = GNUNET_NO; | ||
222 | #endif | ||
223 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
224 | _("Trying to use file `%s' for MySQL configuration.\n"), cnffile); | ||
225 | if ((0 != STAT (cnffile, &st)) || (0 != ACCESS (cnffile, R_OK)) || | ||
226 | (!S_ISREG (st.st_mode))) | ||
227 | { | ||
228 | if (configured == GNUNET_YES) | ||
229 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
230 | _("Could not access file `%s': %s\n"), cnffile, | ||
231 | STRERROR (errno)); | ||
232 | GNUNET_free (cnffile); | ||
233 | return NULL; | ||
234 | } | ||
235 | return cnffile; | ||
236 | } | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Free a prepared statement. | ||
241 | * | ||
242 | * @param plugin plugin context | ||
243 | * @param s prepared statement | ||
244 | */ | ||
245 | static void | ||
246 | prepared_statement_destroy (struct Plugin *plugin, | ||
247 | struct GNUNET_MysqlStatementHandle *s) | ||
248 | { | ||
249 | GNUNET_CONTAINER_DLL_remove (plugin->shead, plugin->stail, s); | ||
250 | if (s->valid) | ||
251 | mysql_stmt_close (s->statement); | ||
252 | GNUNET_free (s->query); | ||
253 | GNUNET_free (s); | ||
254 | } | ||
255 | |||
256 | |||
257 | /** | ||
258 | * Close database connection and all prepared statements (we got a DB | ||
259 | * disconnect error). | ||
260 | */ | ||
261 | static int | ||
262 | iclose (struct Plugin *plugin) | ||
263 | { | ||
264 | while (NULL != plugin->shead) | ||
265 | prepared_statement_destroy (plugin, plugin->shead); | ||
266 | if (plugin->dbf != NULL) | ||
267 | { | ||
268 | mysql_close (plugin->dbf); | ||
269 | plugin->dbf = NULL; | ||
270 | } | ||
271 | return GNUNET_OK; | ||
272 | } | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Open the connection with the database (and initialize | ||
277 | * our default options). | ||
278 | * | ||
279 | * @return GNUNET_OK on success | ||
280 | */ | ||
281 | static int | ||
282 | iopen (struct Plugin *ret) | ||
283 | { | ||
284 | char *mysql_dbname; | ||
285 | char *mysql_server; | ||
286 | char *mysql_user; | ||
287 | char *mysql_password; | ||
288 | unsigned long long mysql_port; | ||
289 | my_bool reconnect; | ||
290 | unsigned int timeout; | ||
291 | |||
292 | ret->dbf = mysql_init (NULL); | ||
293 | if (ret->dbf == NULL) | ||
294 | return GNUNET_SYSERR; | ||
295 | if (ret->cnffile != NULL) | ||
296 | mysql_options (ret->dbf, MYSQL_READ_DEFAULT_FILE, ret->cnffile); | ||
297 | mysql_options (ret->dbf, MYSQL_READ_DEFAULT_GROUP, "client"); | ||
298 | reconnect = 0; | ||
299 | mysql_options (ret->dbf, MYSQL_OPT_RECONNECT, &reconnect); | ||
300 | mysql_options (ret->dbf, MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout); | ||
301 | mysql_options (ret->dbf, MYSQL_SET_CHARSET_NAME, "UTF8"); | ||
302 | timeout = 60; /* in seconds */ | ||
303 | mysql_options (ret->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout); | ||
304 | mysql_options (ret->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout); | ||
305 | mysql_dbname = NULL; | ||
306 | if (GNUNET_YES == | ||
307 | GNUNET_CONFIGURATION_have_value (ret->env->cfg, "datacache-mysql", | ||
308 | "DATABASE")) | ||
309 | GNUNET_assert (GNUNET_OK == | ||
310 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, | ||
311 | "datacache-mysql", | ||
312 | "DATABASE", | ||
313 | &mysql_dbname)); | ||
314 | else | ||
315 | mysql_dbname = GNUNET_strdup ("gnunet"); | ||
316 | mysql_user = NULL; | ||
317 | if (GNUNET_YES == | ||
318 | GNUNET_CONFIGURATION_have_value (ret->env->cfg, "datacache-mysql", | ||
319 | "USER")) | ||
320 | { | ||
321 | GNUNET_assert (GNUNET_OK == | ||
322 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, | ||
323 | "datacache-mysql", | ||
324 | "USER", &mysql_user)); | ||
325 | } | ||
326 | mysql_password = NULL; | ||
327 | if (GNUNET_YES == | ||
328 | GNUNET_CONFIGURATION_have_value (ret->env->cfg, "datacache-mysql", | ||
329 | "PASSWORD")) | ||
330 | { | ||
331 | GNUNET_assert (GNUNET_OK == | ||
332 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, | ||
333 | "datacache-mysql", | ||
334 | "PASSWORD", | ||
335 | &mysql_password)); | ||
336 | } | ||
337 | mysql_server = NULL; | ||
338 | if (GNUNET_YES == | ||
339 | GNUNET_CONFIGURATION_have_value (ret->env->cfg, "datacache-mysql", | ||
340 | "HOST")) | ||
341 | { | ||
342 | GNUNET_assert (GNUNET_OK == | ||
343 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, | ||
344 | "datacache-mysql", | ||
345 | "HOST", | ||
346 | &mysql_server)); | ||
347 | } | ||
348 | mysql_port = 0; | ||
349 | if (GNUNET_YES == | ||
350 | GNUNET_CONFIGURATION_have_value (ret->env->cfg, "datacache-mysql", | ||
351 | "PORT")) | ||
352 | { | ||
353 | GNUNET_assert (GNUNET_OK == | ||
354 | GNUNET_CONFIGURATION_get_value_number (ret->env->cfg, | ||
355 | "datacache-mysql", | ||
356 | "PORT", &mysql_port)); | ||
357 | } | ||
358 | |||
359 | GNUNET_assert (mysql_dbname != NULL); | ||
360 | mysql_real_connect (ret->dbf, mysql_server, mysql_user, mysql_password, | ||
361 | mysql_dbname, (unsigned int) mysql_port, NULL, | ||
362 | CLIENT_IGNORE_SIGPIPE); | ||
363 | GNUNET_free_non_null (mysql_server); | ||
364 | GNUNET_free_non_null (mysql_user); | ||
365 | GNUNET_free_non_null (mysql_password); | ||
366 | GNUNET_free (mysql_dbname); | ||
367 | if (mysql_error (ret->dbf)[0]) | ||
368 | { | ||
369 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_real_connect", ret); | ||
370 | return GNUNET_SYSERR; | ||
371 | } | ||
372 | return GNUNET_OK; | ||
373 | } | ||
374 | |||
375 | |||
376 | /** | ||
377 | * Run the given MySQL statement. | ||
378 | * | ||
379 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
380 | */ | ||
381 | static int | ||
382 | run_statement (struct Plugin *plugin, const char *statement) | ||
383 | { | ||
384 | if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) | ||
385 | return GNUNET_SYSERR; | ||
386 | mysql_query (plugin->dbf, statement); | ||
387 | if (mysql_error (plugin->dbf)[0]) | ||
388 | { | ||
389 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", plugin); | ||
390 | iclose (plugin); | ||
391 | return GNUNET_SYSERR; | ||
392 | } | ||
393 | return GNUNET_OK; | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * Create a prepared statement. | ||
398 | * | ||
399 | * @return NULL on error | ||
400 | */ | ||
401 | static struct GNUNET_MysqlStatementHandle * | ||
402 | prepared_statement_create (struct Plugin *plugin, const char *statement) | ||
403 | { | ||
404 | struct GNUNET_MysqlStatementHandle *ret; | ||
405 | |||
406 | ret = GNUNET_malloc (sizeof (struct GNUNET_MysqlStatementHandle)); | ||
407 | ret->query = GNUNET_strdup (statement); | ||
408 | GNUNET_CONTAINER_DLL_insert (plugin->shead, plugin->stail, ret); | ||
409 | return ret; | ||
410 | } | ||
411 | |||
412 | |||
413 | /** | ||
414 | * Prepare a statement for running. | ||
415 | * | ||
416 | * @return GNUNET_OK on success | ||
417 | */ | ||
418 | static int | ||
419 | prepare_statement (struct Plugin *plugin, | ||
420 | struct GNUNET_MysqlStatementHandle *ret) | ||
421 | { | ||
422 | if (GNUNET_YES == ret->valid) | ||
423 | return GNUNET_OK; | ||
424 | if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) | ||
425 | return GNUNET_SYSERR; | ||
426 | ret->statement = mysql_stmt_init (plugin->dbf); | ||
427 | if (ret->statement == NULL) | ||
428 | { | ||
429 | iclose (plugin); | ||
430 | return GNUNET_SYSERR; | ||
431 | } | ||
432 | if (mysql_stmt_prepare (ret->statement, ret->query, strlen (ret->query))) | ||
433 | { | ||
434 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", plugin); | ||
435 | mysql_stmt_close (ret->statement); | ||
436 | ret->statement = NULL; | ||
437 | iclose (plugin); | ||
438 | return GNUNET_SYSERR; | ||
439 | } | ||
440 | ret->valid = GNUNET_YES; | ||
441 | return GNUNET_OK; | ||
442 | |||
443 | } | ||
444 | |||
445 | |||
446 | /** | ||
447 | * Bind the parameters for the given MySQL statement | ||
448 | * and run it. | ||
449 | * | ||
450 | * @param plugin plugin context | ||
451 | * @param s statement to bind and run | ||
452 | * @param ap arguments for the binding | ||
453 | * @return GNUNET_SYSERR on error, GNUNET_OK on success | ||
454 | */ | ||
455 | static int | ||
456 | init_params (struct Plugin *plugin, struct GNUNET_MysqlStatementHandle *s, | ||
457 | va_list ap) | ||
458 | { | ||
459 | MYSQL_BIND qbind[MAX_PARAM]; | ||
460 | unsigned int pc; | ||
461 | unsigned int off; | ||
462 | enum enum_field_types ft; | ||
463 | |||
464 | pc = mysql_stmt_param_count (s->statement); | ||
465 | if (pc > MAX_PARAM) | ||
466 | { | ||
467 | /* increase internal constant! */ | ||
468 | GNUNET_break (0); | ||
469 | return GNUNET_SYSERR; | ||
470 | } | ||
471 | memset (qbind, 0, sizeof (qbind)); | ||
472 | off = 0; | ||
473 | ft = 0; | ||
474 | while ((pc > 0) && (-1 != (int) (ft = va_arg (ap, enum enum_field_types)))) | ||
475 | { | ||
476 | qbind[off].buffer_type = ft; | ||
477 | switch (ft) | ||
478 | { | ||
479 | case MYSQL_TYPE_FLOAT: | ||
480 | qbind[off].buffer = va_arg (ap, float *); | ||
481 | |||
482 | break; | ||
483 | case MYSQL_TYPE_LONGLONG: | ||
484 | qbind[off].buffer = va_arg (ap, unsigned long long *); | ||
485 | qbind[off].is_unsigned = va_arg (ap, int); | ||
486 | |||
487 | break; | ||
488 | case MYSQL_TYPE_LONG: | ||
489 | qbind[off].buffer = va_arg (ap, unsigned int *); | ||
490 | qbind[off].is_unsigned = va_arg (ap, int); | ||
491 | |||
492 | break; | ||
493 | case MYSQL_TYPE_VAR_STRING: | ||
494 | case MYSQL_TYPE_STRING: | ||
495 | case MYSQL_TYPE_BLOB: | ||
496 | qbind[off].buffer = va_arg (ap, void *); | ||
497 | qbind[off].buffer_length = va_arg (ap, unsigned long); | ||
498 | qbind[off].length = va_arg (ap, unsigned long *); | ||
499 | |||
500 | break; | ||
501 | default: | ||
502 | /* unsupported type */ | ||
503 | GNUNET_break (0); | ||
504 | return GNUNET_SYSERR; | ||
505 | } | ||
506 | pc--; | ||
507 | off++; | ||
508 | } | ||
509 | if (!((pc == 0) && (-1 != (int) ft) && (va_arg (ap, int) == -1))) | ||
510 | { | ||
511 | GNUNET_break (0); | ||
512 | return GNUNET_SYSERR; | ||
513 | } | ||
514 | if (mysql_stmt_bind_param (s->statement, qbind)) | ||
515 | { | ||
516 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
517 | _("`%s' failed at %s:%d with error: %s\n"), | ||
518 | "mysql_stmt_bind_param", __FILE__, __LINE__, | ||
519 | mysql_stmt_error (s->statement)); | ||
520 | iclose (plugin); | ||
521 | return GNUNET_SYSERR; | ||
522 | } | ||
523 | if (mysql_stmt_execute (s->statement)) | ||
524 | { | ||
525 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
526 | _("`%s' failed at %s:%d with error: %s\n"), | ||
527 | "mysql_stmt_execute", __FILE__, __LINE__, | ||
528 | mysql_stmt_error (s->statement)); | ||
529 | iclose (plugin); | ||
530 | return GNUNET_SYSERR; | ||
531 | } | ||
532 | return GNUNET_OK; | ||
533 | } | ||
534 | |||
535 | /** | ||
536 | * Type of a callback that will be called for each | ||
537 | * data set returned from MySQL. | ||
538 | * | ||
539 | * @param cls user-defined argument | ||
540 | * @param num_values number of elements in values | ||
541 | * @param values values returned by MySQL | ||
542 | * @return GNUNET_OK to continue iterating, GNUNET_SYSERR to abort | ||
543 | */ | ||
544 | typedef int (*GNUNET_MysqlDataProcessor) (void *cls, unsigned int num_values, | ||
545 | MYSQL_BIND * values); | ||
546 | |||
547 | |||
548 | /** | ||
549 | * Run a prepared SELECT statement. | ||
550 | * | ||
551 | * @param plugin plugin context | ||
552 | * @param s handle to SELECT statment | ||
553 | * @param result_size number of elements in results array | ||
554 | * @param results pointer to already initialized MYSQL_BIND | ||
555 | * array (of sufficient size) for passing results | ||
556 | * @param processor function to call on each result | ||
557 | * @param processor_cls extra argument to processor | ||
558 | * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective | ||
559 | * values (size + buffer-reference for pointers); terminated | ||
560 | * with "-1" | ||
561 | * @return GNUNET_SYSERR on error, otherwise | ||
562 | * the number of successfully affected (or queried) rows | ||
563 | */ | ||
564 | static int | ||
565 | prepared_statement_run_select (struct Plugin *plugin, | ||
566 | struct GNUNET_MysqlStatementHandle *s, | ||
567 | unsigned int result_size, MYSQL_BIND * results, | ||
568 | GNUNET_MysqlDataProcessor processor, | ||
569 | void *processor_cls, ...) | ||
570 | { | ||
571 | va_list ap; | ||
572 | int ret; | ||
573 | unsigned int rsize; | ||
574 | int total; | ||
575 | |||
576 | if (GNUNET_OK != prepare_statement (plugin, s)) | ||
577 | { | ||
578 | GNUNET_break (0); | ||
579 | return GNUNET_SYSERR; | ||
580 | } | ||
581 | va_start (ap, processor_cls); | ||
582 | if (GNUNET_OK != init_params (plugin, s, ap)) | ||
583 | { | ||
584 | GNUNET_break (0); | ||
585 | va_end (ap); | ||
586 | return GNUNET_SYSERR; | ||
587 | } | ||
588 | va_end (ap); | ||
589 | rsize = mysql_stmt_field_count (s->statement); | ||
590 | if (rsize > result_size) | ||
591 | { | ||
592 | GNUNET_break (0); | ||
593 | return GNUNET_SYSERR; | ||
594 | } | ||
595 | if (mysql_stmt_bind_result (s->statement, results)) | ||
596 | { | ||
597 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
598 | _("`%s' failed at %s:%d with error: %s\n"), | ||
599 | "mysql_stmt_bind_result", __FILE__, __LINE__, | ||
600 | mysql_stmt_error (s->statement)); | ||
601 | iclose (plugin); | ||
602 | return GNUNET_SYSERR; | ||
603 | } | ||
604 | |||
605 | total = 0; | ||
606 | while (1) | ||
607 | { | ||
608 | ret = mysql_stmt_fetch (s->statement); | ||
609 | if (ret == MYSQL_NO_DATA) | ||
610 | break; | ||
611 | if (ret != 0) | ||
612 | { | ||
613 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
614 | _("`%s' failed at %s:%d with error: %s\n"), | ||
615 | "mysql_stmt_fetch", __FILE__, __LINE__, | ||
616 | mysql_stmt_error (s->statement)); | ||
617 | iclose (plugin); | ||
618 | return GNUNET_SYSERR; | ||
619 | } | ||
620 | if (processor != NULL) | ||
621 | if (GNUNET_OK != processor (processor_cls, rsize, results)) | ||
622 | break; | ||
623 | total++; | ||
624 | } | ||
625 | mysql_stmt_reset (s->statement); | ||
626 | return total; | ||
627 | } | ||
628 | |||
629 | |||
630 | |||
631 | /** | ||
632 | * Run a prepared statement that does NOT produce results. | ||
633 | * | ||
634 | * @param plugin plugin context | ||
635 | * @param s handle to SELECT statment | ||
636 | * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective | ||
637 | * values (size + buffer-reference for pointers); terminated | ||
638 | * with "-1" | ||
639 | * @param insert_id NULL or address where to store the row ID of whatever | ||
640 | * was inserted (only for INSERT statements!) | ||
641 | * @return GNUNET_SYSERR on error, otherwise | ||
642 | * the number of successfully affected rows | ||
643 | */ | ||
644 | static int | ||
645 | prepared_statement_run (struct Plugin *plugin, | ||
646 | struct GNUNET_MysqlStatementHandle *s, | ||
647 | unsigned long long *insert_id, ...) | ||
648 | { | ||
649 | va_list ap; | ||
650 | int affected; | ||
651 | |||
652 | if (GNUNET_OK != prepare_statement (plugin, s)) | ||
653 | return GNUNET_SYSERR; | ||
654 | va_start (ap, insert_id); | ||
655 | if (GNUNET_OK != init_params (plugin, s, ap)) | ||
656 | { | ||
657 | va_end (ap); | ||
658 | return GNUNET_SYSERR; | ||
659 | } | ||
660 | va_end (ap); | ||
661 | affected = mysql_stmt_affected_rows (s->statement); | ||
662 | if (NULL != insert_id) | ||
663 | *insert_id = (unsigned long long) mysql_stmt_insert_id (s->statement); | ||
664 | mysql_stmt_reset (s->statement); | ||
665 | return affected; | ||
666 | } | ||
667 | |||
668 | |||
669 | /** | ||
670 | * Create temporary table and prepare statements. | 147 | * Create temporary table and prepare statements. |
671 | * | 148 | * |
672 | * @param plugin plugin context | 149 | * @param plugin plugin context |
@@ -675,7 +152,7 @@ prepared_statement_run (struct Plugin *plugin, | |||
675 | static int | 152 | static int |
676 | itable (struct Plugin *plugin) | 153 | itable (struct Plugin *plugin) |
677 | { | 154 | { |
678 | #define MRUNS(a) (GNUNET_OK != run_statement (plugin, a) ) | 155 | #define MRUNS(a) (GNUNET_OK != GNUNET_MYSQL_statement_run (plugin->mc, a) ) |
679 | if (MRUNS | 156 | if (MRUNS |
680 | ("CREATE TEMPORARY TABLE gn080dstore (" | 157 | ("CREATE TEMPORARY TABLE gn080dstore (" |
681 | " type INT(11) UNSIGNED NOT NULL DEFAULT 0," | 158 | " type INT(11) UNSIGNED NOT NULL DEFAULT 0," |
@@ -689,7 +166,7 @@ itable (struct Plugin *plugin) | |||
689 | ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1")) | 166 | ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1")) |
690 | return GNUNET_SYSERR; | 167 | return GNUNET_SYSERR; |
691 | #undef MRUNS | 168 | #undef MRUNS |
692 | #define PINIT(a,b) (NULL == (a = prepared_statement_create(plugin, b))) | 169 | #define PINIT(a,b) (NULL == (a = GNUNET_MYSQL_statement_prepare (plugin->mc, b))) |
693 | if (PINIT (plugin->select_value, SELECT_VALUE_STMT) || | 170 | if (PINIT (plugin->select_value, SELECT_VALUE_STMT) || |
694 | PINIT (plugin->count_value, COUNT_VALUE_STMT) || | 171 | PINIT (plugin->count_value, COUNT_VALUE_STMT) || |
695 | PINIT (plugin->select_old_value, SELECT_OLD_VALUE_STMT) || | 172 | PINIT (plugin->select_old_value, SELECT_OLD_VALUE_STMT) || |
@@ -742,7 +219,7 @@ mysql_plugin_put (void *cls, const GNUNET_HashCode * key, size_t size, | |||
742 | v_now = (unsigned long long) now.abs_value; | 219 | v_now = (unsigned long long) now.abs_value; |
743 | v_discard_time = (unsigned long long) discard_time.abs_value; | 220 | v_discard_time = (unsigned long long) discard_time.abs_value; |
744 | if (GNUNET_OK == | 221 | if (GNUNET_OK == |
745 | prepared_statement_run (plugin, plugin->update_value, NULL, | 222 | GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->update_value, NULL, |
746 | MYSQL_TYPE_LONGLONG, &v_now, GNUNET_YES, | 223 | MYSQL_TYPE_LONGLONG, &v_now, GNUNET_YES, |
747 | MYSQL_TYPE_LONGLONG, &v_discard_time, GNUNET_YES, | 224 | MYSQL_TYPE_LONGLONG, &v_discard_time, GNUNET_YES, |
748 | MYSQL_TYPE_BLOB, key, sizeof (GNUNET_HashCode), | 225 | MYSQL_TYPE_BLOB, key, sizeof (GNUNET_HashCode), |
@@ -757,7 +234,7 @@ mysql_plugin_put (void *cls, const GNUNET_HashCode * key, size_t size, | |||
757 | v_length = size; | 234 | v_length = size; |
758 | if (GNUNET_OK != | 235 | if (GNUNET_OK != |
759 | (ret = | 236 | (ret = |
760 | prepared_statement_run (plugin, plugin->insert_value, NULL, | 237 | GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->insert_value, NULL, |
761 | MYSQL_TYPE_LONG, &type, GNUNET_YES, | 238 | MYSQL_TYPE_LONG, &type, GNUNET_YES, |
762 | MYSQL_TYPE_LONGLONG, &v_now, GNUNET_YES, | 239 | MYSQL_TYPE_LONGLONG, &v_now, GNUNET_YES, |
763 | MYSQL_TYPE_LONGLONG, &v_discard_time, GNUNET_YES, | 240 | MYSQL_TYPE_LONGLONG, &v_discard_time, GNUNET_YES, |
@@ -825,7 +302,7 @@ mysql_plugin_get (void *cls, const GNUNET_HashCode * key, | |||
825 | v_now = (unsigned long long) now.abs_value; | 302 | v_now = (unsigned long long) now.abs_value; |
826 | if ((GNUNET_OK != | 303 | if ((GNUNET_OK != |
827 | (ret = | 304 | (ret = |
828 | prepared_statement_run_select (plugin, plugin->count_value, 1, rbind, | 305 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->count_value, 1, rbind, |
829 | return_ok, NULL, MYSQL_TYPE_BLOB, key, | 306 | return_ok, NULL, MYSQL_TYPE_BLOB, key, |
830 | sizeof (GNUNET_HashCode), &h_length, | 307 | sizeof (GNUNET_HashCode), &h_length, |
831 | MYSQL_TYPE_LONG, &v_type, GNUNET_YES, | 308 | MYSQL_TYPE_LONG, &v_type, GNUNET_YES, |
@@ -854,7 +331,7 @@ mysql_plugin_get (void *cls, const GNUNET_HashCode * key, | |||
854 | off = (off + 1) % total; | 331 | off = (off + 1) % total; |
855 | if (GNUNET_OK != | 332 | if (GNUNET_OK != |
856 | (ret = | 333 | (ret = |
857 | prepared_statement_run_select (plugin, plugin->select_value, 2, rbind, | 334 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->select_value, 2, rbind, |
858 | return_ok, NULL, MYSQL_TYPE_BLOB, key, | 335 | return_ok, NULL, MYSQL_TYPE_BLOB, key, |
859 | sizeof (GNUNET_HashCode), &h_length, | 336 | sizeof (GNUNET_HashCode), &h_length, |
860 | MYSQL_TYPE_LONG, &v_type, GNUNET_YES, | 337 | MYSQL_TYPE_LONG, &v_type, GNUNET_YES, |
@@ -917,11 +394,11 @@ mysql_plugin_del (void *cls) | |||
917 | rbind[3].buffer = buffer; | 394 | rbind[3].buffer = buffer; |
918 | if ((GNUNET_OK != | 395 | if ((GNUNET_OK != |
919 | (ret = | 396 | (ret = |
920 | prepared_statement_run_select (plugin, plugin->select_old_value, 4, | 397 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->select_old_value, 4, |
921 | rbind, return_ok, NULL, -1))) || | 398 | rbind, return_ok, NULL, -1))) || |
922 | (GNUNET_OK != | 399 | (GNUNET_OK != |
923 | (ret = | 400 | (ret = |
924 | prepared_statement_run (plugin, plugin->delete_value, NULL, | 401 | GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->delete_value, NULL, |
925 | MYSQL_TYPE_BLOB, &v_key, | 402 | MYSQL_TYPE_BLOB, &v_key, |
926 | sizeof (GNUNET_HashCode), &k_length, | 403 | sizeof (GNUNET_HashCode), &k_length, |
927 | MYSQL_TYPE_BLOB, &vhash, | 404 | MYSQL_TYPE_BLOB, &vhash, |
@@ -956,17 +433,12 @@ libgnunet_plugin_datacache_mysql_init (void *cls) | |||
956 | 433 | ||
957 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | 434 | plugin = GNUNET_malloc (sizeof (struct Plugin)); |
958 | plugin->env = env; | 435 | plugin->env = env; |
959 | plugin->cnffile = get_my_cnf_path (env->cfg); | 436 | plugin->mc = GNUNET_MYSQL_context_create (env->cfg, "datacache-mysql"); |
960 | if (GNUNET_OK != iopen (plugin)) | 437 | if ( (NULL == plugin->mc) || |
961 | { | 438 | (GNUNET_OK != itable (plugin)) ) |
962 | GNUNET_free_non_null (plugin->cnffile); | ||
963 | GNUNET_free (plugin); | ||
964 | return NULL; | ||
965 | } | ||
966 | if (GNUNET_OK != itable (plugin)) | ||
967 | { | 439 | { |
968 | iclose (plugin); | 440 | if (NULL != plugin->mc) |
969 | GNUNET_free_non_null (plugin->cnffile); | 441 | GNUNET_MYSQL_context_destroy (plugin->mc); |
970 | GNUNET_free (plugin); | 442 | GNUNET_free (plugin); |
971 | return NULL; | 443 | return NULL; |
972 | } | 444 | } |
@@ -993,8 +465,7 @@ libgnunet_plugin_datacache_mysql_done (void *cls) | |||
993 | struct GNUNET_DATACACHE_PluginFunctions *api = cls; | 465 | struct GNUNET_DATACACHE_PluginFunctions *api = cls; |
994 | struct Plugin *plugin = api->cls; | 466 | struct Plugin *plugin = api->cls; |
995 | 467 | ||
996 | iclose (plugin); | 468 | GNUNET_MYSQL_context_destroy (plugin->mc); |
997 | GNUNET_free_non_null (plugin->cnffile); | ||
998 | GNUNET_free (plugin); | 469 | GNUNET_free (plugin); |
999 | GNUNET_free (api); | 470 | GNUNET_free (api); |
1000 | mysql_library_end (); | 471 | mysql_library_end (); |