GNUnet  0.20.0
plugin_datastore_sqlite.c File Reference

sqlite-based datastore backend More...

#include "platform.h"
#include "gnunet_datastore_plugin.h"
#include "gnunet_sq_lib.h"
#include <sqlite3.h>
Include dependency graph for plugin_datastore_sqlite.c:

Go to the source code of this file.

Data Structures

struct  Plugin
 Handle for a plugin. More...
 
struct  ReplCtx
 Context for #repl_iter() function. More...
 

Macros

#define MAX_ITEM_SIZE   65536
 We allocate items on the stack at times. More...
 
#define BUSY_TIMEOUT_MS   250
 After how many ms "busy" should a DB operation fail for good? A low value makes sure that we are more responsive to requests (especially PUTs). More...
 
#define LOG_SQLITE(db, level, cmd)
 Log an error message at log-level 'level' that indicates a failure of the command 'cmd' on file 'filename' with the message given by strerror(errno). More...
 
#define LOG_SQLITE_MSG(db, msg, level, cmd)
 Log an error message at log-level 'level' that indicates a failure of the command 'cmd' on file 'filename' with the message given by strerror(errno). More...
 
#define ENULL   &e
 
#define ENULL_DEFINED   1
 
#define CHECK(a)
 
#define RESULT_COLUMNS    "repl, type, prio, anonLevel, expire, hash, value, _ROWID_"
 

Functions

static int sq_prepare (sqlite3 *dbh, const char *zSql, sqlite3_stmt **ppStmt)
 Prepare a SQL statement. More...
 
static void create_indices (sqlite3 *dbh)
 Create our database indices. More...
 
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 needed as well). More...
 
static void database_shutdown (struct Plugin *plugin)
 Shutdown database connection and associate data structures. More...
 
static int delete_by_rowid (struct Plugin *plugin, uint64_t rid)
 Delete the database entry with the given row identifier. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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(). More...
 
static void sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc, void *proc_cls)
 Get a random item for replication. More...
 
static void sqlite_plugin_get_expiration (void *cls, PluginDatumProcessor proc, void *proc_cls)
 Get a random item that has expired or has low priority. More...
 
static void sqlite_plugin_get_keys (void *cls, PluginKeyProcessor proc, void *proc_cls)
 Get all of the keys in the datastore. More...
 
static void sqlite_plugin_drop (void *cls)
 Drop database. More...
 
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. More...
 
static void sqlite_plugin_estimate_size (void *cls, unsigned long long *estimate)
 Get an estimate of how much space the database is currently using. More...
 
void * libgnunet_plugin_datastore_sqlite_init (void *cls)
 Entry point for the plugin. More...
 
void * libgnunet_plugin_datastore_sqlite_done (void *cls)
 Exit point from the plugin. More...
 

Detailed Description

sqlite-based datastore backend

Author
Christian Grothoff

Definition in file plugin_datastore_sqlite.c.

Macro Definition Documentation

◆ MAX_ITEM_SIZE

#define MAX_ITEM_SIZE   65536

We allocate items on the stack at times.

To prevent a stack overflow, we impose a limit on the maximum size for the data per item. 64k should be enough.

Definition at line 38 of file plugin_datastore_sqlite.c.

◆ BUSY_TIMEOUT_MS

#define BUSY_TIMEOUT_MS   250

After how many ms "busy" should a DB operation fail for good? A low value makes sure that we are more responsive to requests (especially PUTs).

A high value guarantees a higher success rate (SELECTs in iterate can take several seconds despite LIMIT=1).

The default value of 250ms should ensure that users do not experience huge latencies while at the same time allowing operations to succeed with reasonable probability.

Definition at line 50 of file plugin_datastore_sqlite.c.

◆ LOG_SQLITE

#define LOG_SQLITE (   db,
  level,
  cmd 
)
Value:
do \
{ \
GNUNET_log_from (level, \
"sqlite", \
_ ("`%s' failed at %s:%d with error: %s\n"), \
cmd, \
__FILE__, \
__LINE__, \
sqlite3_errmsg (db->dbh)); \
} while (0)
static struct GNUNET_FS_DirectoryBuilder * db
Definition: gnunet-search.c:97
#define _(String)
GNU gettext support macro.
Definition: platform.h:178

Log an error message at log-level 'level' that indicates a failure of the command 'cmd' on file 'filename' with the message given by strerror(errno).

Definition at line 58 of file plugin_datastore_sqlite.c.

◆ LOG_SQLITE_MSG

#define LOG_SQLITE_MSG (   db,
  msg,
  level,
  cmd 
)
Value:
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)
struct GNUNET_MessageHeader * msg
Definition: 005.c:2

Log an error message at log-level 'level' that indicates a failure of the command 'cmd' on file 'filename' with the message given by strerror(errno).

Definition at line 76 of file plugin_datastore_sqlite.c.

◆ ENULL

#define ENULL   &e

Definition at line 249 of file plugin_datastore_sqlite.c.

◆ ENULL_DEFINED

#define ENULL_DEFINED   1

Definition at line 250 of file plugin_datastore_sqlite.c.

◆ CHECK

#define CHECK (   a)
Value:
if (! (a)) \
{ \
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", e); \
sqlite3_free (e); \
e = NULL; \
}
static struct Experiment * e
@ GNUNET_ERROR_TYPE_ERROR

Definition at line 251 of file plugin_datastore_sqlite.c.

◆ RESULT_COLUMNS

#define RESULT_COLUMNS    "repl, type, prio, anonLevel, expire, hash, value, _ROWID_"

Function Documentation

◆ sq_prepare()

static int sq_prepare ( sqlite3 *  dbh,
const char *  zSql,
sqlite3_stmt **  ppStmt 
)
static

Prepare a SQL statement.

Parameters
dbhhandle to the database
zSqlSQL statement, UTF-8 encoded
ppStmtset to the prepared statement
Returns
0 on success

Definition at line 181 of file plugin_datastore_sqlite.c.

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 }
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static int result
Global testing status.
#define GNUNET_log_from(kind, comp,...)
@ GNUNET_ERROR_TYPE_DEBUG

References dummy, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log_from, and result.

Referenced by database_setup(), sqlite_plugin_estimate_size(), and sqlite_plugin_get_keys().

Here is the caller graph for this function:

◆ create_indices()

static void create_indices ( sqlite3 *  dbh)
static

Create our database indices.

Parameters
dbhhandle to the database

Definition at line 207 of file plugin_datastore_sqlite.c.

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 }

References GNUNET_ERROR_TYPE_ERROR, and GNUNET_log_from.

Referenced by database_setup().

Here is the caller graph for this function:

◆ database_setup()

static int database_setup ( const struct GNUNET_CONFIGURATION_Handle cfg,
struct Plugin plugin 
)
static

Initialize the database connections and associated data structures (create tables and indices as needed as well).

Parameters
cfgour configuration
pluginthe plugin context (state for this module)
Returns
GNUNET_OK on success

Definition at line 271 of file plugin_datastore_sqlite.c.

273 {
274  sqlite3_stmt *stmt;
275  char *afsdir;
276 
277 #if ENULL_DEFINED
278  char *e;
279 #endif
280 
282  "datastore-sqlite",
283  "FILENAME",
284  &afsdir))
285  {
287  "datastore-sqlite",
288  "FILENAME");
289  return GNUNET_SYSERR;
290  }
291  if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
292  {
294  {
295  GNUNET_break (0);
296  GNUNET_free (afsdir);
297  return GNUNET_SYSERR;
298  }
299  /* database is new or got deleted, reset payload to zero! */
300  if (NULL != plugin->env->duc)
301  plugin->env->duc (plugin->env->cls, 0);
302  }
303  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
304  plugin->fn = afsdir;
305 
306  /* Open database and precompile statements */
307  if (SQLITE_OK != sqlite3_open (plugin->fn, &plugin->dbh))
308  {
310  "sqlite",
311  _ ("Unable to initialize SQLite: %s.\n"),
312  sqlite3_errmsg (plugin->dbh));
313  return GNUNET_SYSERR;
314  }
315  CHECK (
316  SQLITE_OK ==
317  sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL, ENULL));
318  CHECK (
319  SQLITE_OK ==
320  sqlite3_exec (plugin->dbh, "PRAGMA synchronous=OFF", NULL, NULL, ENULL));
321  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
322  "PRAGMA legacy_file_format=OFF",
323  NULL,
324  NULL,
325  ENULL));
326  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
327  "PRAGMA auto_vacuum=INCREMENTAL",
328  NULL,
329  NULL,
330  ENULL));
331  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
332  "PRAGMA locking_mode=EXCLUSIVE",
333  NULL,
334  NULL,
335  ENULL));
336  CHECK (
337  SQLITE_OK ==
338  sqlite3_exec (plugin->dbh, "PRAGMA page_size=4096", NULL, NULL, ENULL));
339 
340  CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS));
341 
342 
343  /* We have to do it here, because otherwise precompiling SQL might fail */
344  CHECK (SQLITE_OK ==
345  sq_prepare (plugin->dbh,
346  "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn091'",
347  &stmt));
348 
349  /* FIXME: SQLite does not have unsigned integers! This is ok for the type column because
350  * we only test equality on it and can cast it to/from uint32_t. For repl, prio, and anonLevel
351  * we do math or inequality tests, so we can't handle the entire range of uint32_t.
352  * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC.
353  */if ((SQLITE_DONE == sqlite3_step (stmt)) &&
354  (SQLITE_OK != sqlite3_exec (plugin->dbh,
355  "CREATE TABLE gn091 ("
356  " repl INT4 NOT NULL DEFAULT 0,"
357  " type INT4 NOT NULL DEFAULT 0,"
358  " prio INT4 NOT NULL DEFAULT 0,"
359  " anonLevel INT4 NOT NULL DEFAULT 0,"
360  " expire INT8 NOT NULL DEFAULT 0,"
361  " rvalue INT8 NOT NULL,"
362  " hash TEXT NOT NULL DEFAULT '',"
363  " vhash TEXT NOT NULL DEFAULT '',"
364  " value BLOB NOT NULL DEFAULT '')",
365  NULL,
366  NULL,
367  NULL)))
368  {
369  LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec");
370  sqlite3_finalize (stmt);
371  return GNUNET_SYSERR;
372  }
373  sqlite3_finalize (stmt);
374  create_indices (plugin->dbh);
375 
376 #define RESULT_COLUMNS \
377  "repl, type, prio, anonLevel, expire, hash, value, _ROWID_"
378  if (
379  (SQLITE_OK != sq_prepare (plugin->dbh,
380  "UPDATE gn091 "
381  "SET prio = prio + ?, "
382  "repl = repl + ?, "
383  "expire = MAX(expire, ?) "
384  "WHERE hash = ? AND vhash = ?",
385  &plugin->update)) ||
386  (SQLITE_OK != sq_prepare (plugin->dbh,
387  "UPDATE gn091 "
388  "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?",
389  &plugin->updRepl)) ||
390  (SQLITE_OK != sq_prepare (plugin->dbh,
391  "SELECT " RESULT_COLUMNS " FROM gn091 "
392  "WHERE repl=?2 AND "
393  " (rvalue>=?1 OR "
394  " NOT EXISTS (SELECT 1 FROM gn091 "
395  "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) "
396  "ORDER BY rvalue ASC LIMIT 1",
397  &plugin->selRepl)) ||
398  (SQLITE_OK != sq_prepare (plugin->dbh,
399  "SELECT MAX(repl) FROM gn091",
400  &plugin->maxRepl)) ||
401  (SQLITE_OK !=
402  sq_prepare (plugin->dbh,
403  "SELECT " RESULT_COLUMNS " FROM gn091 "
404  "WHERE NOT EXISTS (SELECT 1 FROM gn091 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) "
405  "ORDER BY expire ASC LIMIT 1",
406  &plugin->selExpi)) ||
407  (SQLITE_OK != sq_prepare (plugin->dbh,
408  "SELECT " RESULT_COLUMNS " FROM gn091 "
409  "WHERE _ROWID_ >= ? AND "
410  "anonLevel = 0 AND "
411  "type = ? "
412  "ORDER BY _ROWID_ ASC LIMIT 1",
413  &plugin->selZeroAnon)) ||
414  (SQLITE_OK !=
415  sq_prepare (plugin->dbh,
416  "INSERT INTO gn091 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) "
417  "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
418  &plugin->insertContent)) ||
419  (SQLITE_OK != sq_prepare (plugin->dbh,
420  "SELECT " RESULT_COLUMNS " FROM gn091 "
421  "WHERE _ROWID_ >= ?1 "
422  "ORDER BY _ROWID_ ASC LIMIT 1",
423  &plugin->get[0])) ||
424  (SQLITE_OK != sq_prepare (plugin->dbh,
425  "SELECT " RESULT_COLUMNS " FROM gn091 "
426  "WHERE _ROWID_ >= ?1 AND "
427  "type = ?4 "
428  "ORDER BY _ROWID_ ASC LIMIT 1",
429  &plugin->get[1])) ||
430  (SQLITE_OK != sq_prepare (plugin->dbh,
431  "SELECT " RESULT_COLUMNS " FROM gn091 "
432  "WHERE _ROWID_ >= ?1 AND "
433  "hash = ?3 "
434  "ORDER BY _ROWID_ ASC LIMIT 1",
435  &plugin->get[2])) ||
436  (SQLITE_OK != sq_prepare (plugin->dbh,
437  "SELECT " RESULT_COLUMNS " FROM gn091 "
438  "WHERE _ROWID_ >= ?1 AND "
439  "hash = ?3 AND "
440  "type = ?4 "
441  "ORDER BY _ROWID_ ASC LIMIT 1",
442  &plugin->get[3])) ||
443  (SQLITE_OK != sq_prepare (plugin->dbh,
444  "SELECT " RESULT_COLUMNS " FROM gn091 "
445  "WHERE _ROWID_ >= ?1 AND "
446  "rvalue >= ?2 "
447  "ORDER BY _ROWID_ ASC LIMIT 1",
448  &plugin->get[4])) ||
449  (SQLITE_OK != sq_prepare (plugin->dbh,
450  "SELECT " RESULT_COLUMNS " FROM gn091 "
451  "WHERE _ROWID_ >= ?1 AND "
452  "rvalue >= ?2 AND "
453  "type = ?4 "
454  "ORDER BY _ROWID_ ASC LIMIT 1",
455  &plugin->get[5])) ||
456  (SQLITE_OK != sq_prepare (plugin->dbh,
457  "SELECT " RESULT_COLUMNS " FROM gn091 "
458  "WHERE _ROWID_ >= ?1 AND "
459  "rvalue >= ?2 AND "
460  "hash = ?3 "
461  "ORDER BY _ROWID_ ASC LIMIT 1",
462  &plugin->get[6])) ||
463  (SQLITE_OK != sq_prepare (plugin->dbh,
464  "SELECT " RESULT_COLUMNS " FROM gn091 "
465  "WHERE _ROWID_ >= ?1 AND "
466  "rvalue >= ?2 AND "
467  "hash = ?3 AND "
468  "type = ?4 "
469  "ORDER BY _ROWID_ ASC LIMIT 1",
470  &plugin->get[7])) ||
471  (SQLITE_OK != sq_prepare (plugin->dbh,
472  "DELETE FROM gn091 WHERE _ROWID_ = ?",
473  &plugin->delRow)) ||
474  (SQLITE_OK != sq_prepare (plugin->dbh,
475  "DELETE FROM gn091 "
476  "WHERE hash = ? AND "
477  "value = ? ",
478  &plugin->remove)) ||
479  false)
480  {
481  LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "precompiling");
482  return GNUNET_SYSERR;
483  }
484  return GNUNET_OK;
485 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
struct TestcasePlugin * plugin
The process handle to the testbed service.
enum GNUNET_GenericReturnValue 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.
enum GNUNET_GenericReturnValue 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:482
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
@ GNUNET_OK
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_free(ptr)
Wrapper around free.
#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...
#define RESULT_COLUMNS
#define LOG_SQLITE(db, level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' on file 'file...
static int sq_prepare(sqlite3 *dbh, const char *zSql, sqlite3_stmt **ppStmt)
Prepare a SQL statement.
static void create_indices(sqlite3 *dbh)
Create our database indices.
#define CHECK(a)
#define ENULL

References _, BUSY_TIMEOUT_MS, cfg, CHECK, create_indices(), e, ENULL, GNUNET_break, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_DISK_directory_create_for_file(), GNUNET_DISK_file_test(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log_config_missing(), GNUNET_log_from, GNUNET_OK, GNUNET_SYSERR, LOG_SQLITE, plugin, RESULT_COLUMNS, and sq_prepare().

Referenced by execute_get(), libgnunet_plugin_datastore_sqlite_init(), and sqlite_plugin_put().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ database_shutdown()

static void database_shutdown ( struct Plugin plugin)
static

Shutdown database connection and associate data structures.

Parameters
pluginthe plugin context (state for this module)

Definition at line 495 of file plugin_datastore_sqlite.c.

496 {
497  int result;
498 
499 #if SQLITE_VERSION_NUMBER >= 3007000
500  sqlite3_stmt *stmt;
501 #endif
502 
503  if (NULL != plugin->remove)
504  sqlite3_finalize (plugin->remove);
505  if (NULL != plugin->delRow)
506  sqlite3_finalize (plugin->delRow);
507  if (NULL != plugin->update)
508  sqlite3_finalize (plugin->update);
509  if (NULL != plugin->updRepl)
510  sqlite3_finalize (plugin->updRepl);
511  if (NULL != plugin->selRepl)
512  sqlite3_finalize (plugin->selRepl);
513  if (NULL != plugin->maxRepl)
514  sqlite3_finalize (plugin->maxRepl);
515  if (NULL != plugin->selExpi)
516  sqlite3_finalize (plugin->selExpi);
517  if (NULL != plugin->selZeroAnon)
518  sqlite3_finalize (plugin->selZeroAnon);
519  if (NULL != plugin->insertContent)
520  sqlite3_finalize (plugin->insertContent);
521  for (int i = 0; i < 8; ++i)
522  if (NULL != plugin->get[i])
523  sqlite3_finalize (plugin->get[i]);
524  result = sqlite3_close (plugin->dbh);
525 #if SQLITE_VERSION_NUMBER >= 3007000
526  if (result == SQLITE_BUSY)
527  {
530  "sqlite",
531  _ (
532  "Tried to close sqlite without finalizing all prepared statements.\n"));
533  stmt = sqlite3_next_stmt (plugin->dbh, NULL);
534  while (NULL != stmt)
535  {
537  "sqlite",
538  "Closing statement %p\n",
539  stmt);
540  result = sqlite3_finalize (stmt);
541  if (result != SQLITE_OK)
543  "sqlite",
544  "Failed to close statement %p: %d\n",
545  stmt,
546  result);
547  stmt = sqlite3_next_stmt (plugin->dbh, NULL);
548  }
549  result = sqlite3_close (plugin->dbh);
550  }
551 #endif
552  if (SQLITE_OK != result)
553  LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
554  GNUNET_free (plugin->fn);
555 }
@ GNUNET_ERROR_TYPE_WARNING

References _, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_from, LOG_SQLITE, plugin, and result.

Referenced by execute_get(), libgnunet_plugin_datastore_sqlite_done(), libgnunet_plugin_datastore_sqlite_init(), and sqlite_plugin_put().

Here is the caller graph for this function:

◆ delete_by_rowid()

static int delete_by_rowid ( struct Plugin plugin,
uint64_t  rid 
)
static

Delete the database entry with the given row identifier.

Parameters
pluginthe plugin context (state for this module)
ridthe ID of the row to delete

Definition at line 566 of file plugin_datastore_sqlite.c.

567 {
568  struct GNUNET_SQ_QueryParam params[] = { GNUNET_SQ_query_param_uint64 (&rid),
570 
571  if (GNUNET_OK != GNUNET_SQ_bind (plugin->delRow, params))
572  return GNUNET_SYSERR;
573  if (SQLITE_DONE != sqlite3_step (plugin->delRow))
574  {
577  "sqlite3_step");
578  GNUNET_SQ_reset (plugin->dbh, plugin->delRow);
579  return GNUNET_SYSERR;
580  }
581  GNUNET_SQ_reset (plugin->dbh, plugin->delRow);
582  return GNUNET_OK;
583 }
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint64(const uint64_t *x)
Generate query parameter for an uint16_t in host byte order.
enum GNUNET_GenericReturnValue GNUNET_SQ_bind(sqlite3_stmt *stmt, const struct GNUNET_SQ_QueryParam *params)
Execute binding operations for a prepared statement.
Definition: sq.c:31
void GNUNET_SQ_reset(sqlite3 *dbh, sqlite3_stmt *stmt)
Reset stmt and log error.
Definition: sq.c:120
#define GNUNET_SQ_query_param_end
End of query parameter specification.
Definition: gnunet_sq_lib.h:87
@ GNUNET_ERROR_TYPE_BULK
Description of a DB query parameter.
Definition: gnunet_sq_lib.h:56

References GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_ERROR, GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_end, GNUNET_SQ_query_param_uint64(), GNUNET_SQ_reset(), GNUNET_SYSERR, LOG_SQLITE, and plugin.

Referenced by execute_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sqlite_plugin_put()

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 
)
static

Store an item in the datastore.

Parameters
clsclosure
keykey for the item
absenttrue if the key was not found in the bloom filter
sizenumber of bytes in data
datacontent stored
typetype of the content
prioritypriority of the content
anonymityanonymity-level for the content
replicationreplication-level for the content
expirationexpiration time for the content
contcontinuation called with success or failure status
cont_clscontinuation closure

Definition at line 603 of file plugin_datastore_sqlite.c.

615 {
616  struct Plugin *plugin = cls;
617  struct GNUNET_HashCode vhash;
618  char *msg = NULL;
619 
620  GNUNET_CRYPTO_hash (data, size, &vhash);
621 
622  if (! absent)
623  {
624  struct GNUNET_SQ_QueryParam params[] =
625  { GNUNET_SQ_query_param_uint32 (&priority),
631 
632  if (GNUNET_OK != GNUNET_SQ_bind (plugin->update, params))
633  {
634  cont (cont_cls, key, size, GNUNET_SYSERR, _ ("sqlite bind failure"));
635  return;
636  }
637  if (SQLITE_DONE != sqlite3_step (plugin->update))
638  {
640  &msg,
642  "sqlite3_step");
643  cont (cont_cls, key, size, GNUNET_SYSERR, msg);
644  GNUNET_free (msg);
645  return;
646  }
647  int changes = sqlite3_changes (plugin->dbh);
648  GNUNET_SQ_reset (plugin->dbh, plugin->update);
649  if (0 != changes)
650  {
651  cont (cont_cls, key, size, GNUNET_NO, NULL);
652  return;
653  }
654  }
655 
656  uint64_t rvalue;
657  uint32_t type32 = (uint32_t) type;
658  struct GNUNET_SQ_QueryParam params[] =
661  GNUNET_SQ_query_param_uint32 (&priority),
669  int n;
670  int ret;
671  sqlite3_stmt *stmt;
672 
673  if (size > MAX_ITEM_SIZE)
674  {
675  cont (cont_cls, key, size, GNUNET_SYSERR, _ ("Data too large"));
676  return;
677  }
680  "sqlite",
681  "Storing in database block with type %u/key `%s'/priority %u/expiration in %s (%s).\n",
682  type,
683  GNUNET_h2s (key),
684  priority,
686  expiration),
687  GNUNET_YES),
689  stmt = plugin->insertContent;
691  if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
692  {
693  cont (cont_cls, key, size, GNUNET_SYSERR, NULL);
694  return;
695  }
696  n = sqlite3_step (stmt);
697  switch (n)
698  {
699  case SQLITE_DONE:
700  if (NULL != plugin->env->duc)
701  plugin->env->duc (plugin->env->cls,
704  "sqlite",
705  "Stored new entry (%u bytes)\n",
707  ret = GNUNET_OK;
708  break;
709 
710  case SQLITE_BUSY:
711  GNUNET_break (0);
713  &msg,
715  "sqlite3_step");
716  ret = GNUNET_SYSERR;
717  break;
718 
719  default:
721  &msg,
723  "sqlite3_step");
724  GNUNET_SQ_reset (plugin->dbh, stmt);
726  database_setup (plugin->env->cfg, plugin);
727  cont (cont_cls, key, size, GNUNET_SYSERR, msg);
728  GNUNET_free (msg);
729  return;
730  }
731  GNUNET_SQ_reset (plugin->dbh, stmt);
732  cont (cont_cls, key, size, ret, msg);
733  GNUNET_free (msg);
734 }
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static unsigned int replication
struct GNUNET_HashCode key
The key used in the DHT.
static unsigned int anonymity
uint32_t data
The data value.
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.
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_absolute_time(const struct GNUNET_TIME_Absolute *x)
Generate query parameter for an absolute time value.
#define GNUNET_SQ_query_param_auto_from_type(x)
Generate fixed-size query parameter with size determined by variable type.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_DATASTORE_ENTRY_OVERHEAD
How many bytes of overhead will we assume per entry in any DB (for reservations)?
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
@ GNUNET_YES
@ GNUNET_NO
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
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:405
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:616
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:569
static unsigned int size
Size of the "table".
Definition: peer.c:68
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...
#define MAX_ITEM_SIZE
We allocate items on the stack at times.
#define LOG_SQLITE_MSG(db, msg, level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' on file 'file...
static void database_shutdown(struct Plugin *plugin)
Shutdown database connection and associate data structures.
A 512-bit hashcode.
Handle for a plugin.
Definition: block.c:38
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model

References _, anonymity, data, database_setup(), database_shutdown(), expiration, GNUNET_break, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_h2s(), GNUNET_log_from, GNUNET_NO, GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_absolute_time(), GNUNET_SQ_query_param_auto_from_type, GNUNET_SQ_query_param_end, GNUNET_SQ_query_param_fixed_size(), GNUNET_SQ_query_param_uint32(), GNUNET_SQ_query_param_uint64(), GNUNET_SQ_reset(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_remaining(), GNUNET_YES, key, LOG_SQLITE_MSG, MAX_ITEM_SIZE, msg, plugin, replication, ret, size, and type.

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ execute_get()

static void execute_get ( struct Plugin plugin,
sqlite3_stmt *  stmt,
PluginDatumProcessor  proc,
void *  proc_cls 
)
static

Execute statement that gets a row and call the callback with the result.

Resets the statement afterwards.

Parameters
pluginthe plugin
stmtthe statement
procprocessor to call
proc_clsclosure for proc

Definition at line 747 of file plugin_datastore_sqlite.c.

751 {
752  int n;
754  uint32_t replication;
755  uint32_t type;
756  uint32_t priority;
757  uint32_t anonymity;
758  uint64_t rowid;
759  void *value;
760  size_t value_size;
761  struct GNUNET_HashCode key;
762  int ret;
763  struct GNUNET_SQ_ResultSpec rs[] =
766  GNUNET_SQ_result_spec_uint32 (&priority),
773 
774  n = sqlite3_step (stmt);
775  switch (n)
776  {
777  case SQLITE_ROW:
778  if (GNUNET_OK != GNUNET_SQ_extract_result (stmt, rs))
779  {
780  GNUNET_break (0);
781  break;
782  }
784  "sqlite",
785  "Found reply in database with expiration %s\n",
787  ret = proc (proc_cls,
788  &key,
789  value_size,
790  value,
791  type,
792  priority,
793  anonymity,
794  replication,
795  expiration,
796  rowid);
798  GNUNET_SQ_reset (plugin->dbh, stmt);
799  if ((GNUNET_NO == ret) && (GNUNET_OK == delete_by_rowid (plugin, rowid)) &&
800  (NULL != plugin->env->duc))
801  plugin->env->duc (plugin->env->cls,
802  -(value_size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
803  return;
804 
805  case SQLITE_DONE:
806  /* database must be empty */
807  break;
808 
809  case SQLITE_BUSY:
810  case SQLITE_ERROR:
811  case SQLITE_MISUSE:
812  default:
815  "sqlite3_step");
816  if (SQLITE_OK != sqlite3_reset (stmt))
819  "sqlite3_reset");
820  GNUNET_break (0);
821  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
823  database_setup (plugin->env->cfg, plugin);
824  return;
825  }
826  GNUNET_SQ_reset (plugin->dbh, stmt);
827  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
828 }
static char * value
Value of the record to add/remove.
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:76
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:105
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.
#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_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.
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
static int delete_by_rowid(struct Plugin *plugin, uint64_t rid)
Delete the database entry with the given row identifier.
Description of a DB result cell.
Time for absolute times used by GNUnet, in microseconds.

References anonymity, database_setup(), database_shutdown(), delete_by_rowid(), expiration, GNUNET_break, GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log_from, GNUNET_NO, GNUNET_OK, GNUNET_SQ_cleanup_result(), GNUNET_SQ_extract_result(), GNUNET_SQ_reset(), GNUNET_SQ_result_spec_absolute_time(), GNUNET_SQ_result_spec_auto_from_type, GNUNET_SQ_result_spec_end, GNUNET_SQ_result_spec_uint32(), GNUNET_SQ_result_spec_uint64(), GNUNET_SQ_result_spec_variable_size(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_UNIT_ZERO_ABS, key, LOG_SQLITE, plugin, replication, ret, type, and value.

Referenced by sqlite_plugin_get_expiration(), sqlite_plugin_get_key(), sqlite_plugin_get_replication(), and sqlite_plugin_get_zero_anonymity().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sqlite_plugin_get_zero_anonymity()

static void sqlite_plugin_get_zero_anonymity ( void *  cls,
uint64_t  next_uid,
enum GNUNET_BLOCK_Type  type,
PluginDatumProcessor  proc,
void *  proc_cls 
)
static

Select a subset of the items in the datastore and call the given processor for the item.

Parameters
clsour plugin context
next_uidreturn the result with lowest uid >= next_uid
typeentries of which type should be considered? Must not be zero (ANY).
procfunction to call on the matching value; will be called with NULL if no value matches
proc_clsclosure for proc

Definition at line 844 of file plugin_datastore_sqlite.c.

849 {
850  struct Plugin *plugin = cls;
851  uint32_t type32 = type;
853  &next_uid),
855  &type32),
857 
859  if (GNUNET_OK != GNUNET_SQ_bind (plugin->selZeroAnon, params))
860  {
861  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
862  return;
863  }
864  execute_get (plugin, plugin->selZeroAnon, proc, proc_cls);
865 }
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
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.

References execute_get(), GNUNET_assert, GNUNET_BLOCK_TYPE_ANY, GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_end, GNUNET_SQ_query_param_uint32(), GNUNET_SQ_query_param_uint64(), GNUNET_TIME_UNIT_ZERO_ABS, plugin, and type.

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sqlite_plugin_get_key()

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 
)
static

Get results for a particular key in the datastore.

Parameters
clsclosure
next_uidreturn the result with lowest uid >= next_uid
randomif true, return a random result instead of using next_uid
keymaybe NULL (to match all entries)
typeentries of which type are relevant? Use 0 for any type.
procfunction to call on the matching value; will be called with NULL if nothing matches
proc_clsclosure for proc

Definition at line 882 of file plugin_datastore_sqlite.c.

889 {
890  struct Plugin *plugin = cls;
891  uint64_t rvalue;
892  int use_rvalue = random;
893  uint32_t type32 = (uint32_t) type;
894  int use_type = GNUNET_BLOCK_TYPE_ANY != type;
895  int use_key = NULL != key;
896  sqlite3_stmt *stmt = plugin->get[use_rvalue * 4 + use_key * 2 + use_type];
897  struct GNUNET_SQ_QueryParam params[] =
898  { GNUNET_SQ_query_param_uint64 (&next_uid),
903 
904  /* SQLite doesn't like it when you try to bind a parameter greater than the
905  * last numbered parameter, but unused parameters in the middle are OK.
906  */
907  if (! use_type)
908  {
909  params[3] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
910  if (! use_key)
911  {
912  params[2] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
913  if (! use_rvalue)
914  params[1] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
915  }
916  }
917  if (random)
918  {
920  next_uid = 0;
921  }
922  else
923  rvalue = 0;
924 
925  if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
926  {
927  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
928  return;
929  }
930  execute_get (plugin, stmt, proc, proc_cls);
931 }

References execute_get(), GNUNET_BLOCK_TYPE_ANY, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_auto_from_type, GNUNET_SQ_query_param_end, GNUNET_SQ_query_param_uint32(), GNUNET_SQ_query_param_uint64(), GNUNET_TIME_UNIT_ZERO_ABS, key, plugin, and type.

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ repl_proc()

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 
)
static

Wrapper for the processor for sqlite_plugin_get_replication().

Decrements the replication counter and calls the original processor.

Parameters
clsclosure
keykey for the content
sizenumber of bytes in data
datacontent stored
typetype of the content
prioritypriority of the content
anonymityanonymity-level for the content
replicationreplication-level for the content
expirationexpiration time for the content
uidunique identifier for the datum; maybe 0 if no unique identifier is available
Returns
GNUNET_OK for normal return, GNUNET_NO to delete the item

Definition at line 981 of file plugin_datastore_sqlite.c.

991 {
992  struct ReplCtx *rc = cls;
993  int ret;
994 
995  if (GNUNET_SYSERR == rc->have_uid)
996  rc->have_uid = GNUNET_NO;
997  ret = rc->proc (rc->proc_cls,
998  key,
999  size,
1000  data,
1001  type,
1002  priority,
1003  anonymity,
1004  replication,
1005  expiration,
1006  uid);
1007  if (NULL != key)
1008  {
1009  rc->uid = uid;
1010  rc->have_uid = GNUNET_YES;
1011  }
1012  return ret;
1013 }
Context for #repl_iter() function.
void * proc_cls
Closure for proc.
uint64_t uid
UID to use.
int have_uid
Yes if UID was set.
PluginDatumProcessor proc
Function to call for the result (or the NULL).

References anonymity, data, expiration, GNUNET_NO, GNUNET_SYSERR, GNUNET_YES, ReplCtx::have_uid, key, ReplCtx::proc, ReplCtx::proc_cls, replication, ret, size, type, and ReplCtx::uid.

Referenced by sqlite_plugin_get_replication().

Here is the caller graph for this function:

◆ sqlite_plugin_get_replication()

static void sqlite_plugin_get_replication ( void *  cls,
PluginDatumProcessor  proc,
void *  proc_cls 
)
static

Get a random item for replication.

Returns a single random item from those with the highest replication counters. The item's replication counter is decremented by one IF it was positive before. Call proc with all values ZERO or NULL if the datastore is empty.

Parameters
clsclosure
procfunction to call the value (once only).
proc_clsclosure for proc

Definition at line 1027 of file plugin_datastore_sqlite.c.

1030 {
1031  struct Plugin *plugin = cls;
1032  struct ReplCtx rc;
1033  uint64_t rvalue = 0;
1034  uint32_t repl;
1035  struct GNUNET_SQ_QueryParam params_sel_repl[] =
1036  { GNUNET_SQ_query_param_uint64 (&rvalue),
1039  struct GNUNET_SQ_QueryParam params_upd_repl[] =
1041 
1043  "datastore-sqlite",
1044  "Getting random block based on replication order.\n");
1045  if (SQLITE_ROW != sqlite3_step (plugin->maxRepl))
1046  {
1047  GNUNET_SQ_reset (plugin->dbh, plugin->maxRepl);
1048  /* DB empty */
1049  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1050  return;
1051  }
1052  repl = sqlite3_column_int (plugin->maxRepl, 0);
1053  GNUNET_SQ_reset (plugin->dbh, plugin->maxRepl);
1055  if (GNUNET_OK != GNUNET_SQ_bind (plugin->selRepl, params_sel_repl))
1056  {
1057  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1058  return;
1059  }
1060  rc.have_uid = GNUNET_SYSERR;
1061  rc.proc = proc;
1062  rc.proc_cls = proc_cls;
1063  execute_get (plugin, plugin->selRepl, &repl_proc, &rc);
1064  if (GNUNET_YES == rc.have_uid)
1065  {
1066  if (GNUNET_OK != GNUNET_SQ_bind (plugin->updRepl, params_upd_repl))
1067  {
1068  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1069  return;
1070  }
1071  if (SQLITE_DONE != sqlite3_step (plugin->updRepl))
1072  LOG_SQLITE (plugin,
1074  "sqlite3_step");
1075  GNUNET_SQ_reset (plugin->dbh, plugin->updRepl);
1076  }
1077  if (GNUNET_SYSERR == rc.have_uid)
1078  {
1079  /* proc was not called at all so far, do it now. */
1080  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1081  }
1082 }
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().

References execute_get(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log_from, GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_end, GNUNET_SQ_query_param_uint32(), GNUNET_SQ_query_param_uint64(), GNUNET_SQ_reset(), GNUNET_SYSERR, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_YES, ReplCtx::have_uid, LOG_SQLITE, plugin, ReplCtx::proc, ReplCtx::proc_cls, repl_proc(), and ReplCtx::uid.

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sqlite_plugin_get_expiration()

static void sqlite_plugin_get_expiration ( void *  cls,
PluginDatumProcessor  proc,
void *  proc_cls 
)
static

Get a random item that has expired or has low priority.

Call proc with all values ZERO or NULL if the datastore is empty.

Parameters
clsclosure
procfunction to call the value (once only).
proc_clsclosure for proc

Definition at line 1094 of file plugin_datastore_sqlite.c.

1097 {
1098  struct Plugin *plugin = cls;
1099  sqlite3_stmt *stmt;
1100  struct GNUNET_TIME_Absolute now = { 0 };
1102  &now),
1104 
1105  GNUNET_log_from (
1107  "sqlite",
1108  "Getting random block based on expiration and priority order.\n");
1109  now = GNUNET_TIME_absolute_get ();
1110  stmt = plugin->selExpi;
1111  if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
1112  {
1113  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1114  return;
1115  }
1116  execute_get (plugin, stmt, proc, proc_cls);
1117 }
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111

References execute_get(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log_from, GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_absolute_time(), GNUNET_SQ_query_param_end, GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_ZERO_ABS, and plugin.

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sqlite_plugin_get_keys()

static void sqlite_plugin_get_keys ( void *  cls,
PluginKeyProcessor  proc,
void *  proc_cls 
)
static

Get all of the keys in the datastore.

Parameters
clsclosure
procfunction to call on each key
proc_clsclosure for proc

Definition at line 1128 of file plugin_datastore_sqlite.c.

1129 {
1130  struct Plugin *plugin = cls;
1131  struct GNUNET_HashCode key;
1132  struct GNUNET_SQ_ResultSpec results[] =
1134  sqlite3_stmt *stmt;
1135  int ret;
1136 
1137  GNUNET_assert (NULL != proc);
1138  if (SQLITE_OK != sq_prepare (plugin->dbh, "SELECT hash FROM gn091", &stmt))
1139  {
1140  LOG_SQLITE (plugin,
1142  "sqlite_prepare");
1143  proc (proc_cls, NULL, 0);
1144  return;
1145  }
1146  while (SQLITE_ROW == (ret = sqlite3_step (stmt)))
1147  {
1149  proc (proc_cls, &key, 1);
1150  else
1151  GNUNET_break (0);
1152  }
1153  if (SQLITE_DONE != ret)
1154  LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step");
1155  sqlite3_finalize (stmt);
1156  proc (proc_cls, NULL, 0);
1157 }
static unsigned int results

References GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_ERROR, GNUNET_OK, GNUNET_SQ_extract_result(), GNUNET_SQ_result_spec_auto_from_type, GNUNET_SQ_result_spec_end, key, LOG_SQLITE, plugin, results, ret, and sq_prepare().

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sqlite_plugin_drop()

static void sqlite_plugin_drop ( void *  cls)
static

Drop database.

Parameters
clsour plugin context

Definition at line 1166 of file plugin_datastore_sqlite.c.

1167 {
1168  struct Plugin *plugin = cls;
1169 
1170  plugin->drop_on_shutdown = GNUNET_YES;
1171 }

References GNUNET_YES, and plugin.

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the caller graph for this function:

◆ sqlite_plugin_remove_key()

static void sqlite_plugin_remove_key ( void *  cls,
const struct GNUNET_HashCode key,
uint32_t  size,
const void *  data,
PluginRemoveCont  cont,
void *  cont_cls 
)
static

Remove a particular key in the datastore.

Parameters
clsclosure
keykey for the content
sizenumber of bytes in data
datacontent stored
contcontinuation called with success or failure status
cont_clscontinuation closure for cont

Definition at line 1185 of file plugin_datastore_sqlite.c.

1191 {
1192  struct Plugin *plugin = cls;
1193  struct GNUNET_SQ_QueryParam params[] =
1197 
1198  if (GNUNET_OK != GNUNET_SQ_bind (plugin->remove, params))
1199  {
1200  cont (cont_cls, key, size, GNUNET_SYSERR, "bind failed");
1201  return;
1202  }
1203  if (SQLITE_DONE != sqlite3_step (plugin->remove))
1204  {
1205  LOG_SQLITE (plugin,
1207  "sqlite3_step");
1208  GNUNET_SQ_reset (plugin->dbh, plugin->remove);
1209  cont (cont_cls, key, size, GNUNET_SYSERR, "sqlite3_step failed");
1210  return;
1211  }
1212  int changes = sqlite3_changes (plugin->dbh);
1213  GNUNET_SQ_reset (plugin->dbh, plugin->remove);
1214  if (0 == changes)
1215  {
1216  cont (cont_cls, key, size, GNUNET_NO, NULL);
1217  return;
1218  }
1219  if (NULL != plugin->env->duc)
1220  plugin->env->duc (plugin->env->cls,
1222  cont (cont_cls, key, size, GNUNET_OK, NULL);
1223 }

References data, GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_ERROR, GNUNET_NO, GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_auto_from_type, GNUNET_SQ_query_param_end, GNUNET_SQ_query_param_fixed_size(), GNUNET_SQ_reset(), GNUNET_SYSERR, key, LOG_SQLITE, plugin, and size.

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sqlite_plugin_estimate_size()

static void sqlite_plugin_estimate_size ( void *  cls,
unsigned long long *  estimate 
)
static

Get an estimate of how much space the database is currently using.

Parameters
clsthe struct Plugin
Returns
the size of the database on disk (estimate)

Definition at line 1234 of file plugin_datastore_sqlite.c.

1235 {
1236  struct Plugin *plugin = cls;
1237  sqlite3_stmt *stmt;
1238  uint64_t pages;
1239  uint64_t page_size;
1240 
1241 #if ENULL_DEFINED
1242  char *e;
1243 #endif
1244 
1245  if (NULL == estimate)
1246  return;
1247  if (SQLITE_VERSION_NUMBER < 3006000)
1248  {
1249  GNUNET_log_from (
1251  "datastore-sqlite",
1252  _ ("sqlite version to old to determine size, assuming zero\n"));
1253  *estimate = 0;
1254  return;
1255  }
1256  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "VACUUM", NULL, NULL, ENULL));
1257  CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
1258  "PRAGMA auto_vacuum=INCREMENTAL",
1259  NULL,
1260  NULL,
1261  ENULL));
1262  if (SQLITE_OK != sq_prepare (plugin->dbh, "PRAGMA page_count", &stmt))
1263  {
1264  GNUNET_log_from (
1266  "datastore-sqlite",
1267  _("error preparing statement\n"));
1268  return;
1269  }
1270  if (SQLITE_ROW == sqlite3_step (stmt))
1271  pages = sqlite3_column_int64 (stmt, 0);
1272  else
1273  pages = 0;
1274  sqlite3_finalize (stmt);
1275  if (SQLITE_OK != sq_prepare (plugin->dbh, "PRAGMA page_size", &stmt))
1276  {
1277  GNUNET_log_from (
1279  "datastore-sqlite",
1280  _("error preparing statement\n"));
1281  return;
1282  }
1283  if (SQLITE_ROW != sqlite3_step (stmt))
1284  {
1285  GNUNET_log_from (
1287  "datastore-sqlite",
1288  _("error stepping\n"));
1289  return;
1290  }
1291  page_size = sqlite3_column_int64 (stmt, 0);
1292  sqlite3_finalize (stmt);
1293  GNUNET_log (
1295  _ (
1296  "Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"),
1297  (unsigned long long) pages,
1298  (unsigned long long) page_size);
1299  *estimate = pages * page_size;
1300 }
#define GNUNET_log(kind,...)
@ GNUNET_ERROR_TYPE_INFO

References _, CHECK, e, ENULL, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_from, plugin, and sq_prepare().

Referenced by libgnunet_plugin_datastore_sqlite_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ libgnunet_plugin_datastore_sqlite_init()

void* libgnunet_plugin_datastore_sqlite_init ( void *  cls)

Entry point for the plugin.

Parameters
clsthe struct GNUNET_DATASTORE_PluginEnvironment *
Returns
NULL on error, othrewise the plugin context

Definition at line 1310 of file plugin_datastore_sqlite.c.

1311 {
1312  static struct Plugin plugin;
1315 
1316  if (NULL != plugin.env)
1317  return NULL; /* can only initialize once! */
1318  memset (&plugin, 0, sizeof(struct Plugin));
1319  plugin.env = env;
1320  if (GNUNET_OK != database_setup (env->cfg, &plugin))
1321  {
1323  return NULL;
1324  }
1326  api->cls = &plugin;
1328  api->put = &sqlite_plugin_put;
1334  api->drop = &sqlite_plugin_drop;
1337  "sqlite",
1338  _ ("Sqlite database running\n"));
1339  return api;
1340 }
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void sqlite_plugin_estimate_size(void *cls, unsigned long long *estimate)
Get an estimate of how much space the database is currently using.
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.
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.
static void sqlite_plugin_get_keys(void *cls, PluginKeyProcessor proc, void *proc_cls)
Get all of the keys in the datastore.
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.
static void sqlite_plugin_get_replication(void *cls, PluginDatumProcessor proc, void *proc_cls)
Get a random item for replication.
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.
static void sqlite_plugin_drop(void *cls)
Drop database.
static void sqlite_plugin_get_expiration(void *cls, PluginDatumProcessor proc, void *proc_cls)
Get a random item that has expired or has low priority.
The datastore service will pass a pointer to a struct of this type as the first and only argument to ...
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
PluginGetKey get_key
Get a particular datum matching a given hash from the datastore.
PluginGetRandom get_expiration
Function to get a random expired item or, if none are expired, either the oldest entry or one with a ...
PluginEstimateSize estimate_size
Calculate the current on-disk size of the SQ store.
PluginGetKeys get_keys
Iterate over all keys in the database.
PluginGetRandom get_replication
Function to get a random item with high replication score from the database, lowering the item's repl...
PluginPut put
Function to store an item in the datastore.
void * cls
Closure to use for all of the following callbacks (except "next_request").
PluginGetType get_zero_anonymity
Get datum (of the specified type) with anonymity level zero.
PluginDrop drop
Delete the database.
PluginRemoveKey remove_key
Function to remove an item from the database.

References _, GNUNET_DATASTORE_PluginEnvironment::cls, GNUNET_DATASTORE_PluginFunctions::cls, database_setup(), database_shutdown(), GNUNET_DATASTORE_PluginFunctions::drop, env, GNUNET_DATASTORE_PluginFunctions::estimate_size, GNUNET_DATASTORE_PluginFunctions::get_expiration, GNUNET_DATASTORE_PluginFunctions::get_key, GNUNET_DATASTORE_PluginFunctions::get_keys, GNUNET_DATASTORE_PluginFunctions::get_replication, GNUNET_DATASTORE_PluginFunctions::get_zero_anonymity, GNUNET_ERROR_TYPE_INFO, GNUNET_log_from, GNUNET_new, GNUNET_OK, plugin, GNUNET_DATASTORE_PluginFunctions::put, GNUNET_DATASTORE_PluginFunctions::remove_key, sqlite_plugin_drop(), sqlite_plugin_estimate_size(), sqlite_plugin_get_expiration(), sqlite_plugin_get_key(), sqlite_plugin_get_keys(), sqlite_plugin_get_replication(), sqlite_plugin_get_zero_anonymity(), sqlite_plugin_put(), and sqlite_plugin_remove_key().

Here is the call graph for this function:

◆ libgnunet_plugin_datastore_sqlite_done()

void* libgnunet_plugin_datastore_sqlite_done ( void *  cls)

Exit point from the plugin.

Parameters
clsthe plugin context (as returned by "init")
Returns
always NULL

Definition at line 1350 of file plugin_datastore_sqlite.c.

1351 {
1352  char *fn;
1353  struct GNUNET_DATASTORE_PluginFunctions *api = cls;
1354  struct Plugin *plugin = api->cls;
1355 
1357  "sqlite",
1358  "sqlite plugin is done\n");
1359  fn = NULL;
1360  if (plugin->drop_on_shutdown)
1361  fn = GNUNET_strdup (plugin->fn);
1363  plugin->env = NULL;
1364  GNUNET_free (api);
1365  if (NULL != fn)
1366  {
1367  if (0 != unlink (fn))
1369  GNUNET_free (fn);
1370  }
1371  return NULL;
1372 }
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
void * cls
Closure for all of the callbacks.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
char * fn
Filename used for the DB.

References Plugin::api, GNUNET_BLOCK_PluginFunctions::cls, GNUNET_DATASTORE_PluginFunctions::cls, database_shutdown(), Plugin::fn, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_from, GNUNET_log_strerror_file, GNUNET_strdup, and plugin.

Here is the call graph for this function: