From b56cfa1127b0f4f376ad73c8ecd5622600b1da1c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 3 Jun 2017 21:42:38 +0200 Subject: migrate another function to libgnunetpq --- src/datacache/plugin_datacache_postgres.c | 196 +++++++++++++++++------------- 1 file 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 @@ /* This file is part of GNUnet - Copyright (C) 2006, 2009, 2010, 2012, 2015 GNUnet e.V. + Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -478,6 +478,97 @@ postgres_plugin_get_random (void *cls, } +/** + * Closure for #extract_result_cb. + */ +struct ExtractResultContext +{ + /** + * Function to call for each result found. + */ + GNUNET_DATACACHE_Iterator iter; + + /** + * Closure for @e iter. + */ + void *iter_cls; + +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Calls the `iter` + * from @a cls for each result. + * + * @param cls closure with the `struct ExtractResultContext` + * @param result the postgres result + * @param num_result the number of results in @a result + */ +static void +extract_result_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ExtractResultContext *erc = cls; + + if (NULL == erc->iter) + return; + for (unsigned int i=0;iiter (erc->iter_cls, + &key, + data_size, + data, + (enum GNUNET_BLOCK_Type) type, + expiration_time, + path_len, + path)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Ending iteration (client error)\n"); + GNUNET_PQ_cleanup_result (rs); + break; + } + GNUNET_PQ_cleanup_result (rs); + } +} + + /** * Iterate over the results that are "close" to a particular key in * the datacache. "close" is defined as numerically larger than @a @@ -499,105 +590,36 @@ postgres_plugin_get_closest (void *cls, void *iter_cls) { struct Plugin *plugin = cls; - uint32_t nbo_limit = htonl (num_results); - const char *paramValues[] = { - (const char *) key, - (const char *) &nbo_limit, + uint32_t num_results32 = (uint32_t) num_results; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (key), + GNUNET_PQ_query_param_uint32 (&num_results32), + GNUNET_PQ_query_param_end }; - int paramLengths[] = { - sizeof (struct GNUNET_HashCode), - sizeof (nbo_limit) + enum GNUNET_PQ_QueryStatus res; + struct ExtractResultContext erc; - }; - const int paramFormats[] = { 1, 1 }; - struct GNUNET_TIME_Absolute expiration_time; - uint32_t size; - unsigned int type; - unsigned int cnt; - unsigned int i; - unsigned int path_len; - const struct GNUNET_PeerIdentity *path; - PGresult *res; - - res = - PQexecPrepared (plugin->dbh, - "get_closest", - 2, - paramValues, - paramLengths, - paramFormats, - 1); - if (GNUNET_OK != - GNUNET_POSTGRES_check_result (plugin->dbh, - res, - PGRES_TUPLES_OK, - "PQexecPrepared", - "get_closest")) + erc.iter = iter; + erc.iter_cls = iter_cls; + res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, + "get_closest", + params, + &extract_result_cb, + &erc); + if (0 > res) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (postgres error)\n"); return 0; } - - if (0 == (cnt = PQntuples (res))) + if (GNUNET_PQ_STATUS_SUCCESS_NO_RESULTS == res) { /* no result */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (no more results)\n"); - PQclear (res); return 0; } - if (NULL == iter) - { - PQclear (res); - return cnt; - } - if ( (5 != PQnfields (res)) || - (sizeof (uint64_t) != PQfsize (res, 0)) || - (sizeof (uint32_t) != PQfsize (res, 1)) || - (sizeof (struct GNUNET_HashCode) != PQfsize (res, 4)) ) - { - GNUNET_break (0); - PQclear (res); - return 0; - } - for (i = 0; i < cnt; i++) - { - expiration_time.abs_value_us = - GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0)); - type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1)); - size = PQgetlength (res, i, 2); - path_len = PQgetlength (res, i, 3); - if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) - { - GNUNET_break (0); - path_len = 0; - } - path_len %= sizeof (struct GNUNET_PeerIdentity); - path = (const struct GNUNET_PeerIdentity *) PQgetvalue (res, i, 3); - key = (const struct GNUNET_HashCode *) PQgetvalue (res, i, 4); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Found result of size %u bytes and type %u in database\n", - (unsigned int) size, - (unsigned int) type); - if (GNUNET_SYSERR == - iter (iter_cls, - key, - size, - PQgetvalue (res, i, 2), - (enum GNUNET_BLOCK_Type) type, - expiration_time, - path_len, - path)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Ending iteration (client error)\n"); - PQclear (res); - return cnt; - } - } - PQclear (res); - return cnt; + return res; } -- cgit v1.2.3