aboutsummaryrefslogtreecommitdiff
path: root/src/datacache/plugin_datacache_mysql.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/datacache/plugin_datacache_mysql.c')
-rw-r--r--src/datacache/plugin_datacache_mysql.c769
1 files changed, 374 insertions, 395 deletions
diff --git a/src/datacache/plugin_datacache_mysql.c b/src/datacache/plugin_datacache_mysql.c
index 8e477409e..f4530ccef 100644
--- a/src/datacache/plugin_datacache_mysql.c
+++ b/src/datacache/plugin_datacache_mysql.c
@@ -127,7 +127,7 @@ struct GNUNET_MysqlStatementHandle
127/** 127/**
128 * Context for all functions in this plugin. 128 * Context for all functions in this plugin.
129 */ 129 */
130struct Plugin 130struct Plugin
131{ 131{
132 /** 132 /**
133 * Our execution environment. 133 * Our execution environment.
@@ -183,6 +183,7 @@ get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg)
183 char *cnffile; 183 char *cnffile;
184 char *home_dir; 184 char *home_dir;
185 struct stat st; 185 struct stat st;
186
186#ifndef WINDOWS 187#ifndef WINDOWS
187 struct passwd *pw; 188 struct passwd *pw;
188#endif 189#endif
@@ -191,44 +192,46 @@ get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg)
191#ifndef WINDOWS 192#ifndef WINDOWS
192 pw = getpwuid (getuid ()); 193 pw = getpwuid (getuid ());
193 if (!pw) 194 if (!pw)
194 { 195 {
195 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, 196 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "getpwuid");
196 "getpwuid"); 197 return NULL;
197 return NULL; 198 }
198 }
199 if (GNUNET_YES == 199 if (GNUNET_YES ==
200 GNUNET_CONFIGURATION_have_value (cfg, 200 GNUNET_CONFIGURATION_have_value (cfg, "datacache-mysql", "CONFIG"))
201 "datacache-mysql", "CONFIG")) 201 {
202 { 202 GNUNET_assert (GNUNET_OK ==
203 GNUNET_assert (GNUNET_OK == 203 GNUNET_CONFIGURATION_get_value_filename (cfg,
204 GNUNET_CONFIGURATION_get_value_filename (cfg, 204 "datacache-mysql",
205 "datacache-mysql", "CONFIG", &cnffile)); 205 "CONFIG",
206 configured = GNUNET_YES; 206 &cnffile));
207 } 207 configured = GNUNET_YES;
208 }
208 else 209 else
209 { 210 {
210 home_dir = GNUNET_strdup (pw->pw_dir); 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 }
211#else 216#else
212 home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); 217 home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1);
213 plibc_conv_to_win_path ("~/", home_dir); 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;
214#endif 222#endif
215 GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir);
216 GNUNET_free (home_dir);
217 configured = GNUNET_NO;
218 }
219 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 223 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
220 _("Trying to use file `%s' for MySQL configuration.\n"), 224 _("Trying to use file `%s' for MySQL configuration.\n"), cnffile);
221 cnffile);
222 if ((0 != STAT (cnffile, &st)) || 225 if ((0 != STAT (cnffile, &st)) ||
223 (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode))) 226 (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode)))
224 { 227 {
225 if (configured == GNUNET_YES) 228 if (configured == GNUNET_YES)
226 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
227 _("Could not access file `%s': %s\n"), cnffile, 230 _("Could not access file `%s': %s\n"), cnffile,
228 STRERROR (errno)); 231 STRERROR (errno));
229 GNUNET_free (cnffile); 232 GNUNET_free (cnffile);
230 return NULL; 233 return NULL;
231 } 234 }
232 return cnffile; 235 return cnffile;
233} 236}
234 237
@@ -240,13 +243,10 @@ get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg)
240 * @param s prepared statement 243 * @param s prepared statement
241 */ 244 */
242static void 245static void
243prepared_statement_destroy (struct Plugin *plugin, 246prepared_statement_destroy (struct Plugin *plugin,
244 struct GNUNET_MysqlStatementHandle 247 struct GNUNET_MysqlStatementHandle *s)
245 *s)
246{ 248{
247 GNUNET_CONTAINER_DLL_remove (plugin->shead, 249 GNUNET_CONTAINER_DLL_remove (plugin->shead, plugin->stail, s);
248 plugin->stail,
249 s);
250 if (s->valid) 250 if (s->valid)
251 mysql_stmt_close (s->statement); 251 mysql_stmt_close (s->statement);
252 GNUNET_free (s->query); 252 GNUNET_free (s->query);
@@ -262,13 +262,12 @@ static int
262iclose (struct Plugin *plugin) 262iclose (struct Plugin *plugin)
263{ 263{
264 while (NULL != plugin->shead) 264 while (NULL != plugin->shead)
265 prepared_statement_destroy (plugin, 265 prepared_statement_destroy (plugin, plugin->shead);
266 plugin->shead);
267 if (plugin->dbf != NULL) 266 if (plugin->dbf != NULL)
268 { 267 {
269 mysql_close (plugin->dbf); 268 mysql_close (plugin->dbf);
270 plugin->dbf = NULL; 269 plugin->dbf = NULL;
271 } 270 }
272 return GNUNET_OK; 271 return GNUNET_OK;
273} 272}
274 273
@@ -298,71 +297,75 @@ iopen (struct Plugin *ret)
298 mysql_options (ret->dbf, MYSQL_READ_DEFAULT_GROUP, "client"); 297 mysql_options (ret->dbf, MYSQL_READ_DEFAULT_GROUP, "client");
299 reconnect = 0; 298 reconnect = 0;
300 mysql_options (ret->dbf, MYSQL_OPT_RECONNECT, &reconnect); 299 mysql_options (ret->dbf, MYSQL_OPT_RECONNECT, &reconnect);
301 mysql_options (ret->dbf, 300 mysql_options (ret->dbf, MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout);
302 MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout); 301 mysql_options (ret->dbf, MYSQL_SET_CHARSET_NAME, "UTF8");
303 mysql_options(ret->dbf, MYSQL_SET_CHARSET_NAME, "UTF8"); 302 timeout = 60; /* in seconds */
304 timeout = 60; /* in seconds */
305 mysql_options (ret->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout); 303 mysql_options (ret->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout);
306 mysql_options (ret->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout); 304 mysql_options (ret->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout);
307 mysql_dbname = NULL; 305 mysql_dbname = NULL;
308 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, 306 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
309 "datacache-mysql", "DATABASE")) 307 "datacache-mysql",
310 GNUNET_assert (GNUNET_OK == 308 "DATABASE"))
311 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, 309 GNUNET_assert (GNUNET_OK ==
312 "datacache-mysql", "DATABASE", 310 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
313 &mysql_dbname)); 311 "datacache-mysql",
312 "DATABASE",
313 &mysql_dbname));
314 else 314 else
315 mysql_dbname = GNUNET_strdup ("gnunet"); 315 mysql_dbname = GNUNET_strdup ("gnunet");
316 mysql_user = NULL; 316 mysql_user = NULL;
317 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, 317 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
318 "datacache-mysql", "USER")) 318 "datacache-mysql", "USER"))
319 { 319 {
320 GNUNET_assert (GNUNET_OK == 320 GNUNET_assert (GNUNET_OK ==
321 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, 321 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
322 "datacache-mysql", "USER", 322 "datacache-mysql",
323 &mysql_user)); 323 "USER", &mysql_user));
324 } 324 }
325 mysql_password = NULL; 325 mysql_password = NULL;
326 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, 326 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
327 "datacache-mysql", "PASSWORD")) 327 "datacache-mysql",
328 { 328 "PASSWORD"))
329 GNUNET_assert (GNUNET_OK == 329 {
330 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, 330 GNUNET_assert (GNUNET_OK ==
331 "datacache-mysql", "PASSWORD", 331 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
332 &mysql_password)); 332 "datacache-mysql",
333 } 333 "PASSWORD",
334 &mysql_password));
335 }
334 mysql_server = NULL; 336 mysql_server = NULL;
335 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, 337 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
336 "datacache-mysql", "HOST")) 338 "datacache-mysql", "HOST"))
337 { 339 {
338 GNUNET_assert (GNUNET_OK == 340 GNUNET_assert (GNUNET_OK ==
339 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, 341 GNUNET_CONFIGURATION_get_value_string (ret->env->cfg,
340 "datacache-mysql", "HOST", 342 "datacache-mysql",
341 &mysql_server)); 343 "HOST",
342 } 344 &mysql_server));
345 }
343 mysql_port = 0; 346 mysql_port = 0;
344 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, 347 if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg,
345 "datacache-mysql", "PORT")) 348 "datacache-mysql", "PORT"))
346 { 349 {
347 GNUNET_assert (GNUNET_OK == 350 GNUNET_assert (GNUNET_OK ==
348 GNUNET_CONFIGURATION_get_value_number (ret->env->cfg, "datacache-mysql", 351 GNUNET_CONFIGURATION_get_value_number (ret->env->cfg,
349 "PORT", &mysql_port)); 352 "datacache-mysql",
350 } 353 "PORT", &mysql_port));
354 }
351 355
352 GNUNET_assert (mysql_dbname != NULL); 356 GNUNET_assert (mysql_dbname != NULL);
353 mysql_real_connect (ret->dbf, mysql_server, mysql_user, mysql_password, 357 mysql_real_connect (ret->dbf, mysql_server, mysql_user, mysql_password,
354 mysql_dbname, (unsigned int) mysql_port, NULL, 358 mysql_dbname, (unsigned int) mysql_port, NULL,
355 CLIENT_IGNORE_SIGPIPE); 359 CLIENT_IGNORE_SIGPIPE);
356 GNUNET_free_non_null (mysql_server); 360 GNUNET_free_non_null (mysql_server);
357 GNUNET_free_non_null (mysql_user); 361 GNUNET_free_non_null (mysql_user);
358 GNUNET_free_non_null (mysql_password); 362 GNUNET_free_non_null (mysql_password);
359 GNUNET_free (mysql_dbname); 363 GNUNET_free (mysql_dbname);
360 if (mysql_error (ret->dbf)[0]) 364 if (mysql_error (ret->dbf)[0])
361 { 365 {
362 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, 366 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_real_connect", ret);
363 "mysql_real_connect", ret); 367 return GNUNET_SYSERR;
364 return GNUNET_SYSERR; 368 }
365 }
366 return GNUNET_OK; 369 return GNUNET_OK;
367} 370}
368 371
@@ -373,19 +376,17 @@ iopen (struct Plugin *ret)
373 * @return GNUNET_OK on success, GNUNET_SYSERR on error 376 * @return GNUNET_OK on success, GNUNET_SYSERR on error
374 */ 377 */
375static int 378static int
376run_statement (struct Plugin *plugin, 379run_statement (struct Plugin *plugin, const char *statement)
377 const char *statement)
378{ 380{
379 if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) 381 if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin)))
380 return GNUNET_SYSERR; 382 return GNUNET_SYSERR;
381 mysql_query (plugin->dbf, statement); 383 mysql_query (plugin->dbf, statement);
382 if (mysql_error (plugin->dbf)[0]) 384 if (mysql_error (plugin->dbf)[0])
383 { 385 {
384 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, 386 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", plugin);
385 "mysql_query", plugin); 387 iclose (plugin);
386 iclose (plugin); 388 return GNUNET_SYSERR;
387 return GNUNET_SYSERR; 389 }
388 }
389 return GNUNET_OK; 390 return GNUNET_OK;
390} 391}
391 392
@@ -395,16 +396,13 @@ run_statement (struct Plugin *plugin,
395 * @return NULL on error 396 * @return NULL on error
396 */ 397 */
397static struct GNUNET_MysqlStatementHandle * 398static struct GNUNET_MysqlStatementHandle *
398prepared_statement_create (struct Plugin *plugin, 399prepared_statement_create (struct Plugin *plugin, const char *statement)
399 const char *statement)
400{ 400{
401 struct GNUNET_MysqlStatementHandle *ret; 401 struct GNUNET_MysqlStatementHandle *ret;
402 402
403 ret = GNUNET_malloc (sizeof (struct GNUNET_MysqlStatementHandle)); 403 ret = GNUNET_malloc (sizeof (struct GNUNET_MysqlStatementHandle));
404 ret->query = GNUNET_strdup (statement); 404 ret->query = GNUNET_strdup (statement);
405 GNUNET_CONTAINER_DLL_insert (plugin->shead, 405 GNUNET_CONTAINER_DLL_insert (plugin->shead, plugin->stail, ret);
406 plugin->stail,
407 ret);
408 return ret; 406 return ret;
409} 407}
410 408
@@ -415,32 +413,27 @@ prepared_statement_create (struct Plugin *plugin,
415 * @return GNUNET_OK on success 413 * @return GNUNET_OK on success
416 */ 414 */
417static int 415static int
418prepare_statement (struct Plugin *plugin, 416prepare_statement (struct Plugin *plugin,
419 struct GNUNET_MysqlStatementHandle *ret) 417 struct GNUNET_MysqlStatementHandle *ret)
420{ 418{
421 if (GNUNET_YES == ret->valid) 419 if (GNUNET_YES == ret->valid)
422 return GNUNET_OK; 420 return GNUNET_OK;
423 if ((NULL == plugin->dbf) && 421 if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin)))
424 (GNUNET_OK != iopen (plugin)))
425 return GNUNET_SYSERR; 422 return GNUNET_SYSERR;
426 ret->statement = mysql_stmt_init (plugin->dbf); 423 ret->statement = mysql_stmt_init (plugin->dbf);
427 if (ret->statement == NULL) 424 if (ret->statement == NULL)
428 { 425 {
429 iclose (plugin); 426 iclose (plugin);
430 return GNUNET_SYSERR; 427 return GNUNET_SYSERR;
431 } 428 }
432 if (mysql_stmt_prepare (ret->statement, 429 if (mysql_stmt_prepare (ret->statement, ret->query, strlen (ret->query)))
433 ret->query, 430 {
434 strlen (ret->query))) 431 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", plugin);
435 { 432 mysql_stmt_close (ret->statement);
436 LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, 433 ret->statement = NULL;
437 "mysql_stmt_prepare", 434 iclose (plugin);
438 plugin); 435 return GNUNET_SYSERR;
439 mysql_stmt_close (ret->statement); 436 }
440 ret->statement = NULL;
441 iclose (plugin);
442 return GNUNET_SYSERR;
443 }
444 ret->valid = GNUNET_YES; 437 ret->valid = GNUNET_YES;
445 return GNUNET_OK; 438 return GNUNET_OK;
446 439
@@ -458,8 +451,7 @@ prepare_statement (struct Plugin *plugin,
458 */ 451 */
459static int 452static int
460init_params (struct Plugin *plugin, 453init_params (struct Plugin *plugin,
461 struct GNUNET_MysqlStatementHandle *s, 454 struct GNUNET_MysqlStatementHandle *s, va_list ap)
462 va_list ap)
463{ 455{
464 MYSQL_BIND qbind[MAX_PARAM]; 456 MYSQL_BIND qbind[MAX_PARAM];
465 unsigned int pc; 457 unsigned int pc;
@@ -468,68 +460,72 @@ init_params (struct Plugin *plugin,
468 460
469 pc = mysql_stmt_param_count (s->statement); 461 pc = mysql_stmt_param_count (s->statement);
470 if (pc > MAX_PARAM) 462 if (pc > MAX_PARAM)
471 { 463 {
472 /* increase internal constant! */ 464 /* increase internal constant! */
473 GNUNET_break (0); 465 GNUNET_break (0);
474 return GNUNET_SYSERR; 466 return GNUNET_SYSERR;
475 } 467 }
476 memset (qbind, 0, sizeof (qbind)); 468 memset (qbind, 0, sizeof (qbind));
477 off = 0; 469 off = 0;
478 ft = 0; 470 ft = 0;
479 while ( (pc > 0) && (-1 != (int) (ft = va_arg (ap, enum enum_field_types))) ) 471 while ((pc > 0) && (-1 != (int) (ft = va_arg (ap, enum enum_field_types))))
480 { 472 {
481 qbind[off].buffer_type = ft; 473 qbind[off].buffer_type = ft;
482 switch (ft) 474 switch (ft)
483 {
484 case MYSQL_TYPE_FLOAT:
485 qbind[off].buffer = va_arg (ap, float *);
486 break;
487 case MYSQL_TYPE_LONGLONG:
488 qbind[off].buffer = va_arg (ap, unsigned long long *);
489 qbind[off].is_unsigned = va_arg (ap, int);
490 break;
491 case MYSQL_TYPE_LONG:
492 qbind[off].buffer = va_arg (ap, unsigned int *);
493 qbind[off].is_unsigned = va_arg (ap, int);
494 break;
495 case MYSQL_TYPE_VAR_STRING:
496 case MYSQL_TYPE_STRING:
497 case MYSQL_TYPE_BLOB:
498 qbind[off].buffer = va_arg (ap, void *);
499 qbind[off].buffer_length = va_arg (ap, unsigned long);
500 qbind[off].length = va_arg (ap, unsigned long *);
501 break;
502 default:
503 /* unsupported type */
504 GNUNET_break (0);
505 return GNUNET_SYSERR;
506 }
507 pc--;
508 off++;
509 }
510 if (! ( (pc == 0) && (-1 != (int) ft) && (va_arg (ap, int) == -1)) )
511 { 475 {
476 case MYSQL_TYPE_FLOAT:
477 qbind[off].buffer = va_arg (ap, float *);
478
479 break;
480 case MYSQL_TYPE_LONGLONG:
481 qbind[off].buffer = va_arg (ap, unsigned long long *);
482 qbind[off].is_unsigned = va_arg (ap, int);
483
484 break;
485 case MYSQL_TYPE_LONG:
486 qbind[off].buffer = va_arg (ap, unsigned int *);
487 qbind[off].is_unsigned = va_arg (ap, int);
488
489 break;
490 case MYSQL_TYPE_VAR_STRING:
491 case MYSQL_TYPE_STRING:
492 case MYSQL_TYPE_BLOB:
493 qbind[off].buffer = va_arg (ap, void *);
494 qbind[off].buffer_length = va_arg (ap, unsigned long);
495 qbind[off].length = va_arg (ap, unsigned long *);
496
497 break;
498 default:
499 /* unsupported type */
512 GNUNET_break (0); 500 GNUNET_break (0);
513 return GNUNET_SYSERR; 501 return GNUNET_SYSERR;
514 } 502 }
503 pc--;
504 off++;
505 }
506 if (!((pc == 0) && (-1 != (int) ft) && (va_arg (ap, int) == -1)))
507 {
508 GNUNET_break (0);
509 return GNUNET_SYSERR;
510 }
515 if (mysql_stmt_bind_param (s->statement, qbind)) 511 if (mysql_stmt_bind_param (s->statement, qbind))
516 { 512 {
517 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 513 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
518 _("`%s' failed at %s:%d with error: %s\n"), 514 _("`%s' failed at %s:%d with error: %s\n"),
519 "mysql_stmt_bind_param", 515 "mysql_stmt_bind_param",
520 __FILE__, __LINE__, mysql_stmt_error (s->statement)); 516 __FILE__, __LINE__, mysql_stmt_error (s->statement));
521 iclose (plugin); 517 iclose (plugin);
522 return GNUNET_SYSERR; 518 return GNUNET_SYSERR;
523 } 519 }
524 if (mysql_stmt_execute (s->statement)) 520 if (mysql_stmt_execute (s->statement))
525 { 521 {
526 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 522 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
527 _("`%s' failed at %s:%d with error: %s\n"), 523 _("`%s' failed at %s:%d with error: %s\n"),
528 "mysql_stmt_execute", 524 "mysql_stmt_execute",
529 __FILE__, __LINE__, mysql_stmt_error (s->statement)); 525 __FILE__, __LINE__, mysql_stmt_error (s->statement));
530 iclose (plugin); 526 iclose (plugin);
531 return GNUNET_SYSERR; 527 return GNUNET_SYSERR;
532 } 528 }
533 return GNUNET_OK; 529 return GNUNET_OK;
534} 530}
535 531
@@ -565,13 +561,12 @@ typedef int (*GNUNET_MysqlDataProcessor) (void *cls,
565 */ 561 */
566static int 562static int
567prepared_statement_run_select (struct Plugin *plugin, 563prepared_statement_run_select (struct Plugin *plugin,
568 struct GNUNET_MysqlStatementHandle 564 struct GNUNET_MysqlStatementHandle
569 *s, 565 *s,
570 unsigned int result_size, 566 unsigned int result_size,
571 MYSQL_BIND * results, 567 MYSQL_BIND * results,
572 GNUNET_MysqlDataProcessor 568 GNUNET_MysqlDataProcessor
573 processor, void *processor_cls, 569 processor, void *processor_cls, ...)
574 ...)
575{ 570{
576 va_list ap; 571 va_list ap;
577 int ret; 572 int ret;
@@ -579,54 +574,54 @@ prepared_statement_run_select (struct Plugin *plugin,
579 int total; 574 int total;
580 575
581 if (GNUNET_OK != prepare_statement (plugin, s)) 576 if (GNUNET_OK != prepare_statement (plugin, s))
582 { 577 {
583 GNUNET_break (0); 578 GNUNET_break (0);
584 return GNUNET_SYSERR; 579 return GNUNET_SYSERR;
585 } 580 }
586 va_start (ap, processor_cls); 581 va_start (ap, processor_cls);
587 if (GNUNET_OK != init_params (plugin, s, ap)) 582 if (GNUNET_OK != init_params (plugin, s, ap))
588 { 583 {
589 GNUNET_break (0); 584 GNUNET_break (0);
590 va_end (ap); 585 va_end (ap);
591 return GNUNET_SYSERR; 586 return GNUNET_SYSERR;
592 } 587 }
593 va_end (ap); 588 va_end (ap);
594 rsize = mysql_stmt_field_count (s->statement); 589 rsize = mysql_stmt_field_count (s->statement);
595 if (rsize > result_size) 590 if (rsize > result_size)
596 { 591 {
597 GNUNET_break (0); 592 GNUNET_break (0);
598 return GNUNET_SYSERR; 593 return GNUNET_SYSERR;
599 } 594 }
600 if (mysql_stmt_bind_result (s->statement, results)) 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",
600 __FILE__, __LINE__, 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)
601 { 612 {
602 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 613 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603 _("`%s' failed at %s:%d with error: %s\n"), 614 _("`%s' failed at %s:%d with error: %s\n"),
604 "mysql_stmt_bind_result", 615 "mysql_stmt_fetch",
605 __FILE__, __LINE__, mysql_stmt_error (s->statement)); 616 __FILE__, __LINE__, mysql_stmt_error (s->statement));
606 iclose (plugin); 617 iclose (plugin);
607 return GNUNET_SYSERR; 618 return GNUNET_SYSERR;
608 } 619 }
609 620 if (processor != NULL)
610 total = 0; 621 if (GNUNET_OK != processor (processor_cls, rsize, results))
611 while (1)
612 {
613 ret = mysql_stmt_fetch (s->statement);
614 if (ret == MYSQL_NO_DATA)
615 break; 622 break;
616 if (ret != 0) 623 total++;
617 { 624 }
618 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619 _("`%s' failed at %s:%d with error: %s\n"),
620 "mysql_stmt_fetch",
621 __FILE__, __LINE__, mysql_stmt_error (s->statement));
622 iclose (plugin);
623 return GNUNET_SYSERR;
624 }
625 if (processor != NULL)
626 if (GNUNET_OK != processor (processor_cls, rsize, results))
627 break;
628 total++;
629 }
630 mysql_stmt_reset (s->statement); 625 mysql_stmt_reset (s->statement);
631 return total; 626 return total;
632} 627}
@@ -648,8 +643,8 @@ prepared_statement_run_select (struct Plugin *plugin,
648 */ 643 */
649static int 644static int
650prepared_statement_run (struct Plugin *plugin, 645prepared_statement_run (struct Plugin *plugin,
651 struct GNUNET_MysqlStatementHandle *s, 646 struct GNUNET_MysqlStatementHandle *s,
652 unsigned long long *insert_id, ...) 647 unsigned long long *insert_id, ...)
653{ 648{
654 va_list ap; 649 va_list ap;
655 int affected; 650 int affected;
@@ -658,10 +653,10 @@ prepared_statement_run (struct Plugin *plugin,
658 return GNUNET_SYSERR; 653 return GNUNET_SYSERR;
659 va_start (ap, insert_id); 654 va_start (ap, insert_id);
660 if (GNUNET_OK != init_params (plugin, s, ap)) 655 if (GNUNET_OK != init_params (plugin, s, ap))
661 { 656 {
662 va_end (ap); 657 va_end (ap);
663 return GNUNET_SYSERR; 658 return GNUNET_SYSERR;
664 } 659 }
665 va_end (ap); 660 va_end (ap);
666 affected = mysql_stmt_affected_rows (s->statement); 661 affected = mysql_stmt_affected_rows (s->statement);
667 if (NULL != insert_id) 662 if (NULL != insert_id)
@@ -718,13 +713,13 @@ itable (struct Plugin *plugin)
718 * @param discard_time when to discard the value in any case 713 * @param discard_time when to discard the value in any case
719 * @return 0 on error, number of bytes used otherwise 714 * @return 0 on error, number of bytes used otherwise
720 */ 715 */
721static size_t 716static size_t
722mysql_plugin_put (void *cls, 717mysql_plugin_put (void *cls,
723 const GNUNET_HashCode * key, 718 const GNUNET_HashCode * key,
724 size_t size, 719 size_t size,
725 const char *data, 720 const char *data,
726 enum GNUNET_BLOCK_Type type, 721 enum GNUNET_BLOCK_Type type,
727 struct GNUNET_TIME_Absolute discard_time) 722 struct GNUNET_TIME_Absolute discard_time)
728{ 723{
729 struct Plugin *plugin = cls; 724 struct Plugin *plugin = cls;
730 struct GNUNET_TIME_Absolute now; 725 struct GNUNET_TIME_Absolute now;
@@ -751,25 +746,23 @@ mysql_plugin_put (void *cls,
751 v_discard_time = (unsigned long long) discard_time.abs_value; 746 v_discard_time = (unsigned long long) discard_time.abs_value;
752 if (GNUNET_OK == 747 if (GNUNET_OK ==
753 prepared_statement_run (plugin, 748 prepared_statement_run (plugin,
754 plugin->update_value, 749 plugin->update_value,
755 NULL, 750 NULL,
756 MYSQL_TYPE_LONGLONG, 751 MYSQL_TYPE_LONGLONG,
757 &v_now, 752 &v_now,
758 GNUNET_YES, 753 GNUNET_YES,
759 MYSQL_TYPE_LONGLONG, 754 MYSQL_TYPE_LONGLONG,
760 &v_discard_time, 755 &v_discard_time,
761 GNUNET_YES, 756 GNUNET_YES,
762 MYSQL_TYPE_BLOB, 757 MYSQL_TYPE_BLOB,
763 key, 758 key,
764 sizeof (GNUNET_HashCode), 759 sizeof (GNUNET_HashCode),
765 &k_length, 760 &k_length,
766 MYSQL_TYPE_BLOB, 761 MYSQL_TYPE_BLOB,
767 &vhash, 762 &vhash,
768 sizeof (GNUNET_HashCode), 763 sizeof (GNUNET_HashCode),
769 &h_length, 764 &h_length,
770 MYSQL_TYPE_LONG, 765 MYSQL_TYPE_LONG, &v_type, GNUNET_YES, -1))
771 &v_type,
772 GNUNET_YES, -1))
773 return GNUNET_OK; 766 return GNUNET_OK;
774 767
775 /* now try INSERT */ 768 /* now try INSERT */
@@ -778,34 +771,33 @@ mysql_plugin_put (void *cls,
778 v_length = size; 771 v_length = size;
779 if (GNUNET_OK != 772 if (GNUNET_OK !=
780 (ret = prepared_statement_run (plugin, 773 (ret = prepared_statement_run (plugin,
781 plugin->insert_value, 774 plugin->insert_value,
782 NULL, 775 NULL,
783 MYSQL_TYPE_LONG, 776 MYSQL_TYPE_LONG,
784 &type, 777 &type,
785 GNUNET_YES, 778 GNUNET_YES,
786 MYSQL_TYPE_LONGLONG, 779 MYSQL_TYPE_LONGLONG,
787 &v_now, 780 &v_now,
788 GNUNET_YES, 781 GNUNET_YES,
789 MYSQL_TYPE_LONGLONG, 782 MYSQL_TYPE_LONGLONG,
790 &v_discard_time, 783 &v_discard_time,
791 GNUNET_YES, 784 GNUNET_YES,
792 MYSQL_TYPE_BLOB, 785 MYSQL_TYPE_BLOB,
793 key, 786 key,
794 sizeof (GNUNET_HashCode), 787 sizeof (GNUNET_HashCode),
795 &k_length, 788 &k_length,
796 MYSQL_TYPE_BLOB, 789 MYSQL_TYPE_BLOB,
797 &vhash, 790 &vhash,
798 sizeof (GNUNET_HashCode), 791 sizeof (GNUNET_HashCode),
799 &h_length, 792 &h_length,
800 MYSQL_TYPE_BLOB, 793 MYSQL_TYPE_BLOB,
801 data, 794 data,
802 (unsigned long) size, 795 (unsigned long) size, &v_length, -1)))
803 &v_length, -1))) 796 {
804 { 797 if (ret == GNUNET_SYSERR)
805 if (ret == GNUNET_SYSERR) 798 itable (plugin);
806 itable (plugin); 799 return GNUNET_SYSERR;
807 return GNUNET_SYSERR; 800 }
808 }
809 return size + OVERHEAD; 801 return size + OVERHEAD;
810} 802}
811 803
@@ -828,12 +820,11 @@ return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values)
828 * @param iter_cls closure for iter 820 * @param iter_cls closure for iter
829 * @return the number of results found 821 * @return the number of results found
830 */ 822 */
831static unsigned int 823static unsigned int
832mysql_plugin_get (void *cls, 824mysql_plugin_get (void *cls,
833 const GNUNET_HashCode * key, 825 const GNUNET_HashCode * key,
834 enum GNUNET_BLOCK_Type type, 826 enum GNUNET_BLOCK_Type type,
835 GNUNET_DATACACHE_Iterator iter, 827 GNUNET_DATACACHE_Iterator iter, void *iter_cls)
836 void *iter_cls)
837{ 828{
838 struct Plugin *plugin = cls; 829 struct Plugin *plugin = cls;
839 MYSQL_BIND rbind[3]; 830 MYSQL_BIND rbind[3];
@@ -862,79 +853,72 @@ mysql_plugin_get (void *cls,
862 v_now = (unsigned long long) now.abs_value; 853 v_now = (unsigned long long) now.abs_value;
863 if ((GNUNET_OK != 854 if ((GNUNET_OK !=
864 (ret = prepared_statement_run_select (plugin, 855 (ret = prepared_statement_run_select (plugin,
865 plugin->count_value, 856 plugin->count_value,
866 1, 857 1,
867 rbind, 858 rbind,
868 return_ok, 859 return_ok,
869 NULL, 860 NULL,
870 MYSQL_TYPE_BLOB, 861 MYSQL_TYPE_BLOB,
871 key, 862 key,
872 sizeof 863 sizeof
873 (GNUNET_HashCode), 864 (GNUNET_HashCode),
874 &h_length, 865 &h_length,
875 MYSQL_TYPE_LONG, 866 MYSQL_TYPE_LONG,
876 &v_type, GNUNET_YES, 867 &v_type, GNUNET_YES,
877 MYSQL_TYPE_LONGLONG, 868 MYSQL_TYPE_LONGLONG,
878 &v_now, GNUNET_YES, 869 &v_now, GNUNET_YES,
879 -1))) 870 -1))) || (-1 == total))
880 || (-1 == total)) 871 {
881 { 872 if (ret == GNUNET_SYSERR)
882 if (ret == GNUNET_SYSERR) 873 itable (plugin);
883 itable (plugin); 874 return GNUNET_SYSERR;
884 return GNUNET_SYSERR; 875 }
885 }
886 if ((iter == NULL) || (total == 0)) 876 if ((iter == NULL) || (total == 0))
887 return (int) total; 877 return (int) total;
888 878
889 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); 879 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
890 cnt = 0; 880 cnt = 0;
891 while (cnt < total) 881 while (cnt < total)
882 {
883 memset (rbind, 0, sizeof (rbind));
884 rbind[0].buffer_type = MYSQL_TYPE_BLOB;
885 rbind[0].buffer_length = sizeof (buffer);
886 rbind[0].length = &v_length;
887 rbind[0].buffer = buffer;
888 rbind[1].buffer_type = MYSQL_TYPE_LONGLONG;
889 rbind[1].is_unsigned = 1;
890 rbind[1].buffer = &v_expire;
891 off = (off + 1) % total;
892 if (GNUNET_OK !=
893 (ret = prepared_statement_run_select (plugin,
894 plugin->select_value,
895 2,
896 rbind,
897 return_ok,
898 NULL,
899 MYSQL_TYPE_BLOB,
900 key,
901 sizeof
902 (GNUNET_HashCode),
903 &h_length,
904 MYSQL_TYPE_LONG,
905 &v_type,
906 GNUNET_YES,
907 MYSQL_TYPE_LONGLONG,
908 &v_now,
909 GNUNET_YES,
910 MYSQL_TYPE_LONG,
911 &off, GNUNET_YES, -1)))
892 { 912 {
893 memset (rbind, 0, sizeof (rbind)); 913 if (ret == GNUNET_SYSERR)
894 rbind[0].buffer_type = MYSQL_TYPE_BLOB; 914 itable (plugin);
895 rbind[0].buffer_length = sizeof (buffer); 915 return GNUNET_SYSERR;
896 rbind[0].length = &v_length;
897 rbind[0].buffer = buffer;
898 rbind[1].buffer_type = MYSQL_TYPE_LONGLONG;
899 rbind[1].is_unsigned = 1;
900 rbind[1].buffer = &v_expire;
901 off = (off + 1) % total;
902 if (GNUNET_OK !=
903 (ret = prepared_statement_run_select (plugin,
904 plugin->select_value,
905 2,
906 rbind,
907 return_ok,
908 NULL,
909 MYSQL_TYPE_BLOB,
910 key,
911 sizeof
912 (GNUNET_HashCode),
913 &h_length,
914 MYSQL_TYPE_LONG,
915 &v_type,
916 GNUNET_YES,
917 MYSQL_TYPE_LONGLONG,
918 &v_now,
919 GNUNET_YES,
920 MYSQL_TYPE_LONG,
921 &off,
922 GNUNET_YES,
923 -1)))
924 {
925 if (ret == GNUNET_SYSERR)
926 itable (plugin);
927 return GNUNET_SYSERR;
928 }
929 cnt++;
930 expire.abs_value = v_expire;
931 if (GNUNET_OK != iter (iter_cls,
932 expire,
933 key,
934 v_length, buffer,
935 type))
936 break;
937 } 916 }
917 cnt++;
918 expire.abs_value = v_expire;
919 if (GNUNET_OK != iter (iter_cls, expire, key, v_length, buffer, type))
920 break;
921 }
938 return cnt; 922 return cnt;
939} 923}
940 924
@@ -945,8 +929,8 @@ mysql_plugin_get (void *cls,
945 * 929 *
946 * @param cls closure (our "struct Plugin") 930 * @param cls closure (our "struct Plugin")
947 * @return GNUNET_OK on success, GNUNET_SYSERR on error 931 * @return GNUNET_OK on success, GNUNET_SYSERR on error
948 */ 932 */
949static int 933static int
950mysql_plugin_del (void *cls) 934mysql_plugin_del (void *cls)
951{ 935{
952 struct Plugin *plugin = cls; 936 struct Plugin *plugin = cls;
@@ -982,40 +966,37 @@ mysql_plugin_del (void *cls)
982 rbind[3].buffer = buffer; 966 rbind[3].buffer = buffer;
983 if ((GNUNET_OK != 967 if ((GNUNET_OK !=
984 (ret = prepared_statement_run_select (plugin, 968 (ret = prepared_statement_run_select (plugin,
985 plugin->select_old_value, 969 plugin->select_old_value,
986 4, 970 4,
987 rbind, 971 rbind,
988 return_ok, 972 return_ok,
989 NULL, 973 NULL,
990 -1))) || 974 -1))) ||
991 (GNUNET_OK != 975 (GNUNET_OK !=
992 (ret = prepared_statement_run (plugin, 976 (ret = prepared_statement_run (plugin,
993 plugin->delete_value, 977 plugin->delete_value,
994 NULL, 978 NULL,
995 MYSQL_TYPE_BLOB, 979 MYSQL_TYPE_BLOB,
996 &v_key, 980 &v_key,
997 sizeof (GNUNET_HashCode), 981 sizeof (GNUNET_HashCode),
998 &k_length, 982 &k_length,
999 MYSQL_TYPE_BLOB, 983 MYSQL_TYPE_BLOB,
1000 &vhash, 984 &vhash,
1001 sizeof (GNUNET_HashCode), 985 sizeof (GNUNET_HashCode),
1002 &h_length, 986 &h_length,
1003 MYSQL_TYPE_LONG, 987 MYSQL_TYPE_LONG,
1004 &v_type, 988 &v_type,
1005 GNUNET_YES, 989 GNUNET_YES,
1006 MYSQL_TYPE_BLOB, 990 MYSQL_TYPE_BLOB,
1007 buffer, 991 buffer,
1008 (unsigned long) 992 (unsigned long)
1009 sizeof (buffer), 993 sizeof (buffer), &v_length, -1))))
1010 &v_length, -1)))) 994 {
1011 { 995 if (ret == GNUNET_SYSERR)
1012 if (ret == GNUNET_SYSERR) 996 itable (plugin);
1013 itable (plugin); 997 return GNUNET_SYSERR;
1014 return GNUNET_SYSERR; 998 }
1015 } 999 plugin->env->delete_notify (plugin->env->cls, &v_key, v_length + OVERHEAD);
1016 plugin->env->delete_notify (plugin->env->cls,
1017 &v_key,
1018 v_length + OVERHEAD);
1019 1000
1020 return GNUNET_OK; 1001 return GNUNET_OK;
1021} 1002}
@@ -1037,21 +1018,19 @@ libgnunet_plugin_datacache_mysql_init (void *cls)
1037 plugin = GNUNET_malloc (sizeof (struct Plugin)); 1018 plugin = GNUNET_malloc (sizeof (struct Plugin));
1038 plugin->env = env; 1019 plugin->env = env;
1039 plugin->cnffile = get_my_cnf_path (env->cfg); 1020 plugin->cnffile = get_my_cnf_path (env->cfg);
1040 if (GNUNET_OK != 1021 if (GNUNET_OK != iopen (plugin))
1041 iopen (plugin)) 1022 {
1042 { 1023 GNUNET_free_non_null (plugin->cnffile);
1043 GNUNET_free_non_null (plugin->cnffile); 1024 GNUNET_free (plugin);
1044 GNUNET_free (plugin); 1025 return NULL;
1045 return NULL; 1026 }
1046 } 1027 if (GNUNET_OK != itable (plugin))
1047 if (GNUNET_OK != 1028 {
1048 itable (plugin)) 1029 iclose (plugin);
1049 { 1030 GNUNET_free_non_null (plugin->cnffile);
1050 iclose (plugin); 1031 GNUNET_free (plugin);
1051 GNUNET_free_non_null (plugin->cnffile); 1032 return NULL;
1052 GNUNET_free (plugin); 1033 }
1053 return NULL;
1054 }
1055 api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions)); 1034 api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions));
1056 api->cls = plugin; 1035 api->cls = plugin;
1057 api->get = &mysql_plugin_get; 1036 api->get = &mysql_plugin_get;