GNUnet  0.10.x
plugin_namestore_postgres.c
Go to the documentation of this file.
1  /*
2  * This file is part of GNUnet
3  * Copyright (C) 2009-2013, 2016-2018 GNUnet e.V.
4  *
5  * GNUnet is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Affero General Public License as published
7  * by the Free Software Foundation, either version 3 of the License,
8  * or (at your option) any later version.
9  *
10  * GNUnet is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
29 #include "gnunet_gnsrecord_lib.h"
30 #include "gnunet_pq_lib.h"
31 #include "namestore.h"
32 
33 
34 #define LOG(kind,...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__)
35 
36 
40 struct Plugin
41 {
42 
46  const struct GNUNET_CONFIGURATION_Handle *cfg;
47 
51  PGconn *dbh;
52 
53 };
54 
55 
64 static int
66 {
67  struct GNUNET_PQ_ExecuteStatement es_temporary =
68  GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns098records ("
69  " seq BIGSERIAL PRIMARY KEY,"
70  " zone_private_key BYTEA NOT NULL DEFAULT '',"
71  " pkey BYTEA DEFAULT '',"
72  " rvalue BYTEA NOT NULL DEFAULT '',"
73  " record_count INTEGER NOT NULL DEFAULT 0,"
74  " record_data BYTEA NOT NULL DEFAULT '',"
75  " label TEXT NOT NULL DEFAULT '',"
76  " CONSTRAINT zl UNIQUE (zone_private_key,label)"
77  ")"
78  "WITH OIDS");
79  struct GNUNET_PQ_ExecuteStatement es_default =
80  GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
81  " seq BIGSERIAL PRIMARY KEY,"
82  " zone_private_key BYTEA NOT NULL DEFAULT '',"
83  " pkey BYTEA DEFAULT '',"
84  " rvalue BYTEA NOT NULL DEFAULT '',"
85  " record_count INTEGER NOT NULL DEFAULT 0,"
86  " record_data BYTEA NOT NULL DEFAULT '',"
87  " label TEXT NOT NULL DEFAULT '',"
88  " CONSTRAINT zl UNIQUE (zone_private_key,label)"
89  ")"
90  "WITH OIDS");
91  const struct GNUNET_PQ_ExecuteStatement *cr;
92 
93  plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
94  "namestore-postgres");
95  if (NULL == plugin->dbh)
96  return GNUNET_SYSERR;
97  if (GNUNET_YES ==
99  "namestore-postgres",
100  "ASYNC_COMMIT"))
101  {
102  struct GNUNET_PQ_ExecuteStatement es[] = {
103  GNUNET_PQ_make_try_execute ("SET synchronous_commit TO off"),
105  };
106 
107  if (GNUNET_OK !=
109  es))
110  {
111  PQfinish (plugin->dbh);
112  plugin->dbh = NULL;
113  return GNUNET_SYSERR;
114  }
115  }
116  if (GNUNET_YES ==
118  "namestore-postgres",
119  "TEMPORARY_TABLE"))
120  {
121  cr = &es_temporary;
122  }
123  else
124  {
125  cr = &es_default;
126  }
127 
128  {
129  struct GNUNET_PQ_ExecuteStatement es[] = {
130  *cr,
131  GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
132  "ON ns098records (zone_private_key,pkey)"),
133  GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
134  "ON ns098records (zone_private_key,seq)"),
135  GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label "
136  "ON ns098records (label)"),
137  GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label "
138  "ON ns098records (zone_private_key,label)"),
140  };
141 
142  if (GNUNET_OK !=
144  es))
145  {
146  PQfinish (plugin->dbh);
147  plugin->dbh = NULL;
148  return GNUNET_SYSERR;
149  }
150  }
151 
152  {
153  struct GNUNET_PQ_PreparedStatement ps[] = {
154  GNUNET_PQ_make_prepare ("store_records",
155  "INSERT INTO ns098records"
156  " (zone_private_key, pkey, rvalue, record_count, record_data, label)"
157  " VALUES ($1, $2, $3, $4, $5, $6)"
158  " ON CONFLICT ON CONSTRAINT zl"
159  " DO UPDATE"
160  " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5"
161  " WHERE ns098records.zone_private_key = $1"
162  " AND ns098records.label = $6",
163  6),
164  GNUNET_PQ_make_prepare ("delete_records",
165  "DELETE FROM ns098records "
166  "WHERE zone_private_key=$1 AND label=$2",
167  2),
168  GNUNET_PQ_make_prepare ("zone_to_name",
169  "SELECT seq,record_count,record_data,label FROM ns098records"
170  " WHERE zone_private_key=$1 AND pkey=$2",
171  2),
172  GNUNET_PQ_make_prepare ("iterate_zone",
173  "SELECT seq,record_count,record_data,label FROM ns098records "
174  "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3",
175  3),
176  GNUNET_PQ_make_prepare ("iterate_all_zones",
177  "SELECT seq,record_count,record_data,label,zone_private_key"
178  " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2",
179  2),
180  GNUNET_PQ_make_prepare ("lookup_label",
181  "SELECT seq,record_count,record_data,label "
182  "FROM ns098records WHERE zone_private_key=$1 AND label=$2",
183  2),
185  };
186 
187  if (GNUNET_OK !=
189  ps))
190  {
191  PQfinish (plugin->dbh);
192  plugin->dbh = NULL;
193  return GNUNET_SYSERR;
194  }
195  }
196 
197  return GNUNET_OK;
198 }
199 
200 
212 static int
214  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
215  const char *label,
216  unsigned int rd_count,
217  const struct GNUNET_GNSRECORD_Data *rd)
218 {
219  struct Plugin *plugin = cls;
220  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
221  uint64_t rvalue;
222  uint32_t rd_count32 = (uint32_t) rd_count;
223  ssize_t data_size;
224 
225  memset (&pkey,
226  0,
227  sizeof (pkey));
228  for (unsigned int i=0;i<rd_count;i++)
229  if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type)
230  {
231  GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size);
232  GNUNET_memcpy (&pkey,
233  rd[i].data,
234  rd[i].data_size);
235  break;
236  }
238  UINT64_MAX);
239  data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
240  rd);
241  if (data_size < 0)
242  {
243  GNUNET_break (0);
244  return GNUNET_SYSERR;
245  }
246  if (data_size >= UINT16_MAX)
247  {
248  GNUNET_break (0);
249  return GNUNET_SYSERR;
250  }
251  /* if record set is empty, delete existing records */
252  if (0 == rd_count)
253  {
254  struct GNUNET_PQ_QueryParam params[] = {
258  };
260 
262  "delete_records",
263  params);
264  if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) &&
266  {
267  GNUNET_break (0);
268  return GNUNET_SYSERR;
269  }
271  "postgres",
272  "Record deleted\n");
273  return GNUNET_OK;
274  }
275  /* otherwise, UPSERT (i.e. UPDATE if exists, otherwise INSERT) */
276  {
277  char data[data_size];
278  struct GNUNET_PQ_QueryParam params[] = {
282  GNUNET_PQ_query_param_uint32 (&rd_count32),
283  GNUNET_PQ_query_param_fixed_size (data, data_size),
286  };
288  ssize_t ret;
289 
290  ret = GNUNET_GNSRECORD_records_serialize (rd_count,
291  rd,
292  data_size,
293  data);
294  if ( (ret < 0) ||
295  (data_size != ret) )
296  {
297  GNUNET_break (0);
298  return GNUNET_SYSERR;
299  }
300 
302  "store_records",
303  params);
305  return GNUNET_SYSERR;
306  }
307  return GNUNET_OK;
308 }
309 
310 
315 {
320 
324  void *iter_cls;
325 
330 
335  uint64_t limit;
336 };
337 
338 
347 static void
349  PGresult *res,
350  unsigned int num_results)
351 {
352  struct ParserContext *pc = cls;
353 
354  if (NULL == pc->iter)
355  return; /* no need to do more work */
356  for (unsigned int i=0;i<num_results;i++)
357  {
358  uint64_t serial;
359  void *data;
360  size_t data_size;
361  uint32_t record_count;
362  char *label;
364  struct GNUNET_PQ_ResultSpec rs_with_zone[] = {
365  GNUNET_PQ_result_spec_uint64 ("seq", &serial),
366  GNUNET_PQ_result_spec_uint32 ("record_count", &record_count),
367  GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size),
368  GNUNET_PQ_result_spec_string ("label", &label),
369  GNUNET_PQ_result_spec_auto_from_type ("zone_private_key", &zk),
371  };
372  struct GNUNET_PQ_ResultSpec rs_without_zone[] = {
373  GNUNET_PQ_result_spec_uint64 ("seq", &serial),
374  GNUNET_PQ_result_spec_uint32 ("record_count", &record_count),
375  GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size),
376  GNUNET_PQ_result_spec_string ("label", &label),
378  };
379  struct GNUNET_PQ_ResultSpec *rs;
380 
381  rs = (NULL == pc->zone_key) ? rs_with_zone : rs_without_zone;
382  if (GNUNET_YES !=
384  rs,
385  i))
386  {
387  GNUNET_break (0);
388  return;
389  }
390 
391  if (record_count > 64 * 1024)
392  {
393  /* sanity check, don't stack allocate far too much just
394  because database might contain a large value here */
395  GNUNET_break (0);
397  return;
398  }
399 
400  {
401  struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(record_count)];
402 
403  GNUNET_assert (0 != serial);
404  if (GNUNET_OK !=
406  data,
407  record_count,
408  rd))
409  {
410  GNUNET_break (0);
412  return;
413  }
414  pc->iter (pc->iter_cls,
415  serial,
416  (NULL == pc->zone_key) ? &zk : pc->zone_key,
417  label,
418  record_count,
419  rd);
420  }
422  }
423  pc->limit -= num_results;
424 }
425 
426 
437 static int
439  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
440  const char *label,
442  void *iter_cls)
443 {
444  struct Plugin *plugin = cls;
445  struct GNUNET_PQ_QueryParam params[] = {
449  };
450  struct ParserContext pc;
452 
453  if (NULL == zone)
454  {
455  GNUNET_break (0);
456  return GNUNET_SYSERR;
457  }
458  pc.iter = iter;
459  pc.iter_cls = iter_cls;
460  pc.zone_key = zone;
462  "lookup_label",
463  params,
465  &pc);
466  if (res < 0)
467  return GNUNET_SYSERR;
469  return GNUNET_NO;
470  return GNUNET_OK;
471 }
472 
473 
486 static int
488  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
489  uint64_t serial,
490  uint64_t limit,
492  void *iter_cls)
493 {
494  struct Plugin *plugin = cls;
496  struct ParserContext pc;
497 
498  pc.iter = iter;
499  pc.iter_cls = iter_cls;
500  pc.zone_key = zone;
501  pc.limit = limit;
502  if (NULL == zone)
503  {
504  struct GNUNET_PQ_QueryParam params_without_zone[] = {
508  };
509 
511  "iterate_all_zones",
512  params_without_zone,
514  &pc);
515  }
516  else
517  {
518  struct GNUNET_PQ_QueryParam params_with_zone[] = {
523  };
524 
526  "iterate_zone",
527  params_with_zone,
529  &pc);
530  }
531  if (res < 0)
532  return GNUNET_SYSERR;
533 
534  if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) ||
535  (pc.limit > 0) )
536  return GNUNET_NO;
537  return GNUNET_OK;
538 }
539 
540 
552 static int
554  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
555  const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
557 {
558  struct Plugin *plugin = cls;
559  struct GNUNET_PQ_QueryParam params[] = {
563  };
565  struct ParserContext pc;
566 
567  pc.iter = iter;
568  pc.iter_cls = iter_cls;
569  pc.zone_key = zone;
571  "zone_to_name",
572  params,
574  &pc);
575  if (res < 0)
576  return GNUNET_SYSERR;
577  return GNUNET_OK;
578 }
579 
580 
587 static void
589 {
590  PQfinish (plugin->dbh);
591  plugin->dbh = NULL;
592 }
593 
594 
601 void *
603 {
604  static struct Plugin plugin;
605  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
607 
608  if (NULL != plugin.cfg)
609  return NULL; /* can only initialize once! */
610  memset (&plugin, 0, sizeof (struct Plugin));
611  plugin.cfg = cfg;
612  if (GNUNET_OK != database_setup (&plugin))
613  {
614  database_shutdown (&plugin);
615  return NULL;
616  }
618  api->cls = &plugin;
624  "Postgres namestore plugin running\n");
625  return api;
626 }
627 
628 
635 void *
637 {
639  struct Plugin *plugin = api->cls;
640 
641  database_shutdown (plugin);
642  plugin->cfg = NULL;
643  GNUNET_free (api);
645  "Postgres namestore plugin is finished\n");
646  return NULL;
647 }
648 
649 /* end of plugin_namestore_postgres.c */
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
struct GNUNET_PQ_ExecuteStatement GNUNET_PQ_make_execute(const char *sql)
Create a struct GNUNET_PQ_ExecuteStatement where errors are fatal.
Definition: pq_exec.c:37
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
struct GNUNET_PQ_QueryParam GNUNET_PQ_query_param_string(const char *ptr)
Generate query parameter for a string.
int(* zone_to_name)(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Look for an existing PKEY delegation record for a given public key.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Information needed to run a list of SQL statements using GNUNET_PQ_exec_statements().
Information needed to prepare a list of SQL statements using GNUNET_PQ_prepare_statements().
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Description of a DB result cell.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static void database_shutdown(struct Plugin *plugin)
Shutdown database connection and associate data structures.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Private ECC key encoded for transmission.
void(* GNUNET_NAMESTORE_RecordIterator)(void *cls, uint64_t serial, const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Function called for each matching record.
enum GNUNET_DB_QueryStatus GNUNET_PQ_eval_prepared_non_select(PGconn *connection, const char *statement_name, const struct GNUNET_PQ_QueryParam *params)
Execute a named prepared statement that is NOT a SELECT statement in connnection using the given para...
Definition: pq_eval.c:151
int GNUNET_GNSRECORD_records_deserialize(size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest)
Deserialize the given records to the given destination.
#define LOG(kind,...)
static int ret
Final status code.
Definition: gnunet-arm.c:89
uint64_t limit
Number of results still to return (counted down by number of results given to iterator).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
common internal definitions for namestore service
static char * zone
Name of the zone we manage.
void * cls
Closure to pass to all plugin functions.
static uint64_t record_count
Record count.
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_string(const char *name, char **dst)
0-terminated string expected.
#define GNUNET_PQ_result_spec_end
End of result parameter specification.
static int namestore_postgres_store_records(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Store a record in the datastore.
#define GNUNET_PQ_query_param_end
End of query parameter specification.
Definition: gnunet_pq_lib.h:96
static int namestore_postgres_zone_to_name(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Look for an existing PKEY delegation record for a given public key.
int GNUNET_PQ_prepare_statements(PGconn *connection, const struct GNUNET_PQ_PreparedStatement *ps)
Request creation of prepared statements ps from Postgres.
Definition: pq_prepare.c:63
#define GNUNET_memcpy(dst, src, n)
void * libgnunet_plugin_namestore_postgres_init(void *cls)
Entry point for the plugin.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_variable_size(const char *name, void **dst, size_t *sptr)
Variable-size result expected.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint32(const char *name, uint32_t *u32)
uint32_t expected.
#define GNUNET_GNSRECORD_TYPE_PKEY
Record type for GNS zone transfer ("PKEY").
#define GNUNET_PQ_query_param_auto_from_type(x)
Generate fixed-size query parameter with size determined by variable type.
struct GNUNET_PQ_QueryParam GNUNET_PQ_query_param_uint32(const uint32_t *x)
Generate query parameter for an uint32_t in host byte order.
static int database_setup(struct Plugin *plugin)
Initialize the database connections and associated data structures (create tables and indices as need...
static int res
static int namestore_postgres_iterate_records(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, uint64_t serial, uint64_t limit, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Iterate over the results for a particular key and zone in the datastore.
#define GNUNET_PQ_result_spec_auto_from_type(name, dst)
We expect a fixed-size result, with size determined by the type of * dst
PGconn * GNUNET_PQ_connect_with_cfg(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Connect to a postgres database using the configuration option "CONFIG" in section.
Definition: pq_connect.c:112
#define GNUNET_PQ_PREPARED_STATEMENT_END
Terminator for prepared statement list.
GNUNET_NAMESTORE_RecordIterator iter
Function to call for each result.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static void parse_result_call_iterator(void *cls, PGresult *res, unsigned int num_results)
A statement has been run.
helper functions for Postgres DB interactions
void * iter_cls
Iterator cls.
void * libgnunet_plugin_namestore_postgres_done(void *cls)
Exit point from the plugin.
Closure for parse_result_call_iterator.
int GNUNET_PQ_exec_statements(PGconn *connection, const struct GNUNET_PQ_ExecuteStatement *es)
Request execution of an array of statements es from Postgres.
Definition: pq_exec.c:77
static int namestore_postgres_lookup_records(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Lookup records in the datastore for which we are the authority.
The transaction succeeded, and yielded one result.
Definition: gnunet_db_lib.h:58
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
int(* lookup_records)(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Lookup records in the datastore for which we are the authority.
configuration data
Definition: configuration.c:85
Handle for a plugin.
Definition: block.c:37
PGconn * dbh
Native Postgres database handle.
struct GNUNET_PQ_QueryParam GNUNET_PQ_query_param_uint64(const uint64_t *x)
Generate query parameter for an uint16_t in host byte order.
void * iter_cls
Closure for iter.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
Description of a DB query parameter.
Definition: gnunet_pq_lib.h:63
struct GNUNET_PQ_QueryParam GNUNET_PQ_query_param_fixed_size(const void *ptr, size_t ptr_size)
Generate query parameter for a buffer ptr of ptr_size bytes.
#define GNUNET_PQ_EXECUTE_STATEMENT_END
Terminator for executable statement list.
const struct GNUNET_CRYPTO_EcdsaPrivateKey * zone_key
Zone key, NULL if part of record.
#define GNUNET_YES
Definition: gnunet_common.h:80
GNUNET_DB_QueryStatus
Status code returned from functions running database commands.
Definition: gnunet_db_lib.h:34
struct GNUNET_PQ_ExecuteStatement GNUNET_PQ_make_try_execute(const char *sql)
Create a struct GNUNET_PQ_ExecuteStatement where errors should be tolerated.
Definition: pq_exec.c:56
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint64(const char *name, uint64_t *u64)
uint64_t expected.
#define GNUNET_log_from(kind, comp,...)
The transaction succeeded, but yielded zero results.
Definition: gnunet_db_lib.h:53
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint32_t data
The data value.
int(* store_records)(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Store a record in the datastore for which we are the authority.
static size_t data_size
Number of bytes in data.
GNUNET_PEERSTORE_Processor iter
Iterator.
struct returned by the initialization function of the plugin
enum GNUNET_DB_QueryStatus GNUNET_PQ_eval_prepared_multi_select(PGconn *connection, const char *statement_name, const struct GNUNET_PQ_QueryParam *params, GNUNET_PQ_PostgresResultHandler rh, void *rh_cls)
Execute a named prepared statement that is a SELECT statement which may return multiple results in co...
Definition: pq_eval.c:194
struct GNUNET_PQ_PreparedStatement GNUNET_PQ_make_prepare(const char *name, const char *sql, unsigned int num_args)
Create a struct GNUNET_PQ_PreparedStatement.
Definition: pq_prepare.c:39
int(* iterate_records)(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, uint64_t serial, uint64_t limit, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Iterate over the results for a particular zone in the datastore.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
int GNUNET_PQ_extract_result(PGresult *result, struct GNUNET_PQ_ResultSpec *rs, int row)
Extract results from a query result according to the given specification.
Definition: pq.c:144
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_PQ_cleanup_result(struct GNUNET_PQ_ResultSpec *rs)
Free all memory that was allocated in rs during GNUNET_PQ_extract_result().
Definition: pq.c:121