GNUnet  0.11.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) \
59  do \
60  { \
61  GNUNET_log_from (level, \
62  "sqlite", \
63  _ ("`%s' failed at %s:%d with error: %s\n"), \
64  cmd, \
65  __FILE__, \
66  __LINE__, \
67  sqlite3_errmsg (db->dbh)); \
68  } while (0)
69 
70 
76 #define LOG_SQLITE_MSG(db, msg, level, cmd) \
77  do \
78  { \
79  GNUNET_log_from (level, \
80  "sqlite", \
81  _ ("`%s' failed at %s:%d with error: %s\n"), \
82  cmd, \
83  __FILE__, \
84  __LINE__, \
85  sqlite3_errmsg (db->dbh)); \
86  GNUNET_asprintf (msg, \
87  _ ("`%s' failed at %s:%u with error: %s"), \
88  cmd, \
89  __FILE__, \
90  __LINE__, \
91  sqlite3_errmsg (db->dbh)); \
92  } while (0)
93 
94 
98 struct Plugin
99 {
104 
108  char *fn;
109 
113  sqlite3 *dbh;
114 
118  sqlite3_stmt *remove;
119 
123  sqlite3_stmt *delRow;
124 
128  sqlite3_stmt *update;
129 
133  sqlite3_stmt *maxRepl;
134 
138  sqlite3_stmt *updRepl;
139 
143  sqlite3_stmt *selRepl;
144 
148  sqlite3_stmt *selExpi;
149 
153  sqlite3_stmt *selZeroAnon;
154 
158  sqlite3_stmt *insertContent;
159 
163  sqlite3_stmt *get[8];
164 
169 };
170 
171 
180 static int
181 sq_prepare (sqlite3 *dbh, const char *zSql, sqlite3_stmt **ppStmt)
182 {
183  char *dummy;
184  int result;
185 
186  result = sqlite3_prepare_v2 (dbh,
187  zSql,
188  strlen (zSql),
189  ppStmt,
190  (const char **) &dummy);
192  "sqlite",
193  "Prepared `%s' / %p: %d\n",
194  zSql,
195  *ppStmt,
196  result);
197  return result;
198 }
199 
200 
206 static void
207 create_indices (sqlite3 *dbh)
208 {
209  /* create indices */
210  if (
211  0 !=
212  (SQLITE_OK !=
213  sqlite3_exec (dbh,
214  "CREATE INDEX IF NOT EXISTS idx_hash ON gn091 (hash)",
215  NULL,
216  NULL,
217  NULL))
218  + (SQLITE_OK !=
219  sqlite3_exec (
220  dbh,
221  "CREATE INDEX IF NOT EXISTS idx_anon_type ON gn091 (anonLevel ASC,type)",
222  NULL,
223  NULL,
224  NULL))
225  + (SQLITE_OK !=
226  sqlite3_exec (dbh,
227  "CREATE INDEX IF NOT EXISTS idx_expire ON gn091 (expire ASC)",
228  NULL,
229  NULL,
230  NULL))
231  + (SQLITE_OK !=
232  sqlite3_exec (
233  dbh,
234  "CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn091 (repl,rvalue)",
235  NULL,
236  NULL,
237  NULL)))
239  "sqlite",
240  "Failed to create indices: %s\n",
241  sqlite3_errmsg (dbh));
242 }
243 
244 
245 #if 0
246 #define CHECK(a) GNUNET_break (a)
247 #define ENULL NULL
248 #else
249 #define ENULL &e
250 #define ENULL_DEFINED 1
251 #define CHECK(a) \
252  if (! (a)) \
253  { \
254  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", e); \
255  sqlite3_free (e); \
256  }
257 #endif
258 
259 
269 static int
271  struct Plugin *plugin)
272 {
273  sqlite3_stmt *stmt;
274  char *afsdir;
275 
276 #if ENULL_DEFINED
277  char *e;
278 #endif
279 
281  "datastore-sqlite",
282  "FILENAME",
283  &afsdir))
284  {
286  "datastore-sqlite",
287  "FILENAME");
288  return GNUNET_SYSERR;
289  }
290  if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
291  {
293  {
294  GNUNET_break (0);
295  GNUNET_free (afsdir);
296  return GNUNET_SYSERR;
297  }
298  /* database is new or got deleted, reset payload to zero! */
299  if (NULL != plugin->env->duc)
300  plugin->env->duc (plugin->env->cls, 0);
301  }
302  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
303  plugin->fn = afsdir;
304 
305  /* Open database and precompile statements */
306  if (SQLITE_OK != sqlite3_open (plugin->fn, &plugin->dbh))
307  {
309  "sqlite",
310  _ ("Unable to initialize SQLite: %s.\n"),
311  sqlite3_errmsg (plugin->dbh));
312  return GNUNET_SYSERR;
313  }
314  CHECK (
315  SQLITE_OK ==
316  sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL, ENULL));
317  CHECK (
318  SQLITE_OK ==
319  sqlite3_exec (plugin->dbh, "PRAGMA synchronous=OFF", NULL, NULL, ENULL));
320  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
321  "PRAGMA legacy_file_format=OFF",
322  NULL,
323  NULL,
324  ENULL));
325  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
326  "PRAGMA auto_vacuum=INCREMENTAL",
327  NULL,
328  NULL,
329  ENULL));
330  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
331  "PRAGMA locking_mode=EXCLUSIVE",
332  NULL,
333  NULL,
334  ENULL));
335  CHECK (
336  SQLITE_OK ==
337  sqlite3_exec (plugin->dbh, "PRAGMA page_size=4096", NULL, NULL, ENULL));
338 
339  CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS));
340 
341 
342  /* We have to do it here, because otherwise precompiling SQL might fail */
343  CHECK (SQLITE_OK ==
344  sq_prepare (plugin->dbh,
345  "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn091'",
346  &stmt));
347 
348  /* FIXME: SQLite does not have unsigned integers! This is ok for the type column because
349  * we only test equality on it and can cast it to/from uint32_t. For repl, prio, and anonLevel
350  * we do math or inequality tests, so we can't handle the entire range of uint32_t.
351  * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC.
352  */if ((SQLITE_DONE == sqlite3_step (stmt)) &&
353  (SQLITE_OK != sqlite3_exec (plugin->dbh,
354  "CREATE TABLE gn091 ("
355  " repl INT4 NOT NULL DEFAULT 0,"
356  " type INT4 NOT NULL DEFAULT 0,"
357  " prio INT4 NOT NULL DEFAULT 0,"
358  " anonLevel INT4 NOT NULL DEFAULT 0,"
359  " expire INT8 NOT NULL DEFAULT 0,"
360  " rvalue INT8 NOT NULL,"
361  " hash TEXT NOT NULL DEFAULT '',"
362  " vhash TEXT NOT NULL DEFAULT '',"
363  " value BLOB NOT NULL DEFAULT '')",
364  NULL,
365  NULL,
366  NULL)))
367  {
368  LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec");
369  sqlite3_finalize (stmt);
370  return GNUNET_SYSERR;
371  }
372  sqlite3_finalize (stmt);
373  create_indices (plugin->dbh);
374 
375 #define RESULT_COLUMNS \
376  "repl, type, prio, anonLevel, expire, hash, value, _ROWID_"
377  if (
378  (SQLITE_OK != sq_prepare (plugin->dbh,
379  "UPDATE gn091 "
380  "SET prio = prio + ?, "
381  "repl = repl + ?, "
382  "expire = MAX(expire, ?) "
383  "WHERE hash = ? AND vhash = ?",
384  &plugin->update)) ||
385  (SQLITE_OK != sq_prepare (plugin->dbh,
386  "UPDATE gn091 "
387  "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?",
388  &plugin->updRepl)) ||
389  (SQLITE_OK != sq_prepare (plugin->dbh,
390  "SELECT " RESULT_COLUMNS " FROM gn091 "
391  "WHERE repl=?2 AND "
392  " (rvalue>=?1 OR "
393  " NOT EXISTS (SELECT 1 FROM gn091 "
394  "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) "
395  "ORDER BY rvalue ASC LIMIT 1",
396  &plugin->selRepl)) ||
397  (SQLITE_OK != sq_prepare (plugin->dbh,
398  "SELECT MAX(repl) FROM gn091",
399  &plugin->maxRepl)) ||
400  (SQLITE_OK !=
401  sq_prepare (plugin->dbh,
402  "SELECT " RESULT_COLUMNS " FROM gn091 "
403  "WHERE NOT EXISTS (SELECT 1 FROM gn091 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) "
404  "ORDER BY expire ASC LIMIT 1",
405  &plugin->selExpi)) ||
406  (SQLITE_OK != sq_prepare (plugin->dbh,
407  "SELECT " RESULT_COLUMNS " FROM gn091 "
408  "WHERE _ROWID_ >= ? AND "
409  "anonLevel = 0 AND "
410  "type = ? "
411  "ORDER BY _ROWID_ ASC LIMIT 1",
412  &plugin->selZeroAnon)) ||
413  (SQLITE_OK !=
414  sq_prepare (plugin->dbh,
415  "INSERT INTO gn091 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) "
416  "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
417  &plugin->insertContent)) ||
418  (SQLITE_OK != sq_prepare (plugin->dbh,
419  "SELECT " RESULT_COLUMNS " FROM gn091 "
420  "WHERE _ROWID_ >= ?1 "
421  "ORDER BY _ROWID_ ASC LIMIT 1",
422  &plugin->get[0])) ||
423  (SQLITE_OK != sq_prepare (plugin->dbh,
424  "SELECT " RESULT_COLUMNS " FROM gn091 "
425  "WHERE _ROWID_ >= ?1 AND "
426  "type = ?4 "
427  "ORDER BY _ROWID_ ASC LIMIT 1",
428  &plugin->get[1])) ||
429  (SQLITE_OK != sq_prepare (plugin->dbh,
430  "SELECT " RESULT_COLUMNS " FROM gn091 "
431  "WHERE _ROWID_ >= ?1 AND "
432  "hash = ?3 "
433  "ORDER BY _ROWID_ ASC LIMIT 1",
434  &plugin->get[2])) ||
435  (SQLITE_OK != sq_prepare (plugin->dbh,
436  "SELECT " RESULT_COLUMNS " FROM gn091 "
437  "WHERE _ROWID_ >= ?1 AND "
438  "hash = ?3 AND "
439  "type = ?4 "
440  "ORDER BY _ROWID_ ASC LIMIT 1",
441  &plugin->get[3])) ||
442  (SQLITE_OK != sq_prepare (plugin->dbh,
443  "SELECT " RESULT_COLUMNS " FROM gn091 "
444  "WHERE _ROWID_ >= ?1 AND "
445  "rvalue >= ?2 "
446  "ORDER BY _ROWID_ ASC LIMIT 1",
447  &plugin->get[4])) ||
448  (SQLITE_OK != sq_prepare (plugin->dbh,
449  "SELECT " RESULT_COLUMNS " FROM gn091 "
450  "WHERE _ROWID_ >= ?1 AND "
451  "rvalue >= ?2 AND "
452  "type = ?4 "
453  "ORDER BY _ROWID_ ASC LIMIT 1",
454  &plugin->get[5])) ||
455  (SQLITE_OK != sq_prepare (plugin->dbh,
456  "SELECT " RESULT_COLUMNS " FROM gn091 "
457  "WHERE _ROWID_ >= ?1 AND "
458  "rvalue >= ?2 AND "
459  "hash = ?3 "
460  "ORDER BY _ROWID_ ASC LIMIT 1",
461  &plugin->get[6])) ||
462  (SQLITE_OK != sq_prepare (plugin->dbh,
463  "SELECT " RESULT_COLUMNS " FROM gn091 "
464  "WHERE _ROWID_ >= ?1 AND "
465  "rvalue >= ?2 AND "
466  "hash = ?3 AND "
467  "type = ?4 "
468  "ORDER BY _ROWID_ ASC LIMIT 1",
469  &plugin->get[7])) ||
470  (SQLITE_OK != sq_prepare (plugin->dbh,
471  "DELETE FROM gn091 WHERE _ROWID_ = ?",
472  &plugin->delRow)) ||
473  (SQLITE_OK != sq_prepare (plugin->dbh,
474  "DELETE FROM gn091 "
475  "WHERE hash = ? AND "
476  "value = ? ",
477  &plugin->remove)) ||
478  false)
479  {
480  LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "precompiling");
481  return GNUNET_SYSERR;
482  }
483  return GNUNET_OK;
484 }
485 
486 
493 static void
495 {
496  int result;
497 
498 #if SQLITE_VERSION_NUMBER >= 3007000
499  sqlite3_stmt *stmt;
500 #endif
501 
502  if (NULL != plugin->remove)
503  sqlite3_finalize (plugin->remove);
504  if (NULL != plugin->delRow)
505  sqlite3_finalize (plugin->delRow);
506  if (NULL != plugin->update)
507  sqlite3_finalize (plugin->update);
508  if (NULL != plugin->updRepl)
509  sqlite3_finalize (plugin->updRepl);
510  if (NULL != plugin->selRepl)
511  sqlite3_finalize (plugin->selRepl);
512  if (NULL != plugin->maxRepl)
513  sqlite3_finalize (plugin->maxRepl);
514  if (NULL != plugin->selExpi)
515  sqlite3_finalize (plugin->selExpi);
516  if (NULL != plugin->selZeroAnon)
517  sqlite3_finalize (plugin->selZeroAnon);
518  if (NULL != plugin->insertContent)
519  sqlite3_finalize (plugin->insertContent);
520  for (int i = 0; i < 8; ++i)
521  if (NULL != plugin->get[i])
522  sqlite3_finalize (plugin->get[i]);
523  result = sqlite3_close (plugin->dbh);
524 #if SQLITE_VERSION_NUMBER >= 3007000
525  if (result == SQLITE_BUSY)
526  {
529  "sqlite",
530  _ (
531  "Tried to close sqlite without finalizing all prepared statements.\n"));
532  stmt = sqlite3_next_stmt (plugin->dbh, NULL);
533  while (NULL != stmt)
534  {
536  "sqlite",
537  "Closing statement %p\n",
538  stmt);
539  result = sqlite3_finalize (stmt);
540  if (result != SQLITE_OK)
542  "sqlite",
543  "Failed to close statement %p: %d\n",
544  stmt,
545  result);
546  stmt = sqlite3_next_stmt (plugin->dbh, NULL);
547  }
548  result = sqlite3_close (plugin->dbh);
549  }
550 #endif
551  if (SQLITE_OK != result)
552  LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
553  GNUNET_free_non_null (plugin->fn);
554 }
555 
556 
564 static int
565 delete_by_rowid (struct Plugin *plugin, uint64_t rid)
566 {
567  struct GNUNET_SQ_QueryParam params[] = { GNUNET_SQ_query_param_uint64 (&rid),
569 
570  if (GNUNET_OK != GNUNET_SQ_bind (plugin->delRow, params))
571  return GNUNET_SYSERR;
572  if (SQLITE_DONE != sqlite3_step (plugin->delRow))
573  {
574  LOG_SQLITE (plugin,
576  "sqlite3_step");
577  GNUNET_SQ_reset (plugin->dbh, plugin->delRow);
578  return GNUNET_SYSERR;
579  }
580  GNUNET_SQ_reset (plugin->dbh, plugin->delRow);
581  return GNUNET_OK;
582 }
583 
584 
601 static void
602 sqlite_plugin_put (void *cls,
603  const struct GNUNET_HashCode *key,
604  bool absent,
605  uint32_t size,
606  const void *data,
607  enum GNUNET_BLOCK_Type type,
608  uint32_t priority,
609  uint32_t anonymity,
610  uint32_t replication,
612  PluginPutCont cont,
613  void *cont_cls)
614 {
615  struct Plugin *plugin = cls;
616  struct GNUNET_HashCode vhash;
617  char *msg = NULL;
618 
619  GNUNET_CRYPTO_hash (data, size, &vhash);
620 
621  if (! absent)
622  {
623  struct GNUNET_SQ_QueryParam params[] =
624  { GNUNET_SQ_query_param_uint32 (&priority),
625  GNUNET_SQ_query_param_uint32 (&replication),
630 
631  if (GNUNET_OK != GNUNET_SQ_bind (plugin->update, params))
632  {
633  cont (cont_cls, key, size, GNUNET_SYSERR, _ ("sqlite bind failure"));
634  return;
635  }
636  if (SQLITE_DONE != sqlite3_step (plugin->update))
637  {
638  LOG_SQLITE_MSG (plugin,
639  &msg,
641  "sqlite3_step");
642  cont (cont_cls, key, size, GNUNET_SYSERR, msg);
643  GNUNET_free_non_null (msg);
644  return;
645  }
646  int changes = sqlite3_changes (plugin->dbh);
647  GNUNET_SQ_reset (plugin->dbh, plugin->update);
648  if (0 != changes)
649  {
650  cont (cont_cls, key, size, GNUNET_NO, NULL);
651  return;
652  }
653  }
654 
655  uint64_t rvalue;
656  uint32_t type32 = (uint32_t) type;
657  struct GNUNET_SQ_QueryParam params[] =
658  { GNUNET_SQ_query_param_uint32 (&replication),
660  GNUNET_SQ_query_param_uint32 (&priority),
661  GNUNET_SQ_query_param_uint32 (&anonymity),
668  int n;
669  int ret;
670  sqlite3_stmt *stmt;
671 
672  if (size > MAX_ITEM_SIZE)
673  {
674  cont (cont_cls, key, size, GNUNET_SYSERR, _ ("Data too large"));
675  return;
676  }
679  "sqlite",
680  "Storing in database block with type %u/key `%s'/priority %u/expiration in %s (%s).\n",
681  type,
682  GNUNET_h2s (key),
683  priority,
685  expiration),
686  GNUNET_YES),
688  stmt = plugin->insertContent;
690  if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
691  {
692  cont (cont_cls, key, size, GNUNET_SYSERR, NULL);
693  return;
694  }
695  n = sqlite3_step (stmt);
696  switch (n)
697  {
698  case SQLITE_DONE:
699  if (NULL != plugin->env->duc)
700  plugin->env->duc (plugin->env->cls,
703  "sqlite",
704  "Stored new entry (%u bytes)\n",
706  ret = GNUNET_OK;
707  break;
708 
709  case SQLITE_BUSY:
710  GNUNET_break (0);
711  LOG_SQLITE_MSG (plugin,
712  &msg,
714  "sqlite3_step");
715  ret = GNUNET_SYSERR;
716  break;
717 
718  default:
719  LOG_SQLITE_MSG (plugin,
720  &msg,
722  "sqlite3_step");
723  GNUNET_SQ_reset (plugin->dbh, stmt);
724  database_shutdown (plugin);
725  database_setup (plugin->env->cfg, plugin);
726  cont (cont_cls, key, size, GNUNET_SYSERR, msg);
727  GNUNET_free_non_null (msg);
728  return;
729  }
730  GNUNET_SQ_reset (plugin->dbh, stmt);
731  cont (cont_cls, key, size, ret, msg);
732  GNUNET_free_non_null (msg);
733 }
734 
735 
745 static void
747  sqlite3_stmt *stmt,
749  void *proc_cls)
750 {
751  int n;
752  struct GNUNET_TIME_Absolute expiration;
753  uint32_t replication;
754  uint32_t type;
755  uint32_t priority;
756  uint32_t anonymity;
757  uint64_t rowid;
758  void *value;
759  size_t value_size;
760  struct GNUNET_HashCode key;
761  int ret;
762  struct GNUNET_SQ_ResultSpec rs[] =
763  { GNUNET_SQ_result_spec_uint32 (&replication),
765  GNUNET_SQ_result_spec_uint32 (&priority),
766  GNUNET_SQ_result_spec_uint32 (&anonymity),
769  GNUNET_SQ_result_spec_variable_size (&value, &value_size),
772 
773  n = sqlite3_step (stmt);
774  switch (n)
775  {
776  case SQLITE_ROW:
777  if (GNUNET_OK != GNUNET_SQ_extract_result (stmt, rs))
778  {
779  GNUNET_break (0);
780  break;
781  }
783  "sqlite",
784  "Found reply in database with expiration %s\n",
786  ret = proc (proc_cls,
787  &key,
788  value_size,
789  value,
790  type,
791  priority,
792  anonymity,
793  replication,
794  expiration,
795  rowid);
797  GNUNET_SQ_reset (plugin->dbh, stmt);
798  if ((GNUNET_NO == ret) && (GNUNET_OK == delete_by_rowid (plugin, rowid)) &&
799  (NULL != plugin->env->duc))
800  plugin->env->duc (plugin->env->cls,
801  -(value_size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
802  return;
803 
804  case SQLITE_DONE:
805  /* database must be empty */
806  break;
807 
808  case SQLITE_BUSY:
809  case SQLITE_ERROR:
810  case SQLITE_MISUSE:
811  default:
812  LOG_SQLITE (plugin,
814  "sqlite3_step");
815  if (SQLITE_OK != sqlite3_reset (stmt))
816  LOG_SQLITE (plugin,
818  "sqlite3_reset");
819  GNUNET_break (0);
820  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
821  database_shutdown (plugin);
822  database_setup (plugin->env->cfg, plugin);
823  return;
824  }
825  GNUNET_SQ_reset (plugin->dbh, stmt);
826  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
827 }
828 
829 
842 static void
844  uint64_t next_uid,
845  enum GNUNET_BLOCK_Type type,
847  void *proc_cls)
848 {
849  struct Plugin *plugin = cls;
850  uint32_t type32 = type;
852  &next_uid),
854  &type32),
856 
858  if (GNUNET_OK != GNUNET_SQ_bind (plugin->selZeroAnon, params))
859  {
860  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
861  return;
862  }
863  execute_get (plugin, plugin->selZeroAnon, proc, proc_cls);
864 }
865 
866 
880 static void
882  uint64_t next_uid,
883  bool random,
884  const struct GNUNET_HashCode *key,
885  enum GNUNET_BLOCK_Type type,
887  void *proc_cls)
888 {
889  struct Plugin *plugin = cls;
890  uint64_t rvalue;
891  int use_rvalue = random;
892  uint32_t type32 = (uint32_t) type;
893  int use_type = GNUNET_BLOCK_TYPE_ANY != type;
894  int use_key = NULL != key;
895  sqlite3_stmt *stmt = plugin->get[use_rvalue * 4 + use_key * 2 + use_type];
896  struct GNUNET_SQ_QueryParam params[] =
897  { GNUNET_SQ_query_param_uint64 (&next_uid),
902 
903  /* SQLite doesn't like it when you try to bind a parameter greater than the
904  * last numbered parameter, but unused parameters in the middle are OK.
905  */
906  if (! use_type)
907  {
908  params[3] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
909  if (! use_key)
910  {
911  params[2] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
912  if (! use_rvalue)
913  params[1] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
914  }
915  }
916  if (random)
917  {
919  next_uid = 0;
920  }
921  else
922  rvalue = 0;
923 
924  if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
925  {
926  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
927  return;
928  }
929  execute_get (plugin, stmt, proc, proc_cls);
930 }
931 
932 
936 struct ReplCtx
937 {
942 
946  void *proc_cls;
947 
951  uint64_t uid;
952 
956  int have_uid;
957 };
958 
959 
979 static int
980 repl_proc (void *cls,
981  const struct GNUNET_HashCode *key,
982  uint32_t size,
983  const void *data,
984  enum GNUNET_BLOCK_Type type,
985  uint32_t priority,
986  uint32_t anonymity,
987  uint32_t replication,
989  uint64_t uid)
990 {
991  struct ReplCtx *rc = cls;
992  int ret;
993 
994  if (GNUNET_SYSERR == rc->have_uid)
995  rc->have_uid = GNUNET_NO;
996  ret = rc->proc (rc->proc_cls,
997  key,
998  size,
999  data,
1000  type,
1001  priority,
1002  anonymity,
1003  replication,
1004  expiration,
1005  uid);
1006  if (NULL != key)
1007  {
1008  rc->uid = uid;
1009  rc->have_uid = GNUNET_YES;
1010  }
1011  return ret;
1012 }
1013 
1014 
1025 static void
1028  void *proc_cls)
1029 {
1030  struct Plugin *plugin = cls;
1031  struct ReplCtx rc;
1032  uint64_t rvalue;
1033  uint32_t repl;
1034  struct GNUNET_SQ_QueryParam params_sel_repl[] =
1035  { GNUNET_SQ_query_param_uint64 (&rvalue),
1038  struct GNUNET_SQ_QueryParam params_upd_repl[] =
1040 
1042  "datastore-sqlite",
1043  "Getting random block based on replication order.\n");
1044  if (SQLITE_ROW != sqlite3_step (plugin->maxRepl))
1045  {
1046  GNUNET_SQ_reset (plugin->dbh, plugin->maxRepl);
1047  /* DB empty */
1048  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1049  return;
1050  }
1051  repl = sqlite3_column_int (plugin->maxRepl, 0);
1052  GNUNET_SQ_reset (plugin->dbh, plugin->maxRepl);
1054  if (GNUNET_OK != GNUNET_SQ_bind (plugin->selRepl, params_sel_repl))
1055  {
1056  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1057  return;
1058  }
1059  rc.have_uid = GNUNET_SYSERR;
1060  rc.proc = proc;
1061  rc.proc_cls = proc_cls;
1062  execute_get (plugin, plugin->selRepl, &repl_proc, &rc);
1063  if (GNUNET_YES == rc.have_uid)
1064  {
1065  if (GNUNET_OK != GNUNET_SQ_bind (plugin->updRepl, params_upd_repl))
1066  {
1067  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1068  return;
1069  }
1070  if (SQLITE_DONE != sqlite3_step (plugin->updRepl))
1071  LOG_SQLITE (plugin,
1073  "sqlite3_step");
1074  GNUNET_SQ_reset (plugin->dbh, plugin->updRepl);
1075  }
1076  if (GNUNET_SYSERR == rc.have_uid)
1077  {
1078  /* proc was not called at all so far, do it now. */
1079  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1080  }
1081 }
1082 
1083 
1092 static void
1094  PluginDatumProcessor proc,
1095  void *proc_cls)
1096 {
1097  struct Plugin *plugin = cls;
1098  sqlite3_stmt *stmt;
1099  struct GNUNET_TIME_Absolute now;
1101  &now),
1103 
1104  GNUNET_log_from (
1106  "sqlite",
1107  "Getting random block based on expiration and priority order.\n");
1108  now = GNUNET_TIME_absolute_get ();
1109  stmt = plugin->selExpi;
1110  if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
1111  {
1112  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1113  return;
1114  }
1115  execute_get (plugin, stmt, proc, proc_cls);
1116 }
1117 
1118 
1126 static void
1127 sqlite_plugin_get_keys (void *cls, PluginKeyProcessor proc, void *proc_cls)
1128 {
1129  struct Plugin *plugin = cls;
1130  struct GNUNET_HashCode key;
1131  struct GNUNET_SQ_ResultSpec results[] =
1133  sqlite3_stmt *stmt;
1134  int ret;
1135 
1136  GNUNET_assert (NULL != proc);
1137  if (SQLITE_OK != sq_prepare (plugin->dbh, "SELECT hash FROM gn091", &stmt))
1138  {
1139  LOG_SQLITE (plugin,
1141  "sqlite_prepare");
1142  proc (proc_cls, NULL, 0);
1143  return;
1144  }
1145  while (SQLITE_ROW == (ret = sqlite3_step (stmt)))
1146  {
1147  if (GNUNET_OK == GNUNET_SQ_extract_result (stmt, results))
1148  proc (proc_cls, &key, 1);
1149  else
1150  GNUNET_break (0);
1151  }
1152  if (SQLITE_DONE != ret)
1153  LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step");
1154  sqlite3_finalize (stmt);
1155  proc (proc_cls, NULL, 0);
1156 }
1157 
1158 
1164 static void
1166 {
1167  struct Plugin *plugin = cls;
1168 
1169  plugin->drop_on_shutdown = GNUNET_YES;
1170 }
1171 
1172 
1183 static void
1185  const struct GNUNET_HashCode *key,
1186  uint32_t size,
1187  const void *data,
1188  PluginRemoveCont cont,
1189  void *cont_cls)
1190 {
1191  struct Plugin *plugin = cls;
1192  struct GNUNET_SQ_QueryParam params[] =
1194  GNUNET_SQ_query_param_fixed_size (data, size),
1196 
1197  if (GNUNET_OK != GNUNET_SQ_bind (plugin->remove, params))
1198  {
1199  cont (cont_cls, key, size, GNUNET_SYSERR, "bind failed");
1200  return;
1201  }
1202  if (SQLITE_DONE != sqlite3_step (plugin->remove))
1203  {
1204  LOG_SQLITE (plugin,
1206  "sqlite3_step");
1207  GNUNET_SQ_reset (plugin->dbh, plugin->remove);
1208  cont (cont_cls, key, size, GNUNET_SYSERR, "sqlite3_step failed");
1209  return;
1210  }
1211  int changes = sqlite3_changes (plugin->dbh);
1212  GNUNET_SQ_reset (plugin->dbh, plugin->remove);
1213  if (0 == changes)
1214  {
1215  cont (cont_cls, key, size, GNUNET_NO, NULL);
1216  return;
1217  }
1218  if (NULL != plugin->env->duc)
1219  plugin->env->duc (plugin->env->cls,
1221  cont (cont_cls, key, size, GNUNET_OK, NULL);
1222 }
1223 
1224 
1232 static void
1233 sqlite_plugin_estimate_size (void *cls, unsigned long long *estimate)
1234 {
1235  struct Plugin *plugin = cls;
1236  sqlite3_stmt *stmt;
1237  uint64_t pages;
1238  uint64_t page_size;
1239 
1240 #if ENULL_DEFINED
1241  char *e;
1242 #endif
1243 
1244  if (NULL == estimate)
1245  return;
1246  if (SQLITE_VERSION_NUMBER < 3006000)
1247  {
1248  GNUNET_log_from (
1250  "datastore-sqlite",
1251  _ ("sqlite version to old to determine size, assuming zero\n"));
1252  *estimate = 0;
1253  return;
1254  }
1255  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "VACUUM", NULL, NULL, ENULL));
1256  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
1257  "PRAGMA auto_vacuum=INCREMENTAL",
1258  NULL,
1259  NULL,
1260  ENULL));
1261  CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_count", &stmt));
1262  if (SQLITE_ROW == sqlite3_step (stmt))
1263  pages = sqlite3_column_int64 (stmt, 0);
1264  else
1265  pages = 0;
1266  sqlite3_finalize (stmt);
1267  CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_size", &stmt));
1268  CHECK (SQLITE_ROW == sqlite3_step (stmt));
1269  page_size = sqlite3_column_int64 (stmt, 0);
1270  sqlite3_finalize (stmt);
1271  GNUNET_log (
1273  _ (
1274  "Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"),
1275  (unsigned long long) pages,
1276  (unsigned long long) page_size);
1277  *estimate = pages * page_size;
1278 }
1279 
1280 
1287 void *
1289 {
1290  static struct Plugin plugin;
1293 
1294  if (NULL != plugin.env)
1295  return NULL; /* can only initialize once! */
1296  memset (&plugin, 0, sizeof(struct Plugin));
1297  plugin.env = env;
1298  if (GNUNET_OK != database_setup (env->cfg, &plugin))
1299  {
1300  database_shutdown (&plugin);
1301  return NULL;
1302  }
1304  api->cls = &plugin;
1306  api->put = &sqlite_plugin_put;
1312  api->drop = &sqlite_plugin_drop;
1315  "sqlite",
1316  _ ("Sqlite database running\n"));
1317  return api;
1318 }
1319 
1320 
1327 void *
1329 {
1330  char *fn;
1332  struct Plugin *plugin = api->cls;
1333 
1335  "sqlite",
1336  "sqlite plugin is done\n");
1337  fn = NULL;
1338  if (plugin->drop_on_shutdown)
1339  fn = GNUNET_strdup (plugin->fn);
1340  database_shutdown (plugin);
1341  plugin->env = NULL;
1342  GNUNET_free (api);
1343  if (NULL != fn)
1344  {
1345  if (0 != unlink (fn))
1347  GNUNET_free (fn);
1348  }
1349  return NULL;
1350 }
1351 
1352 
1353 /* 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:544
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...
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.
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 int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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:684
#define GNUNET_SQ_result_spec_end
End of result parameter specification.
#define GNUNET_NO
Definition: gnunet_common.h:78
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:75
#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
#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 _(String)
GNU gettext support macro.
Definition: platform.h:181
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.
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:48
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:687
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)? ...
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
int GNUNET_SQ_bind(sqlite3_stmt *stmt, const struct GNUNET_SQ_QueryParam *params)
Execute binding operations for a prepared statement.
Definition: sq.c:37
static char * plugin
Solver plugin name as string.
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:76
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.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
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
struct GNUNET_PQ_Context * 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:77
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:86
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:742
#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.