GNUnet  0.11.x
plugin_datacache_sqlite.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2006, 2009, 2015 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"
27 #include "gnunet_util_lib.h"
29 #include "gnunet_sq_lib.h"
30 #include <sqlite3.h>
31 
32 #define LOG(kind, ...) GNUNET_log_from (kind, "datacache-sqlite", __VA_ARGS__)
33 
34 #define LOG_STRERROR_FILE(kind, op, fn) \
35  GNUNET_log_from_strerror_file (kind, "datacache-sqlite", op, fn)
36 
37 
42 #define OVERHEAD (sizeof(struct GNUNET_HashCode) + 36)
43 
47 struct Plugin
48 {
53 
57  sqlite3 *dbh;
58 
62  char *fn;
63 
67  sqlite3_stmt *insert_stmt;
68 
72  sqlite3_stmt *get_count_stmt;
73 
77  sqlite3_stmt *get_stmt;
78 
82  sqlite3_stmt *del_select_stmt;
83 
87  sqlite3_stmt *del_expired_stmt;
88 
92  sqlite3_stmt *del_stmt;
93 
97  sqlite3_stmt *get_closest_stmt;
98 
102  unsigned int num_items;
103 };
104 
105 
114 #define LOG_SQLITE(db, level, cmd) \
115  do \
116  { \
117  LOG (level, \
118  _ ("`%s' failed at %s:%d with error: %s\n"), \
119  cmd, \
120  __FILE__, \
121  __LINE__, \
122  sqlite3_errmsg (db)); \
123  } while (0)
124 
125 
132 #define SQLITE3_EXEC(db, cmd) \
133  do \
134  { \
135  emsg = NULL; \
136  if (SQLITE_OK != sqlite3_exec (db, cmd, NULL, NULL, &emsg)) \
137  { \
138  LOG (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, \
139  _ ("`%s' failed at %s:%d with error: %s\n"), \
140  "sqlite3_exec", \
141  __FILE__, \
142  __LINE__, \
143  emsg); \
144  sqlite3_free (emsg); \
145  } \
146  } while (0)
147 
148 
157 static int
158 sq_prepare (sqlite3 *dbh,
159  const char *zSql, /* SQL statement, UTF-8 encoded */
160  sqlite3_stmt **ppStmt)
161 { /* OUT: Statement handle */
162  char *dummy;
163 
164  return sqlite3_prepare (dbh,
165  zSql,
166  strlen (zSql),
167  ppStmt,
168  (const char **) &dummy);
169 }
170 
171 
186 static ssize_t
188  const struct GNUNET_HashCode *key,
189  uint32_t xor_distance,
190  size_t size,
191  const char *data,
192  enum GNUNET_BLOCK_Type type,
193  struct GNUNET_TIME_Absolute discard_time,
194  unsigned int path_info_len,
195  const struct GNUNET_DHT_PathElement *path_info)
196 {
197  struct Plugin *plugin = cls;
198  uint32_t type32 = type;
199  struct GNUNET_SQ_QueryParam params[] =
200  { GNUNET_SQ_query_param_uint32 (&type32),
201  GNUNET_SQ_query_param_absolute_time (&discard_time),
203  GNUNET_SQ_query_param_uint32 (&xor_distance),
206  path_info_len
207  * sizeof(struct GNUNET_DHT_PathElement)),
209 
211  "Processing PUT of %u bytes with key `%s' and expiration %s\n",
212  (unsigned int) size,
213  GNUNET_h2s (key),
216  discard_time),
217  GNUNET_YES));
218  if (GNUNET_OK != GNUNET_SQ_bind (plugin->insert_stmt, params))
219  {
222  "sqlite3_bind_xxx");
224  return -1;
225  }
226  if (SQLITE_DONE != sqlite3_step (plugin->insert_stmt))
227  {
230  "sqlite3_step");
232  return -1;
233  }
234  plugin->num_items++;
236  return size + OVERHEAD;
237 }
238 
239 
251 static unsigned int
252 sqlite_plugin_get (void *cls,
253  const struct GNUNET_HashCode *key,
254  enum GNUNET_BLOCK_Type type,
256  void *iter_cls)
257 {
258  struct Plugin *plugin = cls;
259  uint32_t type32 = type;
260  struct GNUNET_TIME_Absolute now;
261  struct GNUNET_TIME_Absolute exp;
262  size_t size;
263  void *dat;
264  unsigned int cnt;
265  uint32_t off;
266  unsigned int total;
267  size_t psize;
268  struct GNUNET_DHT_PathElement *path;
269  struct GNUNET_SQ_QueryParam params_count[] =
274  struct GNUNET_SQ_QueryParam params_select[] =
280  struct GNUNET_SQ_ResultSpec rs[] =
283  GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
285 
286  now = GNUNET_TIME_absolute_get ();
288  "Processing GET for key `%s'\n",
289  GNUNET_h2s (key));
290 
291  if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_count_stmt, params_count))
292  {
295  "sqlite3_bind_xxx");
297  return 0;
298  }
299  if (SQLITE_ROW != sqlite3_step (plugin->get_count_stmt))
300  {
303  "sqlite_step");
306  "No content found when processing GET for key `%s'\n",
307  GNUNET_h2s (key));
308  return 0;
309  }
310  total = sqlite3_column_int (plugin->get_count_stmt, 0);
312  if ((0 == total) || (NULL == iter))
313  {
314  if (0 == total)
316  "No content found when processing GET for key `%s'\n",
317  GNUNET_h2s (key));
318  return total;
319  }
320 
321  cnt = 0;
323  while (cnt < total)
324  {
325  off = (off + 1) % total;
326  if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_stmt, params_select))
327  {
330  "sqlite3_bind_xxx");
332  return cnt;
333  }
334  if (SQLITE_ROW != sqlite3_step (plugin->get_stmt))
335  break;
337  {
338  GNUNET_break (0);
340  break;
341  }
342  if (0 != psize % sizeof(struct GNUNET_DHT_PathElement))
343  {
344  GNUNET_break (0);
345  psize = 0;
346  path = NULL;
347  }
348  psize /= sizeof(struct GNUNET_DHT_PathElement);
349  cnt++;
351  "Found %u-byte result when processing GET for key `%s'\n",
352  (unsigned int) size,
353  GNUNET_h2s (key));
354  if (GNUNET_OK != iter (iter_cls, key, size, dat, type, exp, psize, path))
355  {
358  break;
359  }
362  }
364  return cnt;
365 }
366 
367 
375 static int
376 sqlite_plugin_del (void *cls)
377 {
378  struct Plugin *plugin = cls;
379  uint64_t rowid;
380  void *data;
381  size_t dsize;
382  struct GNUNET_HashCode hc;
383  struct GNUNET_TIME_Absolute now;
384  struct GNUNET_SQ_ResultSpec rs[] =
385  { GNUNET_SQ_result_spec_uint64 (&rowid),
387  GNUNET_SQ_result_spec_variable_size ((void **) &data, &dsize),
390  &rowid),
392  struct GNUNET_SQ_QueryParam time_params[] =
394 
395  LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing DEL\n");
396  now = GNUNET_TIME_absolute_get ();
397  if (GNUNET_OK != GNUNET_SQ_bind (plugin->del_expired_stmt, time_params))
398  {
401  "sqlite3_bind");
403  return GNUNET_SYSERR;
404  }
405  if ((SQLITE_ROW != sqlite3_step (plugin->del_expired_stmt)) ||
407  {
409  if (SQLITE_ROW != sqlite3_step (plugin->del_select_stmt))
410  {
413  "sqlite3_step");
415  return GNUNET_SYSERR;
416  }
418  {
420  GNUNET_break (0);
421  return GNUNET_SYSERR;
422  }
423  }
426  if (GNUNET_OK != GNUNET_SQ_bind (plugin->del_stmt, params))
427  {
430  "sqlite3_bind");
432  return GNUNET_SYSERR;
433  }
434  if (SQLITE_DONE != sqlite3_step (plugin->del_stmt))
435  {
438  "sqlite3_step");
440  return GNUNET_SYSERR;
441  }
442  plugin->num_items--;
443  plugin->env->delete_notify (plugin->env->cls, &hc, dsize + OVERHEAD);
445  return GNUNET_OK;
446 }
447 
448 
462 static unsigned int
464  const struct GNUNET_HashCode *key,
465  unsigned int num_results,
467  void *iter_cls)
468 {
469  struct Plugin *plugin = cls;
470  uint32_t num_results32 = num_results;
471  struct GNUNET_TIME_Absolute now;
472  struct GNUNET_TIME_Absolute exp;
473  size_t size;
474  void *dat;
475  unsigned int cnt;
476  size_t psize;
477  uint32_t type;
478  struct GNUNET_HashCode hc;
479  struct GNUNET_DHT_PathElement *path;
480  struct GNUNET_SQ_QueryParam params[] =
483  GNUNET_SQ_query_param_uint32 (&num_results32),
485  struct GNUNET_SQ_ResultSpec rs[] =
488  GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
492 
493  now = GNUNET_TIME_absolute_get ();
495  "Processing GET_CLOSEST for key `%s'\n",
496  GNUNET_h2s (key));
498  {
501  "sqlite3_bind_xxx");
503  return 0;
504  }
505  cnt = 0;
506  while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt))
507  {
509  {
510  GNUNET_break (0);
511  break;
512  }
513  if (0 != psize % sizeof(struct GNUNET_DHT_PathElement))
514  {
515  GNUNET_break (0);
516  psize = 0;
517  path = NULL;
518  }
519  psize /= sizeof(struct GNUNET_DHT_PathElement);
520  cnt++;
522  "Found %u-byte result at %s when processing GET_CLOSE\n",
523  (unsigned int) size,
524  GNUNET_h2s (&hc));
525  if (GNUNET_OK != iter (iter_cls, &hc, size, dat, type, exp, psize, path))
526  {
528  break;
529  }
531  }
533  return cnt;
534 }
535 
536 
543 void *
545 {
548  struct Plugin *plugin;
549  char *fn;
550  char *fn_utf8;
551  sqlite3 *dbh;
552  char *emsg;
553 
555  "datacache-sqlite",
556  "IN_MEMORY"))
557  {
558  if (SQLITE_OK != sqlite3_open (":memory:", &dbh))
559  return NULL;
560  fn_utf8 = NULL;
561  }
562  else
563  {
564  fn = GNUNET_DISK_mktemp ("gnunet-datacache");
565  if (fn == NULL)
566  {
567  GNUNET_break (0);
568  return NULL;
569  }
570  /* fn should be UTF-8-encoded. If it isn't, it's a bug. */
571  fn_utf8 = GNUNET_strdup (fn);
572  if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh))
573  {
574  GNUNET_free (fn);
575  GNUNET_free (fn_utf8);
576  return NULL;
577  }
578  GNUNET_free (fn);
579  }
580 
581  SQLITE3_EXEC (dbh, "PRAGMA temp_store=MEMORY");
582  SQLITE3_EXEC (dbh, "PRAGMA locking_mode=EXCLUSIVE");
583  SQLITE3_EXEC (dbh, "PRAGMA journal_mode=OFF");
584  SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF");
585  SQLITE3_EXEC (dbh, "PRAGMA page_size=4092");
587  "datacache-sqlite",
588  "IN_MEMORY"))
589  SQLITE3_EXEC (dbh, "PRAGMA sqlite_temp_store=3");
590 
591  SQLITE3_EXEC (dbh,
592  "CREATE TABLE ds091 ("
593  " type INTEGER NOT NULL DEFAULT 0,"
594  " expire INTEGER NOT NULL,"
595  " key BLOB NOT NULL DEFAULT '',"
596  " prox INTEGER NOT NULL,"
597  " value BLOB NOT NULL,"
598  " path BLOB DEFAULT '')");
599  SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds091 (key,type,expire)");
600  SQLITE3_EXEC (dbh, "CREATE INDEX idx_prox_expire ON ds091 (prox,expire)");
601  SQLITE3_EXEC (dbh, "CREATE INDEX idx_expire_only ON ds091 (expire)");
602  plugin = GNUNET_new (struct Plugin);
603  plugin->env = env;
604  plugin->dbh = dbh;
605  plugin->fn = fn_utf8;
606 
607  if ((SQLITE_OK !=
609  "INSERT INTO ds091 (type, expire, key, prox, value, path) "
610  "VALUES (?, ?, ?, ?, ?, ?)",
611  &plugin->insert_stmt)) ||
612  (SQLITE_OK != sq_prepare (plugin->dbh,
613  "SELECT count(*) FROM ds091 "
614  "WHERE key=? AND type=? AND expire >= ?",
615  &plugin->get_count_stmt)) ||
616  (SQLITE_OK !=
618  "SELECT value,expire,path FROM ds091"
619  " WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?",
620  &plugin->get_stmt)) ||
621  (SQLITE_OK != sq_prepare (plugin->dbh,
622  "SELECT _ROWID_,key,value FROM ds091"
623  " WHERE expire < ?"
624  " ORDER BY expire ASC LIMIT 1",
625  &plugin->del_expired_stmt)) ||
626  (SQLITE_OK != sq_prepare (plugin->dbh,
627  "SELECT _ROWID_,key,value FROM ds091"
628  " ORDER BY prox ASC, expire ASC LIMIT 1",
629  &plugin->del_select_stmt)) ||
630  (SQLITE_OK != sq_prepare (plugin->dbh,
631  "DELETE FROM ds091 WHERE _ROWID_=?",
632  &plugin->del_stmt)) ||
633  (SQLITE_OK !=
635  "SELECT value,expire,path,type,key FROM ds091 "
636  "WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?",
638  {
641  "sq_prepare");
642  GNUNET_break (SQLITE_OK == sqlite3_close (plugin->dbh));
644  return NULL;
645  }
646 
648  api->cls = plugin;
649  api->get = &sqlite_plugin_get;
650  api->put = &sqlite_plugin_put;
651  api->del = &sqlite_plugin_del;
652  api->get_closest = &sqlite_plugin_get_closest;
653  LOG (GNUNET_ERROR_TYPE_INFO, "Sqlite datacache running\n");
654  return api;
655 }
656 
657 
664 void *
666 {
668  struct Plugin *plugin = api->cls;
669  int result;
670 
671 #if SQLITE_VERSION_NUMBER >= 3007000
672  sqlite3_stmt *stmt;
673 #endif
674 
675 #if ! WINDOWS || defined(__CYGWIN__)
676  if ((NULL != plugin->fn) && (0 != unlink (plugin->fn)))
678  GNUNET_free (plugin->fn);
679 #endif
680  sqlite3_finalize (plugin->insert_stmt);
681  sqlite3_finalize (plugin->get_count_stmt);
682  sqlite3_finalize (plugin->get_stmt);
683  sqlite3_finalize (plugin->del_select_stmt);
684  sqlite3_finalize (plugin->del_expired_stmt);
685  sqlite3_finalize (plugin->del_stmt);
686  sqlite3_finalize (plugin->get_closest_stmt);
687  result = sqlite3_close (plugin->dbh);
688 #if SQLITE_VERSION_NUMBER >= 3007000
689  if (SQLITE_BUSY == result)
690  {
692  _ (
693  "Tried to close sqlite without finalizing all prepared statements.\n"));
694  stmt = sqlite3_next_stmt (plugin->dbh, NULL);
695  while (NULL != stmt)
696  {
697  result = sqlite3_finalize (stmt);
698  if (result != SQLITE_OK)
700  "Failed to close statement %p: %d\n",
701  stmt,
702  result);
703  stmt = sqlite3_next_stmt (plugin->dbh, NULL);
704  }
705  result = sqlite3_close (plugin->dbh);
706  }
707 #endif
708  if (SQLITE_OK != result)
709  LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
710 
712  GNUNET_free (api);
713  return NULL;
714 }
715 
716 
717 /* end of plugin_datacache_sqlite.c */
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct Plugin * plugin
The process handle to the testbed service.
struct GNUNET_HashCode key
The key used in the DHT.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
uint32_t data
The data value.
static int result
Global testing status.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
helper functions for Sqlite3 DB interactions
int GNUNET_SQ_bind(sqlite3_stmt *stmt, const struct GNUNET_SQ_QueryParam *params)
Execute binding operations for a prepared statement.
Definition: sq.c:37
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_fixed_size(const void *ptr, size_t ptr_size)
Generate query parameter for a buffer ptr of ptr_size bytes.
enum GNUNET_GenericReturnValue GNUNET_SQ_extract_result(sqlite3_stmt *result, struct GNUNET_SQ_ResultSpec *rs)
Extract results from a query result according to the given specification.
Definition: sq.c:82
void GNUNET_SQ_cleanup_result(struct GNUNET_SQ_ResultSpec *rs)
Free all memory that was allocated in rs during GNUNET_SQ_extract_result().
Definition: sq.c:117
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint32(const uint32_t *x)
Generate query parameter for an uint32_t in host byte order.
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint64(const uint64_t *x)
Generate query parameter for an uint16_t in host byte order.
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_absolute_time(struct GNUNET_TIME_Absolute *at)
Absolute time expected.
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_uint32(uint32_t *u32)
uint32_t expected.
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_absolute_time(const struct GNUNET_TIME_Absolute *x)
Generate query parameter for an absolute time value.
#define GNUNET_SQ_result_spec_end
End of result parameter specification.
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_variable_size(void **dst, size_t *sptr)
Variable-size result expected.
#define GNUNET_SQ_query_param_auto_from_type(x)
Generate fixed-size query parameter with size determined by variable type.
void GNUNET_SQ_reset(sqlite3 *dbh, sqlite3_stmt *stmt)
Reset stmt and log error.
Definition: sq.c:132
#define GNUNET_SQ_query_param_end
End of query parameter specification.
Definition: gnunet_sq_lib.h:86
#define GNUNET_SQ_result_spec_auto_from_type(dst)
We expect a fixed-size result, with size determined by the type of * dst
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_uint64(uint64_t *u64)
uint64_t expected.
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
enum GNUNET_GenericReturnValue 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 GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
enum GNUNET_GenericReturnValue(* GNUNET_DATACACHE_Iterator)(void *cls, const struct GNUNET_HashCode *key, size_t data_size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int path_info_len, const struct GNUNET_DHT_PathElement *path_info)
An iterator over a set of items stored in the datacache.
char * GNUNET_DISK_mktemp(const char *t)
Create an (empty) temporary file on disk.
Definition: disk.c:381
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:374
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:94
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:543
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
#define OVERHEAD
How much overhead do we assume per entry in the datacache?
#define SQLITE3_EXEC(db, cmd)
Execute SQL statement.
static ssize_t sqlite_plugin_put(void *cls, const struct GNUNET_HashCode *key, uint32_t xor_distance, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_DHT_PathElement *path_info)
Store an item in the datastore.
void * libgnunet_plugin_datacache_sqlite_done(void *cls)
Exit point from the plugin.
#define LOG_SQLITE(db, level, cmd)
Log an error message at log-level level that indicates a failure of the command cmd with the error fr...
static unsigned int sqlite_plugin_get(void *cls, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
Iterate over the results for a particular key in the datastore.
static int sq_prepare(sqlite3 *dbh, const char *zSql, sqlite3_stmt **ppStmt)
Prepare a SQL statement.
static int sqlite_plugin_del(void *cls)
Delete the entry with the lowest expiration value from the datacache right now.
static unsigned int sqlite_plugin_get_closest(void *cls, const struct GNUNET_HashCode *key, unsigned int num_results, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
Iterate over the results that are "close" to a particular key in the datacache.
#define LOG_STRERROR_FILE(kind, op, fn)
#define LOG(kind,...)
void * libgnunet_plugin_datacache_sqlite_init(void *cls)
Entry point for the plugin.
void * cls
Closure for all of the callbacks.
The datastore service will pass a pointer to a struct of this type as the first and only argument to ...
GNUNET_DATACACHE_DeleteNotifyCallback delete_notify
Function to call whenever the plugin needs to discard content that it was asked to store.
void * cls
Closure to use for callbacks.
struct returned by the initialization function of the plugin
void * cls
Closure to pass to all plugin functions.
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
A 512-bit hashcode.
Description of a DB query parameter.
Definition: gnunet_sq_lib.h:55
Description of a DB result cell.
Time for absolute times used by GNUnet, in microseconds.
Handle for a plugin.
Definition: block.c:38
sqlite3 * dbh
Handle to the sqlite database.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
unsigned int num_items
Number of key-value pairs in the database.
sqlite3_stmt * get_stmt
Prepared statement for sqlite_plugin_get.
sqlite3_stmt * insert_stmt
Prepared statement for sqlite_plugin_put.
sqlite3_stmt * del_select_stmt
Prepared statement for sqlite_plugin_del.
sqlite3_stmt * get_count_stmt
Prepared statement for sqlite_plugin_get.
sqlite3_stmt * del_expired_stmt
Prepared statement for sqlite_plugin_del.
char * fn
Filename used for the DB.
sqlite3_stmt * get_closest_stmt
Prepared statement for sqlite_plugin_get_closest.
sqlite3_stmt * del_stmt
Prepared statement for sqlite_plugin_del.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
struct GNUNET_PQ_Context * dbh
Native Postgres database handle.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model