aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_postgres.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/plugin_namestore_postgres.c')
-rw-r--r--src/namestore/plugin_namestore_postgres.c566
1 files changed, 261 insertions, 305 deletions
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
index 01dbf9e61..491cec1cb 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_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) 2009-2013, 2016 GNUnet e.V. 3 * Copyright (C) 2009-2013, 2016, 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
@@ -27,31 +27,10 @@
27#include "gnunet_namestore_plugin.h" 27#include "gnunet_namestore_plugin.h"
28#include "gnunet_namestore_service.h" 28#include "gnunet_namestore_service.h"
29#include "gnunet_gnsrecord_lib.h" 29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_postgres_lib.h"
31#include "gnunet_pq_lib.h" 30#include "gnunet_pq_lib.h"
32#include "namestore.h" 31#include "namestore.h"
33 32
34 33
35/**
36 * After how many ms "busy" should a DB operation fail for good?
37 * A low value makes sure that we are more responsive to requests
38 * (especially PUTs). A high value guarantees a higher success
39 * rate (SELECTs in iterate can take several seconds despite LIMIT=1).
40 *
41 * The default value of 1s should ensure that users do not experience
42 * huge latencies while at the same time allowing operations to succeed
43 * with reasonable probability.
44 */
45#define BUSY_TIMEOUT_MS 1000
46
47
48/**
49 * Log an error message at log-level 'level' that indicates
50 * a failure of the command 'cmd' on file 'filename'
51 * with the message given by strerror(errno).
52 */
53#define LOG_POSTGRES(db, level, cmd) do { GNUNET_log_from (level, "namestore-postgres", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
54
55#define LOG(kind,...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__) 34#define LOG(kind,...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__)
56 35
57 36
@@ -75,30 +54,6 @@ struct Plugin
75 54
76 55
77/** 56/**
78 * Create our database indices.
79 *
80 * @param dbh handle to the database
81 */
82static void
83create_indices (PGconn * dbh)
84{
85 /* create indices */
86 if ( (GNUNET_OK !=
87 GNUNET_POSTGRES_exec (dbh,
88 "CREATE INDEX IF NOT EXISTS ir_pkey_reverse ON ns097records (zone_private_key,pkey)")) ||
89 (GNUNET_OK !=
90 GNUNET_POSTGRES_exec (dbh,
91 "CREATE INDEX IF NOT EXISTS ir_pkey_iter ON ns097records (zone_private_key,rvalue)")) ||
92 (GNUNET_OK !=
93 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX IF NOT EXISTS it_iter ON ns097records (rvalue)")) ||
94 (GNUNET_OK !=
95 GNUNET_POSTGRES_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_label ON ns097records (label)")) )
96 LOG (GNUNET_ERROR_TYPE_ERROR,
97 _("Failed to create indices\n"));
98}
99
100
101/**
102 * Initialize the database connections and associated 57 * Initialize the database connections and associated
103 * data structures (create tables and indices 58 * data structures (create tables and indices
104 * as needed as well). 59 * as needed as well).
@@ -109,10 +64,30 @@ create_indices (PGconn * dbh)
109static int 64static int
110database_setup (struct Plugin *plugin) 65database_setup (struct Plugin *plugin)
111{ 66{
112 PGresult *res; 67 struct GNUNET_PQ_ExecuteStatement es_temporary =
113 68 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns097records ("
114 plugin->dbh = GNUNET_POSTGRES_connect (plugin->cfg, 69 " zone_private_key BYTEA NOT NULL DEFAULT '',"
115 "namestore-postgres"); 70 " pkey BYTEA DEFAULT '',"
71 " rvalue BYTEA NOT NULL DEFAULT '',"
72 " record_count INTEGER NOT NULL DEFAULT 0,"
73 " record_data BYTEA NOT NULL DEFAULT '',"
74 " label TEXT NOT NULL DEFAULT ''"
75 ")"
76 "WITH OIDS");
77 struct GNUNET_PQ_ExecuteStatement es_default =
78 GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns097records ("
79 " zone_private_key BYTEA NOT NULL DEFAULT '',"
80 " pkey BYTEA DEFAULT '',"
81 " rvalue BYTEA NOT NULL DEFAULT '',"
82 " record_count INTEGER NOT NULL DEFAULT 0,"
83 " record_data BYTEA NOT NULL DEFAULT '',"
84 " label TEXT NOT NULL DEFAULT ''"
85 ")"
86 "WITH OIDS");
87 const struct GNUNET_PQ_ExecuteStatement *cr;
88
89 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
90 "namestore-postgres");
116 if (NULL == plugin->dbh) 91 if (NULL == plugin->dbh)
117 return GNUNET_SYSERR; 92 return GNUNET_SYSERR;
118 if (GNUNET_YES == 93 if (GNUNET_YES ==
@@ -120,80 +95,70 @@ database_setup (struct Plugin *plugin)
120 "namestore-postgres", 95 "namestore-postgres",
121 "TEMPORARY_TABLE")) 96 "TEMPORARY_TABLE"))
122 { 97 {
123 res = 98 cr = &es_temporary;
124 PQexec (plugin->dbh,
125 "CREATE TEMPORARY TABLE IF NOT EXISTS ns097records ("
126 " zone_private_key BYTEA NOT NULL DEFAULT '',"
127 " pkey BYTEA DEFAULT '',"
128 " rvalue BYTEA NOT NULL DEFAULT '',"
129 " record_count INTEGER NOT NULL DEFAULT 0,"
130 " record_data BYTEA NOT NULL DEFAULT '',"
131 " label TEXT NOT NULL DEFAULT ''"
132 ")" "WITH OIDS");
133 } 99 }
134 else 100 else
135 { 101 {
136 res = 102 cr = &es_default;
137 PQexec (plugin->dbh,
138 "CREATE TABLE IF NOT EXISTS ns097records ("
139 " zone_private_key BYTEA NOT NULL DEFAULT '',"
140 " pkey BYTEA DEFAULT '',"
141 " rvalue BYTEA NOT NULL DEFAULT '',"
142 " record_count INTEGER NOT NULL DEFAULT 0,"
143 " record_data BYTEA NOT NULL DEFAULT '',"
144 " label TEXT NOT NULL DEFAULT ''"
145 ")" "WITH OIDS");
146 } 103 }
147 if ( (NULL == res) || 104
148 ((PQresultStatus (res) != PGRES_COMMAND_OK) &&
149 (0 != strcmp ("42P07", /* duplicate table */
150 PQresultErrorField
151 (res,
152 PG_DIAG_SQLSTATE)))))
153 { 105 {
154 (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, 106 struct GNUNET_PQ_ExecuteStatement es[] = {
155 PGRES_COMMAND_OK, "CREATE TABLE", 107 *cr,
156 "ns097records"); 108 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
157 PQfinish (plugin->dbh); 109 "ON ns097records (zone_private_key,pkey)"),
158 plugin->dbh = NULL; 110 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
159 return GNUNET_SYSERR; 111 "ON ns097records (zone_private_key,rvalue)"),
112 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS it_iter "
113 "ON ns097records (rvalue)"),
114 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label "
115 "ON ns097records (label)"),
116 GNUNET_PQ_EXECUTE_STATEMENT_END
117 };
118
119 if (GNUNET_OK !=
120 GNUNET_PQ_exec_statements (plugin->dbh,
121 es))
122 {
123 PQfinish (plugin->dbh);
124 plugin->dbh = NULL;
125 return GNUNET_SYSERR;
126 }
160 } 127 }
161 create_indices (plugin->dbh); 128
162
163 if ((GNUNET_OK !=
164 GNUNET_POSTGRES_prepare (plugin->dbh,
165 "store_records",
166 "INSERT INTO ns097records (zone_private_key, pkey, rvalue, record_count, record_data, label) VALUES "
167 "($1, $2, $3, $4, $5, $6)", 6)) ||
168 (GNUNET_OK !=
169 GNUNET_POSTGRES_prepare (plugin->dbh,
170 "delete_records",
171 "DELETE FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2)) ||
172 (GNUNET_OK !=
173 GNUNET_POSTGRES_prepare (plugin->dbh,
174 "zone_to_name",
175 "SELECT record_count,record_data,label FROM ns097records"
176 " WHERE zone_private_key=$1 AND pkey=$2", 2)) ||
177 (GNUNET_OK !=
178 GNUNET_POSTGRES_prepare (plugin->dbh,
179 "iterate_zone",
180 "SELECT record_count,record_data,label FROM ns097records"
181 " WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) ||
182 (GNUNET_OK !=
183 GNUNET_POSTGRES_prepare (plugin->dbh,
184 "iterate_all_zones",
185 "SELECT record_count,record_data,label,zone_private_key"
186 " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1)) ||
187 (GNUNET_OK !=
188 GNUNET_POSTGRES_prepare (plugin->dbh,
189 "lookup_label",
190 "SELECT record_count,record_data,label"
191 " FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2)))
192 { 129 {
193 PQfinish (plugin->dbh); 130 struct GNUNET_PQ_PreparedStatement ps[] = {
194 plugin->dbh = NULL; 131 GNUNET_PQ_make_prepare ("store_records",
195 return GNUNET_SYSERR; 132 "INSERT INTO ns097records (zone_private_key, pkey, rvalue, record_count, record_data, label) VALUES "
133 "($1, $2, $3, $4, $5, $6)", 6),
134 GNUNET_PQ_make_prepare ("delete_records",
135 "DELETE FROM ns097records "
136 "WHERE zone_private_key=$1 AND label=$2", 2),
137 GNUNET_PQ_make_prepare ("zone_to_name",
138 "SELECT record_count,record_data,label FROM ns097records"
139 " WHERE zone_private_key=$1 AND pkey=$2", 2),
140 GNUNET_PQ_make_prepare ("iterate_zone",
141 "SELECT record_count,record_data,label FROM ns097records "
142 "WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2),
143 GNUNET_PQ_make_prepare ("iterate_all_zones",
144 "SELECT record_count,record_data,label,zone_private_key"
145 " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1),
146 GNUNET_PQ_make_prepare ("lookup_label",
147 "SELECT record_count,record_data,label "
148 "FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2),
149 GNUNET_PQ_PREPARED_STATEMENT_END
150 };
151
152 if (GNUNET_OK !=
153 GNUNET_PQ_prepare_statements (plugin->dbh,
154 ps))
155 {
156 PQfinish (plugin->dbh);
157 plugin->dbh = NULL;
158 return GNUNET_SYSERR;
159 }
196 } 160 }
161
197 return GNUNET_OK; 162 return GNUNET_OK;
198} 163}
199 164
@@ -219,21 +184,21 @@ namestore_postgres_store_records (void *cls,
219 struct Plugin *plugin = cls; 184 struct Plugin *plugin = cls;
220 struct GNUNET_CRYPTO_EcdsaPublicKey pkey; 185 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
221 uint64_t rvalue; 186 uint64_t rvalue;
222 uint32_t rd_count_nbo = htonl ((uint32_t) rd_count); 187 uint32_t rd_count32 = (uint32_t) rd_count;
223 size_t data_size; 188 size_t data_size;
224 unsigned int i;
225 189
226 memset (&pkey, 0, sizeof (pkey)); 190 memset (&pkey, 0, sizeof (pkey));
227 for (i=0;i<rd_count;i++) 191 for (unsigned int i=0;i<rd_count;i++)
228 if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type) 192 if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type)
229 { 193 {
230 GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size); 194 GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size);
231 GNUNET_memcpy (&pkey, 195 GNUNET_memcpy (&pkey,
232 rd[i].data, 196 rd[i].data,
233 rd[i].data_size); 197 rd[i].data_size);
234 break; 198 break;
235 } 199 }
236 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); 200 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
201 UINT64_MAX);
237 data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd); 202 data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
238 if (data_size > 64 * 65536) 203 if (data_size > 64 * 65536)
239 { 204 {
@@ -242,141 +207,134 @@ namestore_postgres_store_records (void *cls,
242 } 207 }
243 { 208 {
244 char data[data_size]; 209 char data[data_size];
245 // FIXME: use libgnunetpq! 210 struct GNUNET_PQ_QueryParam params[] = {
246 const char *paramValues[] = { 211 GNUNET_PQ_query_param_auto_from_type (zone_key),
247 (const char *) zone_key, 212 GNUNET_PQ_query_param_auto_from_type (&pkey),
248 (const char *) &pkey, 213 GNUNET_PQ_query_param_uint64 (&rvalue),
249 (const char *) &rvalue, 214 GNUNET_PQ_query_param_uint32 (&rd_count32),
250 (const char *) &rd_count_nbo, 215 GNUNET_PQ_query_param_fixed_size (data, data_size),
251 (const char *) data, 216 GNUNET_PQ_query_param_string (label),
252 label 217 GNUNET_PQ_query_param_end
253 };
254 int paramLengths[] = {
255 sizeof (*zone_key),
256 sizeof (pkey),
257 sizeof (rvalue),
258 sizeof (rd_count_nbo),
259 data_size,
260 strlen (label)
261 }; 218 };
262 const int paramFormats[] = { 1, 1, 1, 1, 1, 1 }; 219 enum GNUNET_DB_QueryStatus res;
263 PGresult *res;
264 220
265 if (data_size != GNUNET_GNSRECORD_records_serialize (rd_count, rd, 221 if (data_size !=
266 data_size, data)) 222 GNUNET_GNSRECORD_records_serialize (rd_count, rd,
223 data_size, data))
267 { 224 {
268 GNUNET_break (0); 225 GNUNET_break (0);
269 return GNUNET_SYSERR; 226 return GNUNET_SYSERR;
270 } 227 }
271 228
272 res = 229 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
273 PQexecPrepared (plugin->dbh, "store_records", 6, 230 "store_records",
274 paramValues, paramLengths, paramFormats, 1); 231 params);
275 if (GNUNET_OK != 232 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res)
276 GNUNET_POSTGRES_check_result (plugin->dbh,
277 res,
278 PGRES_COMMAND_OK,
279 "PQexecPrepared",
280 "store_records"))
281 return GNUNET_SYSERR; 233 return GNUNET_SYSERR;
282 PQclear (res);
283 return GNUNET_OK;
284 } 234 }
235 return GNUNET_OK;
285} 236}
286 237
287 238
288/** 239/**
240 * Closure for #parse_result_call_iterator.
241 */
242struct ParserContext
243{
244 /**
245 * Function to call for each result.
246 */
247 GNUNET_NAMESTORE_RecordIterator iter;
248
249 /**
250 * Closure for @e iter.
251 */
252 void *iter_cls;
253
254 /**
255 * Zone key, NULL if part of record.
256 */
257 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key;
258};
259
260
261/**
289 * A statement has been run. We should evaluate the result, and if possible 262 * A statement has been run. We should evaluate the result, and if possible
290 * call the given @a iter with the result. 263 * call the @a iter in @a cls with the result.
291 * 264 *
292 * @param plugin plugin context 265 * @param cls closure of type `struct ParserContext *`
293 * @param res result from the statement that was run (to be cleaned up) 266 * @param result the postgres result
294 * @param zone_key private key of the zone, could be NULL, in which case we should 267 * @param num_result the number of results in @a result
295 * get the zone from @a res
296 * @param iter iterator to call with the result
297 * @param iter_cls closure for @a iter
298 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
299 */ 268 */
300static int 269static void
301get_record_and_call_iterator (struct Plugin *plugin, 270parse_result_call_iterator (void *cls,
302 PGresult *res, 271 PGresult *res,
303 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, 272 unsigned int num_results)
304 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
305{ 273{
306 const char *data; 274 struct ParserContext *pc = cls;
307 size_t data_size; 275
308 uint32_t record_count; 276 for (unsigned int i=0;i<num_results;i++)
309 const char *label;
310 size_t label_len;
311 unsigned int cnt;
312
313 if (GNUNET_OK !=
314 GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK,
315 "PQexecPrepared",
316 "iteration"))
317 {
318 LOG (GNUNET_ERROR_TYPE_DEBUG,
319 "Failing lookup (postgres error)\n");
320 return GNUNET_SYSERR;
321 }
322 if (0 == (cnt = PQntuples (res)))
323 {
324 /* no result */
325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Ending iteration (no more results)\n");
327 PQclear (res);
328 return GNUNET_NO;
329 }
330 GNUNET_assert (1 == cnt);
331 GNUNET_assert (3 + ((NULL == zone_key) ? 1 : 0) == PQnfields (res));
332 if (NULL == zone_key)
333 { 277 {
334 if (sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) != PQgetlength (res, 0, 3)) 278 void *data;
279 size_t data_size;
280 uint32_t record_count;
281 char *label;
282 struct GNUNET_CRYPTO_EcdsaPrivateKey zk;
283 struct GNUNET_PQ_ResultSpec rs_with_zone[] = {
284 GNUNET_PQ_result_spec_uint32 ("record_count", &record_count),
285 GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size),
286 GNUNET_PQ_result_spec_string ("label", &label),
287 GNUNET_PQ_result_spec_auto_from_type ("zone_private_key", &zk),
288 GNUNET_PQ_result_spec_end
289 };
290 struct GNUNET_PQ_ResultSpec rs_without_zone[] = {
291 GNUNET_PQ_result_spec_uint32 ("record_count", &record_count),
292 GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size),
293 GNUNET_PQ_result_spec_string ("label", &label),
294 GNUNET_PQ_result_spec_end
295 };
296 struct GNUNET_PQ_ResultSpec *rs;
297
298 rs = (NULL == pc->zone_key) ? rs_with_zone : rs_without_zone;
299 if (GNUNET_YES !=
300 GNUNET_PQ_extract_result (res,
301 rs,
302 i))
335 { 303 {
336 GNUNET_break (0); 304 GNUNET_break (0);
337 PQclear (res); 305 return;
338 return GNUNET_SYSERR;
339 } 306 }
340 zone_key = (const struct GNUNET_CRYPTO_EcdsaPrivateKey *) PQgetvalue (res, 0, 3);
341 }
342 if (sizeof (uint32_t) != PQfsize (res, 0))
343 {
344 GNUNET_break (0);
345 PQclear (res);
346 return GNUNET_SYSERR;
347 }
348 307
349 record_count = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); 308 if (record_count > 64 * 1024)
350 data = PQgetvalue (res, 0, 1);
351 data_size = PQgetlength (res, 0, 1);
352 label = PQgetvalue (res, 0, 2);
353 label_len = PQgetlength (res, 0, 1);
354 if (record_count > 64 * 1024)
355 {
356 /* sanity check, don't stack allocate far too much just
357 because database might contain a large value here */
358 GNUNET_break (0);
359 PQclear (res);
360 return GNUNET_SYSERR;
361 }
362 {
363 struct GNUNET_GNSRECORD_Data rd[record_count];
364 char buf[label_len + 1];
365
366 GNUNET_memcpy (buf, label, label_len);
367 buf[label_len] = '\0';
368 if (GNUNET_OK !=
369 GNUNET_GNSRECORD_records_deserialize (data_size, data,
370 record_count, rd))
371 { 309 {
310 /* sanity check, don't stack allocate far too much just
311 because database might contain a large value here */
372 GNUNET_break (0); 312 GNUNET_break (0);
373 PQclear (res); 313 GNUNET_PQ_cleanup_result (rs);
374 return GNUNET_SYSERR; 314 return;
315 }
316
317 {
318 struct GNUNET_GNSRECORD_Data rd[record_count];
319
320 if (GNUNET_OK !=
321 GNUNET_GNSRECORD_records_deserialize (data_size,
322 data,
323 record_count,
324 rd))
325 {
326 GNUNET_break (0);
327 GNUNET_PQ_cleanup_result (rs);
328 return;
329 }
330 pc->iter (pc->iter_cls,
331 (NULL == pc->zone_key) ? &zk : pc->zone_key,
332 label,
333 record_count,
334 rd);
375 } 335 }
376 iter (iter_cls, zone_key, buf, record_count, rd); 336 GNUNET_PQ_cleanup_result (rs);
377 } 337 }
378 PQclear (res);
379 return GNUNET_OK;
380} 338}
381 339
382 340
@@ -398,25 +356,25 @@ namestore_postgres_lookup_records (void *cls,
398 void *iter_cls) 356 void *iter_cls)
399{ 357{
400 struct Plugin *plugin = cls; 358 struct Plugin *plugin = cls;
401 const char *paramValues[] = { 359 struct GNUNET_PQ_QueryParam params[] = {
402 (const char *) zone, 360 GNUNET_PQ_query_param_auto_from_type (zone),
403 label 361 GNUNET_PQ_query_param_string (label),
362 GNUNET_PQ_query_param_end
404 }; 363 };
405 int paramLengths[] = { 364 struct ParserContext pc;
406 sizeof (*zone), 365 enum GNUNET_DB_QueryStatus res;
407 strlen (label) 366
408 }; 367 pc.iter = iter;
409 const int paramFormats[] = { 1, 1 }; 368 pc.iter_cls = iter_cls;
410 PGresult *res; 369 pc.zone_key = NULL;
411 370 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
412 res = PQexecPrepared (plugin->dbh, 371 "lookup_label",
413 "lookup_label", 2, 372 params,
414 paramValues, paramLengths, paramFormats, 373 &parse_result_call_iterator,
415 1); 374 &pc);
416 return get_record_and_call_iterator (plugin, 375 if (res <= 0)
417 res, 376 return GNUNET_SYSERR;
418 zone, 377 return GNUNET_OK;
419 iter, iter_cls);
420} 378}
421 379
422 380
@@ -435,53 +393,50 @@ static int
435namestore_postgres_iterate_records (void *cls, 393namestore_postgres_iterate_records (void *cls,
436 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 394 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
437 uint64_t offset, 395 uint64_t offset,
438 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) 396 GNUNET_NAMESTORE_RecordIterator iter,
397 void *iter_cls)
439{ 398{
440 struct Plugin *plugin = cls; 399 struct Plugin *plugin = cls;
441 uint64_t offset_be = GNUNET_htonll (offset); 400 enum GNUNET_DB_QueryStatus res;
401 struct ParserContext pc;
442 402
403 pc.iter = iter;
404 pc.iter_cls = iter_cls;
405 pc.zone_key = zone;
443 if (NULL == zone) 406 if (NULL == zone)
444 { 407 {
445 const char *paramValues[] = { 408 struct GNUNET_PQ_QueryParam params_without_zone[] = {
446 (const char *) &offset_be 409 GNUNET_PQ_query_param_uint64 (&offset),
410 GNUNET_PQ_query_param_end
447 }; 411 };
448 int paramLengths[] = { 412
449 sizeof (offset_be) 413 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
450 }; 414 "iterate_all_zones",
451 const int paramFormats[] = { 1 }; 415 params_without_zone,
452 PGresult *res; 416 &parse_result_call_iterator,
453 417 &pc);
454 res = PQexecPrepared (plugin->dbh,
455 "iterate_all_zones", 1,
456 paramValues, paramLengths, paramFormats,
457 1);
458 return get_record_and_call_iterator (plugin,
459 res,
460 NULL,
461 iter, iter_cls);
462 } 418 }
463 else 419 else
464 { 420 {
465 const char *paramValues[] = { 421 struct GNUNET_PQ_QueryParam params_with_zone[] = {
466 (const char *) zone, 422 GNUNET_PQ_query_param_auto_from_type (zone),
467 (const char *) &offset_be 423 GNUNET_PQ_query_param_uint64 (&offset),
468 }; 424 GNUNET_PQ_query_param_end
469 int paramLengths[] = {
470 sizeof (*zone),
471 sizeof (offset_be)
472 }; 425 };
473 const int paramFormats[] = { 1, 1 }; 426
474 PGresult *res; 427 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
475 428 "iterate_zone",
476 res = PQexecPrepared (plugin->dbh, 429 params_with_zone,
477 "iterate_zone", 2, 430 &parse_result_call_iterator,
478 paramValues, paramLengths, paramFormats, 431 &pc);
479 1);
480 return get_record_and_call_iterator (plugin,
481 res,
482 zone,
483 iter, iter_cls);
484 } 432 }
433 if (res < 0)
434 return GNUNET_SYSERR;
435
436 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res)
437 return GNUNET_NO;
438
439 return GNUNET_OK;
485} 440}
486 441
487 442
@@ -503,25 +458,26 @@ namestore_postgres_zone_to_name (void *cls,
503 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) 458 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
504{ 459{
505 struct Plugin *plugin = cls; 460 struct Plugin *plugin = cls;
506 const char *paramValues[] = { 461 struct GNUNET_PQ_QueryParam params[] = {
507 (const char *) zone, 462 GNUNET_PQ_query_param_auto_from_type (zone),
508 (const char *) value_zone 463 GNUNET_PQ_query_param_auto_from_type (value_zone),
464 GNUNET_PQ_query_param_end
509 }; 465 };
510 int paramLengths[] = { 466 enum GNUNET_DB_QueryStatus res;
511 sizeof (*zone), 467 struct ParserContext pc;
512 sizeof (*value_zone) 468
513 }; 469 pc.iter = iter;
514 const int paramFormats[] = { 1, 1 }; 470 pc.iter_cls = iter_cls;
515 PGresult *res; 471 pc.zone_key = zone;
516 472
517 res = PQexecPrepared (plugin->dbh, 473 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
518 "zone_to_name", 2, 474 "zone_to_name",
519 paramValues, paramLengths, paramFormats, 475 params,
520 1); 476 &parse_result_call_iterator,
521 return get_record_and_call_iterator (plugin, 477 &pc);
522 res, 478 if (res < 0)
523 zone, 479 return GNUNET_SYSERR;
524 iter, iter_cls); 480 return GNUNET_OK;
525} 481}
526 482
527 483
@@ -568,7 +524,7 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
568 api->zone_to_name = &namestore_postgres_zone_to_name; 524 api->zone_to_name = &namestore_postgres_zone_to_name;
569 api->lookup_records = &namestore_postgres_lookup_records; 525 api->lookup_records = &namestore_postgres_lookup_records;
570 LOG (GNUNET_ERROR_TYPE_INFO, 526 LOG (GNUNET_ERROR_TYPE_INFO,
571 _("Postgres database running\n")); 527 "Postgres namestore plugin running\n");
572 return api; 528 return api;
573} 529}
574 530
@@ -589,7 +545,7 @@ libgnunet_plugin_namestore_postgres_done (void *cls)
589 plugin->cfg = NULL; 545 plugin->cfg = NULL;
590 GNUNET_free (api); 546 GNUNET_free (api);
591 LOG (GNUNET_ERROR_TYPE_DEBUG, 547 LOG (GNUNET_ERROR_TYPE_DEBUG,
592 "postgres plugin is finished\n"); 548 "Postgres namestore plugin is finished\n");
593 return NULL; 549 return NULL;
594} 550}
595 551