GNUnet  0.10.x
plugin_datastore_sqlite.c
Go to the documentation of this file.
1  /*
2  * This file is part of GNUnet
3  * Copyright (C) 2009, 2011, 2017 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 
27 #include "platform.h"
29 #include "gnunet_sq_lib.h"
30 #include <sqlite3.h>
31 
32 
38 #define MAX_ITEM_SIZE 65536
39 
50 #define BUSY_TIMEOUT_MS 250
51 
52 
58 #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
59 
60 
66 #define LOG_SQLITE_MSG(db, msg, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); GNUNET_asprintf(msg, _("`%s' failed at %s:%u with error: %s"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
67 
68 
69 
73 struct Plugin
74 {
79 
83  char *fn;
84 
88  sqlite3 *dbh;
89 
93  sqlite3_stmt *remove;
94 
98  sqlite3_stmt *delRow;
99 
103  sqlite3_stmt *update;
104 
108  sqlite3_stmt *maxRepl;
109 
113  sqlite3_stmt *updRepl;
114 
118  sqlite3_stmt *selRepl;
119 
123  sqlite3_stmt *selExpi;
124 
128  sqlite3_stmt *selZeroAnon;
129 
133  sqlite3_stmt *insertContent;
134 
138  sqlite3_stmt *get[8];
139 
144 
145 };
146 
147 
156 static int
157 sq_prepare (sqlite3 *dbh,
158  const char *zSql,
159  sqlite3_stmt **ppStmt)
160 {
161  char *dummy;
162  int result;
163 
164  result = sqlite3_prepare_v2 (dbh,
165  zSql,
166  strlen (zSql),
167  ppStmt,
168  (const char **) &dummy);
170  "sqlite",
171  "Prepared `%s' / %p: %d\n",
172  zSql,
173  *ppStmt,
174  result);
175  return result;
176 }
177 
178 
184 static void
185 create_indices (sqlite3 * dbh)
186 {
187  /* create indices */
188  if (0 !=
189  (SQLITE_OK !=
190  sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_hash ON gn091 (hash)",
191  NULL, NULL, NULL)) +
192  (SQLITE_OK !=
193  sqlite3_exec (dbh,
194  "CREATE INDEX IF NOT EXISTS idx_anon_type ON gn091 (anonLevel ASC,type)",
195  NULL, NULL, NULL)) +
196  (SQLITE_OK !=
197  sqlite3_exec (dbh,
198  "CREATE INDEX IF NOT EXISTS idx_expire ON gn091 (expire ASC)",
199  NULL, NULL, NULL)) +
200  (SQLITE_OK !=
201  sqlite3_exec (dbh,
202  "CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn091 (repl,rvalue)",
203  NULL, NULL, NULL)) )
205  "Failed to create indices: %s\n", sqlite3_errmsg (dbh));
206 }
207 
208 
209 #if 0
210 #define CHECK(a) GNUNET_break(a)
211 #define ENULL NULL
212 #else
213 #define ENULL &e
214 #define ENULL_DEFINED 1
215 #define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
216 #endif
217 
218 
228 static int
230  struct Plugin *plugin)
231 {
232  sqlite3_stmt *stmt;
233  char *afsdir;
234 #if ENULL_DEFINED
235  char *e;
236 #endif
237 
238  if (GNUNET_OK !=
240  "datastore-sqlite",
241  "FILENAME",
242  &afsdir))
243  {
245  "datastore-sqlite",
246  "FILENAME");
247  return GNUNET_SYSERR;
248  }
249  if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
250  {
251  if (GNUNET_OK !=
253  {
254  GNUNET_break (0);
255  GNUNET_free (afsdir);
256  return GNUNET_SYSERR;
257  }
258  /* database is new or got deleted, reset payload to zero! */
259  if (NULL != plugin->env->duc)
260  plugin->env->duc (plugin->env->cls,
261  0);
262  }
263  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
264  plugin->fn = afsdir;
265 
266  /* Open database and precompile statements */
267  if (SQLITE_OK !=
268  sqlite3_open (plugin->fn, &plugin->dbh))
269  {
271  _("Unable to initialize SQLite: %s.\n"),
272  sqlite3_errmsg (plugin->dbh));
273  return GNUNET_SYSERR;
274  }
275  CHECK (SQLITE_OK ==
276  sqlite3_exec (plugin->dbh,
277  "PRAGMA temp_store=MEMORY", NULL, NULL,
278  ENULL));
279  CHECK (SQLITE_OK ==
280  sqlite3_exec (plugin->dbh,
281  "PRAGMA synchronous=OFF", NULL, NULL,
282  ENULL));
283  CHECK (SQLITE_OK ==
284  sqlite3_exec (plugin->dbh,
285  "PRAGMA legacy_file_format=OFF", NULL, NULL,
286  ENULL));
287  CHECK (SQLITE_OK ==
288  sqlite3_exec (plugin->dbh,
289  "PRAGMA auto_vacuum=INCREMENTAL", NULL,
290  NULL, ENULL));
291  CHECK (SQLITE_OK ==
292  sqlite3_exec (plugin->dbh,
293  "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
294  ENULL));
295  CHECK (SQLITE_OK ==
296  sqlite3_exec (plugin->dbh,
297  "PRAGMA page_size=4096", NULL, NULL,
298  ENULL));
299 
300  CHECK (SQLITE_OK ==
301  sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS));
302 
303 
304  /* We have to do it here, because otherwise precompiling SQL might fail */
305  CHECK (SQLITE_OK ==
306  sq_prepare (plugin->dbh,
307  "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn091'",
308  &stmt));
309 
310  /* FIXME: SQLite does not have unsigned integers! This is ok for the type column because
311  * we only test equality on it and can cast it to/from uint32_t. For repl, prio, and anonLevel
312  * we do math or inequality tests, so we can't handle the entire range of uint32_t.
313  * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC.
314  */
315  if ( (SQLITE_DONE ==
316  sqlite3_step (stmt)) &&
317  (SQLITE_OK !=
318  sqlite3_exec (plugin->dbh,
319  "CREATE TABLE gn091 ("
320  " repl INT4 NOT NULL DEFAULT 0,"
321  " type INT4 NOT NULL DEFAULT 0,"
322  " prio INT4 NOT NULL DEFAULT 0,"
323  " anonLevel INT4 NOT NULL DEFAULT 0,"
324  " expire INT8 NOT NULL DEFAULT 0,"
325  " rvalue INT8 NOT NULL,"
326  " hash TEXT NOT NULL DEFAULT '',"
327  " vhash TEXT NOT NULL DEFAULT '',"
328  " value BLOB NOT NULL DEFAULT '')",
329  NULL,
330  NULL,
331  NULL)) )
332  {
333  LOG_SQLITE (plugin,
335  "sqlite3_exec");
336  sqlite3_finalize (stmt);
337  return GNUNET_SYSERR;
338  }
339  sqlite3_finalize (stmt);
340  create_indices (plugin->dbh);
341 
342 #define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, _ROWID_"
343  if ( (SQLITE_OK !=
344  sq_prepare (plugin->dbh,
345  "UPDATE gn091 "
346  "SET prio = prio + ?, "
347  "repl = repl + ?, "
348  "expire = MAX(expire, ?) "
349  "WHERE hash = ? AND vhash = ?",
350  &plugin->update)) ||
351  (SQLITE_OK !=
352  sq_prepare (plugin->dbh,
353  "UPDATE gn091 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?",
354  &plugin->updRepl)) ||
355  (SQLITE_OK !=
356  sq_prepare (plugin->dbh,
357  "SELECT " RESULT_COLUMNS " FROM gn091 "
358  "WHERE repl=?2 AND " " (rvalue>=?1 OR "
359  " NOT EXISTS (SELECT 1 FROM gn091 "
360  "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) "
361  "ORDER BY rvalue ASC LIMIT 1",
362  &plugin->selRepl)) ||
363  (SQLITE_OK !=
364  sq_prepare (plugin->dbh,
365  "SELECT MAX(repl) FROM gn091",
366  &plugin->maxRepl)) ||
367  (SQLITE_OK !=
368  sq_prepare (plugin->dbh,
369  "SELECT " RESULT_COLUMNS " FROM gn091 "
370  "WHERE NOT EXISTS (SELECT 1 FROM gn091 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) "
371  "ORDER BY expire ASC LIMIT 1",
372  &plugin->selExpi)) ||
373  (SQLITE_OK !=
374  sq_prepare (plugin->dbh,
375  "SELECT " RESULT_COLUMNS " FROM gn091 "
376  "WHERE _ROWID_ >= ? AND "
377  "anonLevel = 0 AND "
378  "type = ? "
379  "ORDER BY _ROWID_ ASC LIMIT 1",
380  &plugin->selZeroAnon)) ||
381  (SQLITE_OK !=
382  sq_prepare (plugin->dbh,
383  "INSERT INTO gn091 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) "
384  "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
385  &plugin->insertContent)) ||
386  (SQLITE_OK !=
387  sq_prepare (plugin->dbh,
388  "SELECT " RESULT_COLUMNS " FROM gn091 "
389  "WHERE _ROWID_ >= ?1 "
390  "ORDER BY _ROWID_ ASC LIMIT 1",
391  &plugin->get[0])) ||
392  (SQLITE_OK !=
393  sq_prepare (plugin->dbh,
394  "SELECT " RESULT_COLUMNS " FROM gn091 "
395  "WHERE _ROWID_ >= ?1 AND "
396  "type = ?4 "
397  "ORDER BY _ROWID_ ASC LIMIT 1",
398  &plugin->get[1])) ||
399  (SQLITE_OK !=
400  sq_prepare (plugin->dbh,
401  "SELECT " RESULT_COLUMNS " FROM gn091 "
402  "WHERE _ROWID_ >= ?1 AND "
403  "hash = ?3 "
404  "ORDER BY _ROWID_ ASC LIMIT 1",
405  &plugin->get[2])) ||
406  (SQLITE_OK !=
407  sq_prepare (plugin->dbh,
408  "SELECT " RESULT_COLUMNS " FROM gn091 "
409  "WHERE _ROWID_ >= ?1 AND "
410  "hash = ?3 AND "
411  "type = ?4 "
412  "ORDER BY _ROWID_ ASC LIMIT 1",
413  &plugin->get[3])) ||
414  (SQLITE_OK !=
415  sq_prepare (plugin->dbh,
416  "SELECT " RESULT_COLUMNS " FROM gn091 "
417  "WHERE _ROWID_ >= ?1 AND "
418  "rvalue >= ?2 "
419  "ORDER BY _ROWID_ ASC LIMIT 1",
420  &plugin->get[4])) ||
421  (SQLITE_OK !=
422  sq_prepare (plugin->dbh,
423  "SELECT " RESULT_COLUMNS " FROM gn091 "
424  "WHERE _ROWID_ >= ?1 AND "
425  "rvalue >= ?2 AND "
426  "type = ?4 "
427  "ORDER BY _ROWID_ ASC LIMIT 1",
428  &plugin->get[5])) ||
429  (SQLITE_OK !=
430  sq_prepare (plugin->dbh,
431  "SELECT " RESULT_COLUMNS " FROM gn091 "
432  "WHERE _ROWID_ >= ?1 AND "
433  "rvalue >= ?2 AND "
434  "hash = ?3 "
435  "ORDER BY _ROWID_ ASC LIMIT 1",
436  &plugin->get[6])) ||
437  (SQLITE_OK !=
438  sq_prepare (plugin->dbh,
439  "SELECT " RESULT_COLUMNS " FROM gn091 "
440  "WHERE _ROWID_ >= ?1 AND "
441  "rvalue >= ?2 AND "
442  "hash = ?3 AND "
443  "type = ?4 "
444  "ORDER BY _ROWID_ ASC LIMIT 1",
445  &plugin->get[7])) ||
446  (SQLITE_OK !=
447  sq_prepare (plugin->dbh,
448  "DELETE FROM gn091 WHERE _ROWID_ = ?",
449  &plugin->delRow)) ||
450  (SQLITE_OK !=
451  sq_prepare (plugin->dbh,
452  "DELETE FROM gn091 "
453  "WHERE hash = ? AND "
454  "value = ? ",
455  &plugin->remove)) ||
456  false)
457  {
458  LOG_SQLITE (plugin,
460  "precompiling");
461  return GNUNET_SYSERR;
462  }
463  return GNUNET_OK;
464 }
465 
466 
473 static void
475 {
476  int result;
477 #if SQLITE_VERSION_NUMBER >= 3007000
478  sqlite3_stmt *stmt;
479 #endif
480 
481  if (NULL != plugin->remove)
482  sqlite3_finalize (plugin->remove);
483  if (NULL != plugin->delRow)
484  sqlite3_finalize (plugin->delRow);
485  if (NULL != plugin->update)
486  sqlite3_finalize (plugin->update);
487  if (NULL != plugin->updRepl)
488  sqlite3_finalize (plugin->updRepl);
489  if (NULL != plugin->selRepl)
490  sqlite3_finalize (plugin->selRepl);
491  if (NULL != plugin->maxRepl)
492  sqlite3_finalize (plugin->maxRepl);
493  if (NULL != plugin->selExpi)
494  sqlite3_finalize (plugin->selExpi);
495  if (NULL != plugin->selZeroAnon)
496  sqlite3_finalize (plugin->selZeroAnon);
497  if (NULL != plugin->insertContent)
498  sqlite3_finalize (plugin->insertContent);
499  for (int i = 0; i < 8; ++i)
500  if (NULL != plugin->get[i])
501  sqlite3_finalize (plugin->get[i]);
502  result = sqlite3_close (plugin->dbh);
503 #if SQLITE_VERSION_NUMBER >= 3007000
504  if (result == SQLITE_BUSY)
505  {
507  "sqlite",
508  _("Tried to close sqlite without finalizing all prepared statements.\n"));
509  stmt = sqlite3_next_stmt (plugin->dbh,
510  NULL);
511  while (NULL != stmt)
512  {
514  "sqlite",
515  "Closing statement %p\n",
516  stmt);
517  result = sqlite3_finalize (stmt);
518  if (result != SQLITE_OK)
520  "sqlite",
521  "Failed to close statement %p: %d\n",
522  stmt,
523  result);
524  stmt = sqlite3_next_stmt (plugin->dbh,
525  NULL);
526  }
527  result = sqlite3_close (plugin->dbh);
528  }
529 #endif
530  if (SQLITE_OK != result)
531  LOG_SQLITE (plugin,
533  "sqlite3_close");
534  GNUNET_free_non_null (plugin->fn);
535 }
536 
537 
545 static int
547  uint64_t rid)
548 {
549  struct GNUNET_SQ_QueryParam params[] = {
552  };
553 
554  if (GNUNET_OK !=
555  GNUNET_SQ_bind (plugin->delRow,
556  params))
557  return GNUNET_SYSERR;
558  if (SQLITE_DONE != sqlite3_step (plugin->delRow))
559  {
561  "sqlite3_step");
562  GNUNET_SQ_reset (plugin->dbh,
563  plugin->delRow);
564  return GNUNET_SYSERR;
565  }
566  GNUNET_SQ_reset (plugin->dbh,
567  plugin->delRow);
568  return GNUNET_OK;
569 }
570 
571 
588 static void
589 sqlite_plugin_put (void *cls,
590  const struct GNUNET_HashCode *key,
591  bool absent,
592  uint32_t size,
593  const void *data,
594  enum GNUNET_BLOCK_Type type,
595  uint32_t priority,
596  uint32_t anonymity,
597  uint32_t replication,
599  PluginPutCont cont,
600  void *cont_cls)
601 {
602  struct Plugin *plugin = cls;
603  struct GNUNET_HashCode vhash;
604  char *msg = NULL;
605 
606  GNUNET_CRYPTO_hash (data,
607  size,
608  &vhash);
609 
610  if (!absent)
611  {
612  struct GNUNET_SQ_QueryParam params[] = {
613  GNUNET_SQ_query_param_uint32 (&priority),
614  GNUNET_SQ_query_param_uint32 (&replication),
619  };
620 
621  if (GNUNET_OK !=
622  GNUNET_SQ_bind (plugin->update,
623  params))
624  {
625  cont (cont_cls,
626  key,
627  size,
629  _("sqlite bind failure"));
630  return;
631  }
632  if (SQLITE_DONE != sqlite3_step (plugin->update))
633  {
635  "sqlite3_step");
636  cont (cont_cls,
637  key,
638  size,
640  msg);
641  GNUNET_free_non_null (msg);
642  return;
643  }
644  int changes = sqlite3_changes (plugin->dbh);
645  GNUNET_SQ_reset (plugin->dbh,
646  plugin->update);
647  if (0 != changes)
648  {
649  cont (cont_cls,
650  key,
651  size,
652  GNUNET_NO,
653  NULL);
654  return;
655  }
656  }
657 
658  uint64_t rvalue;
659  uint32_t type32 = (uint32_t) type;
660  struct GNUNET_SQ_QueryParam params[] = {
661  GNUNET_SQ_query_param_uint32 (&replication),
663  GNUNET_SQ_query_param_uint32 (&priority),
664  GNUNET_SQ_query_param_uint32 (&anonymity),
671  };
672  int n;
673  int ret;
674  sqlite3_stmt *stmt;
675 
676  if (size > MAX_ITEM_SIZE)
677  {
678  cont (cont_cls, key, size, GNUNET_SYSERR, _("Data too large"));
679  return;
680  }
682  "Storing in database block with type %u/key `%s'/priority %u/expiration in %s (%s).\n",
683  type,
684  GNUNET_h2s (key),
685  priority,
687  GNUNET_YES),
689  stmt = plugin->insertContent;
691  if (GNUNET_OK !=
692  GNUNET_SQ_bind (stmt,
693  params))
694  {
695  cont (cont_cls, key, size, GNUNET_SYSERR, NULL);
696  return;
697  }
698  n = sqlite3_step (stmt);
699  switch (n)
700  {
701  case SQLITE_DONE:
702  if (NULL != plugin->env->duc)
703  plugin->env->duc (plugin->env->cls,
706  "Stored new entry (%u bytes)\n",
708  ret = GNUNET_OK;
709  break;
710  case SQLITE_BUSY:
711  GNUNET_break (0);
712  LOG_SQLITE_MSG (plugin,
713  &msg,
715  "sqlite3_step");
716  ret = GNUNET_SYSERR;
717  break;
718  default:
719  LOG_SQLITE_MSG (plugin,
720  &msg,
722  "sqlite3_step");
723  GNUNET_SQ_reset (plugin->dbh,
724  stmt);
725  database_shutdown (plugin);
726  database_setup (plugin->env->cfg, plugin);
727  cont (cont_cls, key, size, GNUNET_SYSERR, msg);
729  return;
730  }
731  GNUNET_SQ_reset (plugin->dbh,
732  stmt);
733  cont (cont_cls, key, size, ret, msg);
735 }
736 
737 
747 static void
749  sqlite3_stmt *stmt,
751  void *proc_cls)
752 {
753  int n;
754  struct GNUNET_TIME_Absolute expiration;
755  uint32_t replication;
756  uint32_t type;
757  uint32_t priority;
758  uint32_t anonymity;
759  uint64_t rowid;
760  void *value;
761  size_t value_size;
762  struct GNUNET_HashCode key;
763  int ret;
764  struct GNUNET_SQ_ResultSpec rs[] = {
765  GNUNET_SQ_result_spec_uint32 (&replication),
767  GNUNET_SQ_result_spec_uint32 (&priority),
768  GNUNET_SQ_result_spec_uint32 (&anonymity),
772  &value_size),
775  };
776 
777  n = sqlite3_step (stmt);
778  switch (n)
779  {
780  case SQLITE_ROW:
781  if (GNUNET_OK !=
783  rs))
784  {
785  GNUNET_break (0);
786  break;
787  }
789  "sqlite",
790  "Found reply in database with expiration %s\n",
792  ret = proc (proc_cls,
793  &key,
794  value_size,
795  value,
796  type,
797  priority,
798  anonymity,
799  replication,
800  expiration,
801  rowid);
803  GNUNET_SQ_reset (plugin->dbh,
804  stmt);
805  if ( (GNUNET_NO == ret) &&
806  (GNUNET_OK == delete_by_rowid (plugin,
807  rowid)) &&
808  (NULL != plugin->env->duc) )
809  plugin->env->duc (plugin->env->cls,
810  -(value_size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
811  return;
812  case SQLITE_DONE:
813  /* database must be empty */
814  break;
815  case SQLITE_BUSY:
816  case SQLITE_ERROR:
817  case SQLITE_MISUSE:
818  default:
819  LOG_SQLITE (plugin,
821  "sqlite3_step");
822  if (SQLITE_OK !=
823  sqlite3_reset (stmt))
824  LOG_SQLITE (plugin,
826  "sqlite3_reset");
827  GNUNET_break (0);
828  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
829  database_shutdown (plugin);
830  database_setup (plugin->env->cfg,
831  plugin);
832  return;
833  }
834  GNUNET_SQ_reset (plugin->dbh,
835  stmt);
836  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
837 }
838 
839 
852 static void
854  uint64_t next_uid,
855  enum GNUNET_BLOCK_Type type,
857  void *proc_cls)
858 {
859  struct Plugin *plugin = cls;
860  uint32_t type32 = type;
861  struct GNUNET_SQ_QueryParam params[] = {
862  GNUNET_SQ_query_param_uint64 (&next_uid),
865  };
866 
868  if (GNUNET_OK !=
869  GNUNET_SQ_bind (plugin->selZeroAnon,
870  params))
871  {
872  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
873  return;
874  }
875  execute_get (plugin, plugin->selZeroAnon, proc, proc_cls);
876 }
877 
878 
892 static void
894  uint64_t next_uid,
895  bool random,
896  const struct GNUNET_HashCode *key,
897  enum GNUNET_BLOCK_Type type,
899  void *proc_cls)
900 {
901  struct Plugin *plugin = cls;
902  uint64_t rvalue;
903  int use_rvalue = random;
904  uint32_t type32 = (uint32_t) type;
905  int use_type = GNUNET_BLOCK_TYPE_ANY != type;
906  int use_key = NULL != key;
907  sqlite3_stmt *stmt = plugin->get[use_rvalue * 4 + use_key * 2 + use_type];
908  struct GNUNET_SQ_QueryParam params[] = {
909  GNUNET_SQ_query_param_uint64 (&next_uid),
914  };
915 
916  /* SQLite doesn't like it when you try to bind a parameter greater than the
917  * last numbered parameter, but unused parameters in the middle are OK.
918  */
919  if (! use_type)
920  {
921  params[3] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
922  if (! use_key)
923  {
924  params[2] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
925  if (! use_rvalue)
926  params[1] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
927  }
928  }
929  if (random)
930  {
932  UINT64_MAX);
933  next_uid = 0;
934  }
935  else
936  rvalue = 0;
937 
938  if (GNUNET_OK !=
939  GNUNET_SQ_bind (stmt,
940  params))
941  {
942  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
943  return;
944  }
945  execute_get (plugin,
946  stmt,
947  proc,
948  proc_cls);
949 }
950 
951 
955 struct ReplCtx
956 {
957 
962 
966  void *proc_cls;
967 
971  uint64_t uid;
972 
976  int have_uid;
977 };
978 
979 
999 static int
1000 repl_proc (void *cls,
1001  const struct GNUNET_HashCode *key,
1002  uint32_t size,
1003  const void *data,
1004  enum GNUNET_BLOCK_Type type,
1005  uint32_t priority,
1006  uint32_t anonymity,
1007  uint32_t replication,
1009  uint64_t uid)
1010 {
1011  struct ReplCtx *rc = cls;
1012  int ret;
1013 
1014  if (GNUNET_SYSERR == rc->have_uid)
1015  rc->have_uid = GNUNET_NO;
1016  ret = rc->proc (rc->proc_cls,
1017  key,
1018  size,
1019  data,
1020  type,
1021  priority,
1022  anonymity,
1023  replication,
1024  expiration,
1025  uid);
1026  if (NULL != key)
1027  {
1028  rc->uid = uid;
1029  rc->have_uid = GNUNET_YES;
1030  }
1031  return ret;
1032 }
1033 
1034 
1045 static void
1048  void *proc_cls)
1049 {
1050  struct Plugin *plugin = cls;
1051  struct ReplCtx rc;
1052  uint64_t rvalue;
1053  uint32_t repl;
1054  struct GNUNET_SQ_QueryParam params_sel_repl[] = {
1055  GNUNET_SQ_query_param_uint64 (&rvalue),
1058  };
1059  struct GNUNET_SQ_QueryParam params_upd_repl[] = {
1062  };
1063 
1065  "datastore-sqlite",
1066  "Getting random block based on replication order.\n");
1067  if (SQLITE_ROW !=
1068  sqlite3_step (plugin->maxRepl))
1069  {
1070  GNUNET_SQ_reset (plugin->dbh,
1071  plugin->maxRepl);
1072  /* DB empty */
1073  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1074  return;
1075  }
1076  repl = sqlite3_column_int (plugin->maxRepl,
1077  0);
1078  GNUNET_SQ_reset (plugin->dbh,
1079  plugin->maxRepl);
1081  UINT64_MAX);
1082  if (GNUNET_OK !=
1083  GNUNET_SQ_bind (plugin->selRepl,
1084  params_sel_repl))
1085  {
1086  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1087  return;
1088  }
1089  rc.have_uid = GNUNET_SYSERR;
1090  rc.proc = proc;
1091  rc.proc_cls = proc_cls;
1092  execute_get (plugin,
1093  plugin->selRepl,
1094  &repl_proc,
1095  &rc);
1096  if (GNUNET_YES == rc.have_uid)
1097  {
1098  if (GNUNET_OK !=
1099  GNUNET_SQ_bind (plugin->updRepl,
1100  params_upd_repl))
1101  {
1102  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1103  return;
1104  }
1105  if (SQLITE_DONE !=
1106  sqlite3_step (plugin->updRepl))
1107  LOG_SQLITE (plugin,
1109  "sqlite3_step");
1110  GNUNET_SQ_reset (plugin->dbh,
1111  plugin->updRepl);
1112  }
1113  if (GNUNET_SYSERR == rc.have_uid)
1114  {
1115  /* proc was not called at all so far, do it now. */
1116  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1117  }
1118 }
1119 
1120 
1129 static void
1131  void *proc_cls)
1132 {
1133  struct Plugin *plugin = cls;
1134  sqlite3_stmt *stmt;
1135  struct GNUNET_TIME_Absolute now;
1136  struct GNUNET_SQ_QueryParam params[] = {
1139  };
1140 
1142  "sqlite",
1143  "Getting random block based on expiration and priority order.\n");
1144  now = GNUNET_TIME_absolute_get ();
1145  stmt = plugin->selExpi;
1146  if (GNUNET_OK !=
1147  GNUNET_SQ_bind (stmt,
1148  params))
1149  {
1150  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1151  return;
1152  }
1153  execute_get (plugin, stmt, proc, proc_cls);
1154 }
1155 
1156 
1164 static void
1166  PluginKeyProcessor proc,
1167  void *proc_cls)
1168 {
1169  struct Plugin *plugin = cls;
1170  struct GNUNET_HashCode key;
1171  struct GNUNET_SQ_ResultSpec results[] = {
1174  };
1175  sqlite3_stmt *stmt;
1176  int ret;
1177 
1178  GNUNET_assert (NULL != proc);
1179  if (SQLITE_OK !=
1180  sq_prepare (plugin->dbh,
1181  "SELECT hash FROM gn091",
1182  &stmt))
1183  {
1184  LOG_SQLITE (plugin,
1186  "sqlite_prepare");
1187  proc (proc_cls,
1188  NULL,
1189  0);
1190  return;
1191  }
1192  while (SQLITE_ROW == (ret = sqlite3_step (stmt)))
1193  {
1194  if (GNUNET_OK ==
1196  results))
1197  proc (proc_cls,
1198  &key,
1199  1);
1200  else
1201  GNUNET_break (0);
1202  }
1203  if (SQLITE_DONE != ret)
1204  LOG_SQLITE (plugin,
1206  "sqlite_step");
1207  sqlite3_finalize (stmt);
1208  proc (proc_cls,
1209  NULL,
1210  0);
1211 }
1212 
1213 
1219 static void
1221 {
1222  struct Plugin *plugin = cls;
1223 
1224  plugin->drop_on_shutdown = GNUNET_YES;
1225 }
1226 
1227 
1238 static void
1240  const struct GNUNET_HashCode *key,
1241  uint32_t size,
1242  const void *data,
1243  PluginRemoveCont cont,
1244  void *cont_cls)
1245 {
1246  struct Plugin *plugin = cls;
1247  struct GNUNET_SQ_QueryParam params[] = {
1249  GNUNET_SQ_query_param_fixed_size (data, size),
1251  };
1252 
1253  if (GNUNET_OK !=
1254  GNUNET_SQ_bind (plugin->remove,
1255  params))
1256  {
1257  cont (cont_cls,
1258  key,
1259  size,
1260  GNUNET_SYSERR,
1261  "bind failed");
1262  return;
1263  }
1264  if (SQLITE_DONE != sqlite3_step (plugin->remove))
1265  {
1266  LOG_SQLITE (plugin,
1268  "sqlite3_step");
1269  GNUNET_SQ_reset (plugin->dbh,
1270  plugin->remove);
1271  cont (cont_cls,
1272  key,
1273  size,
1274  GNUNET_SYSERR,
1275  "sqlite3_step failed");
1276  return;
1277  }
1278  int changes = sqlite3_changes (plugin->dbh);
1279  GNUNET_SQ_reset (plugin->dbh,
1280  plugin->remove);
1281  if (0 == changes)
1282  {
1283  cont (cont_cls,
1284  key,
1285  size,
1286  GNUNET_NO,
1287  NULL);
1288  return;
1289  }
1290  if (NULL != plugin->env->duc)
1291  plugin->env->duc (plugin->env->cls,
1293  cont (cont_cls,
1294  key,
1295  size,
1296  GNUNET_OK,
1297  NULL);
1298 }
1299 
1300 
1308 static void
1310  unsigned long long *estimate)
1311 {
1312  struct Plugin *plugin = cls;
1313  sqlite3_stmt *stmt;
1314  uint64_t pages;
1315  uint64_t page_size;
1316 
1317 #if ENULL_DEFINED
1318  char *e;
1319 #endif
1320 
1321  if (NULL == estimate)
1322  return;
1323  if (SQLITE_VERSION_NUMBER < 3006000)
1324  {
1326  "datastore-sqlite",
1327  _("sqlite version to old to determine size, assuming zero\n"));
1328  *estimate = 0;
1329  return;
1330  }
1331  CHECK (SQLITE_OK ==
1332  sqlite3_exec (plugin->dbh,
1333  "VACUUM",
1334  NULL,
1335  NULL,
1336  ENULL));
1337  CHECK (SQLITE_OK ==
1338  sqlite3_exec (plugin->dbh,
1339  "PRAGMA auto_vacuum=INCREMENTAL",
1340  NULL,
1341  NULL, ENULL));
1342  CHECK (SQLITE_OK ==
1343  sq_prepare (plugin->dbh,
1344  "PRAGMA page_count",
1345  &stmt));
1346  if (SQLITE_ROW == sqlite3_step (stmt))
1347  pages = sqlite3_column_int64 (stmt,
1348  0);
1349  else
1350  pages = 0;
1351  sqlite3_finalize (stmt);
1352  CHECK (SQLITE_OK ==
1353  sq_prepare (plugin->dbh,
1354  "PRAGMA page_size",
1355  &stmt));
1356  CHECK (SQLITE_ROW ==
1357  sqlite3_step (stmt));
1358  page_size = sqlite3_column_int64 (stmt, 0);
1359  sqlite3_finalize (stmt);
1361  _("Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"),
1362  (unsigned long long) pages,
1363  (unsigned long long) page_size);
1364  *estimate = pages * page_size;
1365 }
1366 
1367 
1374 void *
1376 {
1377  static struct Plugin plugin;
1380 
1381  if (NULL != plugin.env)
1382  return NULL; /* can only initialize once! */
1383  memset (&plugin,
1384  0,
1385  sizeof (struct Plugin));
1386  plugin.env = env;
1387  if (GNUNET_OK != database_setup (env->cfg, &plugin))
1388  {
1389  database_shutdown (&plugin);
1390  return NULL;
1391  }
1393  api->cls = &plugin;
1395  api->put = &sqlite_plugin_put;
1401  api->drop = &sqlite_plugin_drop;
1404  "sqlite",
1405  _("Sqlite database running\n"));
1406  return api;
1407 }
1408 
1409 
1416 void *
1418 {
1419  char *fn;
1421  struct Plugin *plugin = api->cls;
1422 
1424  "sqlite",
1425  "sqlite plugin is done\n");
1426  fn = NULL;
1427  if (plugin->drop_on_shutdown)
1428  fn = GNUNET_strdup (plugin->fn);
1429  database_shutdown (plugin);
1430  plugin->env = NULL;
1431  GNUNET_free (api);
1432  if (NULL != fn)
1433  {
1434  if (0 != UNLINK (fn))
1436  "unlink",
1437  fn);
1438  GNUNET_free (fn);
1439  }
1440  return NULL;
1441 }
1442 
1443 /* end of plugin_datastore_sqlite.c */
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:669
PluginGetKeys get_keys
Iterate over all keys in the database.
PluginPut put
Function to store an item in the datastore.
static int database_setup(const struct GNUNET_CONFIGURATION_Handle *cfg, struct Plugin *plugin)
Initialize the database connections and associated data structures (create tables and indices as need...
int(* PluginDatumProcessor)(void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
An processor over a set of items stored in the datastore.
void * proc_cls
Closure for proc.
PluginGetType get_zero_anonymity
Get datum (of the specified type) with anonymity level zero.
static void sqlite_plugin_put(void *cls, const struct GNUNET_HashCode *key, bool absent, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, PluginPutCont cont, void *cont_cls)
Store an item in the datastore.
Description of a DB result cell.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define BUSY_TIMEOUT_MS
After how many ms "busy" should a DB operation fail for good? A low value makes sure that we are more...
static char * expiration
Credential TTL.
sqlite3_stmt * update
Precompiled SQL for update.
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_uint32(uint32_t *u32)
uint32_t expected.
static struct in_addr dummy
Target "dummy" address.
int have_uid
Yes if UID was set.
Any type of block, used as a wildcard when searching.
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
sqlite3_stmt * updRepl
Precompiled SQL for replication decrement.
static int sq_prepare(sqlite3 *dbh, const char *zSql, sqlite3_stmt **ppStmt)
Prepare a SQL statement.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_SQ_query_param_auto_from_type(x)
Generate fixed-size query parameter with size determined by variable type.
PluginRemoveKey remove_key
Function to remove an item from the database.
char * key
TLS key.
sqlite3_stmt * delRow
Precompiled SQL for deletion.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static unsigned int replication
PluginEstimateSize estimate_size
Calculate the current on-disk size of the SQ store.
static struct Experiment * e
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:833
#define GNUNET_SQ_result_spec_end
End of result parameter specification.
#define GNUNET_NO
Definition: gnunet_common.h:81
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define RESULT_COLUMNS
#define GNUNET_SQ_result_spec_auto_from_type(dst)
We expect a fixed-size result, with size determined by the type of * dst
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define CHECK(a)
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
void(* PluginPutCont)(void *cls, const struct GNUNET_HashCode *key, uint32_t size, int status, const char *msg)
Put continuation.
static void sqlite_plugin_get_replication(void *cls, PluginDatumProcessor proc, void *proc_cls)
Get a random item for replication.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void * libgnunet_plugin_datastore_sqlite_init(void *cls)
Entry point for the plugin.
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_absolute_time(struct GNUNET_TIME_Absolute *at)
Absolute time expected.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
#define LOG_SQLITE_MSG(db, msg, level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; on file &#39;file...
sqlite3_stmt * insertContent
Precompiled SQL for insertion.
#define UNLINK(f)
Definition: plibc.h:666
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
sqlite3_stmt * get[8]
Precompiled SQL for selection.
static void sqlite_plugin_get_keys(void *cls, PluginKeyProcessor proc, void *proc_cls)
Get all of the keys in the datastore.
int 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
PluginGetRandom get_replication
Function to get a random item with high replication score from the database, lowering the item&#39;s repl...
static void database_shutdown(struct Plugin *plugin)
Shutdown database connection and associate data structures.
PluginDrop drop
Delete the database.
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint32(const uint32_t *x)
Generate query parameter for an uint32_t in host byte order.
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
void * cls
Closure for conv and cleaner.
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
static int repl_proc(void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
Wrapper for the processor for sqlite_plugin_get_replication().
static void sqlite_plugin_drop(void *cls)
Drop database.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
void(* PluginKeyProcessor)(void *cls, const struct GNUNET_HashCode *key, unsigned int count)
An processor over a set of keys stored in the datastore.
int drop_on_shutdown
Should the database be dropped on shutdown?
PluginGetRandom get_expiration
Function to get a random expired item or, if none are expired, either the oldest entry or one with a ...
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
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:727
sqlite3_stmt * selZeroAnon
Precompiled SQL for expiration selection.
#define MAX_ITEM_SIZE
We allocate items on the stack at times.
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_variable_size(void **dst, size_t *sptr)
Variable-size result expected.
static int result
Global testing status.
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_absolute_time(const struct GNUNET_TIME_Absolute *x)
Generate query parameter for an absolute time value.
The datastore service will pass a pointer to a struct of this type as the first and only argument to ...
A 512-bit hashcode.
sqlite3_stmt * selRepl
Precompiled SQL for replication selection.
#define GNUNET_DATASTORE_ENTRY_OVERHEAD
How many bytes of overhead will we assume per entry in any DB (for reservations)? ...
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_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
uint64_t uid
UID to use.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
Context for repl_proc() function.
sqlite3_stmt * remove
Precompiled SQL for remove_key.
static void sqlite_plugin_estimate_size(void *cls, unsigned long long *estimate)
Get an estimate of how much space the database is currently using.
helper functions for Sqlite3 DB interactions
void(* PluginRemoveCont)(void *cls, const struct GNUNET_HashCode *key, uint32_t size, int status, const char *msg)
Remove continuation.
#define LOG_SQLITE(db, level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; on file &#39;file...
Description of a DB query parameter.
Definition: gnunet_sq_lib.h:54
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_uint64(uint64_t *u64)
uint64_t expected.
#define ENULL
static void create_indices(sqlite3 *dbh)
Create our database indices.
void * cls
Closure to use for all of the following callbacks (except "next_request").
char * fn
Filename used for the DB.
void GNUNET_SQ_reset(sqlite3 *dbh, sqlite3_stmt *stmt)
Reset stmt and log error.
Definition: sq.c:132
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint64(const uint64_t *x)
Generate query parameter for an uint16_t in host byte order.
unsigned long long size
Size of all values we&#39;re storing.
configuration data
Definition: configuration.c:85
Handle for a plugin.
Definition: block.c:37
PGconn * dbh
Native Postgres database handle.
static void sqlite_plugin_get_zero_anonymity(void *cls, uint64_t next_uid, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls)
Select a subset of the items in the datastore and call the given processor for the item...
PluginDatumProcessor proc
Function to call for the result (or the NULL).
static void sqlite_plugin_get_expiration(void *cls, PluginDatumProcessor proc, void *proc_cls)
Get a random item that has expired or has low priority.
#define GNUNET_log(kind,...)
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
static int delete_by_rowid(struct Plugin *plugin, uint64_t rid)
Delete the database entry with the given row identifier.
sqlite3_stmt * maxRepl
Get maximum repl value in database.
sqlite3_stmt * selExpi
Precompiled SQL for expiration selection.
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:331
void * cls
Closure to use for callbacks.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
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.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
static unsigned int anonymity
static void execute_get(struct Plugin *plugin, sqlite3_stmt *stmt, PluginDatumProcessor proc, void *proc_cls)
Execute statement that gets a row and call the callback with the result.
#define GNUNET_SQ_query_param_end
End of query parameter specification.
Definition: gnunet_sq_lib.h:87
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:792
#define GNUNET_log_from(kind, comp,...)
PluginGetKey get_key
Get a particular datum matching a given hash from the datastore.
uint32_t data
The data value.
static void sqlite_plugin_get_key(void *cls, uint64_t next_uid, bool random, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls)
Get results for a particular key in the datastore.
void * libgnunet_plugin_datastore_sqlite_done(void *cls)
Exit point from the plugin.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
static void sqlite_plugin_remove_key(void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, PluginRemoveCont cont, void *cont_cls)
Remove a particular key in the datastore.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
#define GNUNET_free(ptr)
Wrapper around free.