aboutsummaryrefslogtreecommitdiff
path: root/src/datacache
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-06-03 21:42:38 +0200
committerChristian Grothoff <christian@grothoff.org>2017-06-03 21:42:38 +0200
commitb56cfa1127b0f4f376ad73c8ecd5622600b1da1c (patch)
treefa33633d6def8bb6a09a273ae881afda73af7efe /src/datacache
parenta2ce8dba133e644e304bb41e4205435bebd6145c (diff)
downloadgnunet-b56cfa1127b0f4f376ad73c8ecd5622600b1da1c.tar.gz
gnunet-b56cfa1127b0f4f376ad73c8ecd5622600b1da1c.zip
migrate another function to libgnunetpq
Diffstat (limited to 'src/datacache')
-rw-r--r--src/datacache/plugin_datacache_postgres.c196
1 files changed, 109 insertions, 87 deletions
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c
index c5bbb390c..ce469a9ed 100644
--- a/src/datacache/plugin_datacache_postgres.c
+++ b/src/datacache/plugin_datacache_postgres.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2006, 2009, 2010, 2012, 2015 GNUnet e.V. 3 Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -479,6 +479,97 @@ postgres_plugin_get_random (void *cls,
479 479
480 480
481/** 481/**
482 * Closure for #extract_result_cb.
483 */
484struct ExtractResultContext
485{
486 /**
487 * Function to call for each result found.
488 */
489 GNUNET_DATACACHE_Iterator iter;
490
491 /**
492 * Closure for @e iter.
493 */
494 void *iter_cls;
495
496};
497
498
499/**
500 * Function to be called with the results of a SELECT statement
501 * that has returned @a num_results results. Calls the `iter`
502 * from @a cls for each result.
503 *
504 * @param cls closure with the `struct ExtractResultContext`
505 * @param result the postgres result
506 * @param num_result the number of results in @a result
507 */
508static void
509extract_result_cb (void *cls,
510 PGresult *result,
511 unsigned int num_results)
512{
513 struct ExtractResultContext *erc = cls;
514
515 if (NULL == erc->iter)
516 return;
517 for (unsigned int i=0;i<num_results;i++)
518 {
519 struct GNUNET_TIME_Absolute expiration_time;
520 uint32_t type;
521 void *data;
522 size_t data_size;
523 struct GNUNET_PeerIdentity *path;
524 size_t path_len;
525 struct GNUNET_HashCode key;
526 struct GNUNET_PQ_ResultSpec rs[] = {
527 GNUNET_PQ_result_spec_absolute_time ("",
528 &expiration_time),
529 GNUNET_PQ_result_spec_uint32 ("type",
530 &type),
531 GNUNET_PQ_result_spec_variable_size ("value",
532 &data,
533 &data_size),
534 GNUNET_PQ_result_spec_variable_size ("path",
535 (void **) &path,
536 &path_len),
537 GNUNET_PQ_result_spec_auto_from_type ("key",
538 &key),
539 GNUNET_PQ_result_spec_end
540 };
541
542 if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity)))
543 {
544 GNUNET_break (0);
545 path_len = 0;
546 }
547 path_len %= sizeof (struct GNUNET_PeerIdentity);
548 LOG (GNUNET_ERROR_TYPE_DEBUG,
549 "Found result of size %u bytes and type %u in database\n",
550 (unsigned int) data_size,
551 (unsigned int) type);
552 if (GNUNET_SYSERR ==
553 erc->iter (erc->iter_cls,
554 &key,
555 data_size,
556 data,
557 (enum GNUNET_BLOCK_Type) type,
558 expiration_time,
559 path_len,
560 path))
561 {
562 LOG (GNUNET_ERROR_TYPE_DEBUG,
563 "Ending iteration (client error)\n");
564 GNUNET_PQ_cleanup_result (rs);
565 break;
566 }
567 GNUNET_PQ_cleanup_result (rs);
568 }
569}
570
571
572/**
482 * Iterate over the results that are "close" to a particular key in 573 * Iterate over the results that are "close" to a particular key in
483 * the datacache. "close" is defined as numerically larger than @a 574 * the datacache. "close" is defined as numerically larger than @a
484 * key (when interpreted as a circular address space), with small 575 * key (when interpreted as a circular address space), with small
@@ -499,105 +590,36 @@ postgres_plugin_get_closest (void *cls,
499 void *iter_cls) 590 void *iter_cls)
500{ 591{
501 struct Plugin *plugin = cls; 592 struct Plugin *plugin = cls;
502 uint32_t nbo_limit = htonl (num_results); 593 uint32_t num_results32 = (uint32_t) num_results;
503 const char *paramValues[] = { 594 struct GNUNET_PQ_QueryParam params[] = {
504 (const char *) key, 595 GNUNET_PQ_query_param_auto_from_type (key),
505 (const char *) &nbo_limit, 596 GNUNET_PQ_query_param_uint32 (&num_results32),
597 GNUNET_PQ_query_param_end
506 }; 598 };
507 int paramLengths[] = { 599 enum GNUNET_PQ_QueryStatus res;
508 sizeof (struct GNUNET_HashCode), 600 struct ExtractResultContext erc;
509 sizeof (nbo_limit)
510 601
511 }; 602 erc.iter = iter;
512 const int paramFormats[] = { 1, 1 }; 603 erc.iter_cls = iter_cls;
513 struct GNUNET_TIME_Absolute expiration_time; 604 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
514 uint32_t size; 605 "get_closest",
515 unsigned int type; 606 params,
516 unsigned int cnt; 607 &extract_result_cb,
517 unsigned int i; 608 &erc);
518 unsigned int path_len; 609 if (0 > res)
519 const struct GNUNET_PeerIdentity *path;
520 PGresult *res;
521
522 res =
523 PQexecPrepared (plugin->dbh,
524 "get_closest",
525 2,
526 paramValues,
527 paramLengths,
528 paramFormats,
529 1);
530 if (GNUNET_OK !=
531 GNUNET_POSTGRES_check_result (plugin->dbh,
532 res,
533 PGRES_TUPLES_OK,
534 "PQexecPrepared",
535 "get_closest"))
536 { 610 {
537 LOG (GNUNET_ERROR_TYPE_DEBUG, 611 LOG (GNUNET_ERROR_TYPE_DEBUG,
538 "Ending iteration (postgres error)\n"); 612 "Ending iteration (postgres error)\n");
539 return 0; 613 return 0;
540 } 614 }
541 615 if (GNUNET_PQ_STATUS_SUCCESS_NO_RESULTS == res)
542 if (0 == (cnt = PQntuples (res)))
543 { 616 {
544 /* no result */ 617 /* no result */
545 LOG (GNUNET_ERROR_TYPE_DEBUG, 618 LOG (GNUNET_ERROR_TYPE_DEBUG,
546 "Ending iteration (no more results)\n"); 619 "Ending iteration (no more results)\n");
547 PQclear (res);
548 return 0; 620 return 0;
549 } 621 }
550 if (NULL == iter) 622 return res;
551 {
552 PQclear (res);
553 return cnt;
554 }
555 if ( (5 != PQnfields (res)) ||
556 (sizeof (uint64_t) != PQfsize (res, 0)) ||
557 (sizeof (uint32_t) != PQfsize (res, 1)) ||
558 (sizeof (struct GNUNET_HashCode) != PQfsize (res, 4)) )
559 {
560 GNUNET_break (0);
561 PQclear (res);
562 return 0;
563 }
564 for (i = 0; i < cnt; i++)
565 {
566 expiration_time.abs_value_us =
567 GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0));
568 type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1));
569 size = PQgetlength (res, i, 2);
570 path_len = PQgetlength (res, i, 3);
571 if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity)))
572 {
573 GNUNET_break (0);
574 path_len = 0;
575 }
576 path_len %= sizeof (struct GNUNET_PeerIdentity);
577 path = (const struct GNUNET_PeerIdentity *) PQgetvalue (res, i, 3);
578 key = (const struct GNUNET_HashCode *) PQgetvalue (res, i, 4);
579 LOG (GNUNET_ERROR_TYPE_DEBUG,
580 "Found result of size %u bytes and type %u in database\n",
581 (unsigned int) size,
582 (unsigned int) type);
583 if (GNUNET_SYSERR ==
584 iter (iter_cls,
585 key,
586 size,
587 PQgetvalue (res, i, 2),
588 (enum GNUNET_BLOCK_Type) type,
589 expiration_time,
590 path_len,
591 path))
592 {
593 LOG (GNUNET_ERROR_TYPE_DEBUG,
594 "Ending iteration (client error)\n");
595 PQclear (res);
596 return cnt;
597 }
598 }
599 PQclear (res);
600 return cnt;
601} 623}
602 624
603 625