GNUnet  0.11.x
Data Structures | Macros | Functions
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_proc() 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:41
#define _(String)
GNU gettext support macro.
Definition: platform.h:177

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); \
}
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 270 of file plugin_datastore_sqlite.c.

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 ==
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);
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 !=
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 !=
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 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
struct Plugin * plugin
The process handle to the testbed service.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
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
#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
void * cls
Closure to use for callbacks.
sqlite3_stmt * maxRepl
Get maximum repl value in database.
sqlite3_stmt * insertContent
Precompiled SQL for insertion.
sqlite3_stmt * update
Precompiled SQL for update.
sqlite3_stmt * remove
Precompiled SQL for remove_key.
char * fn
Filename used for the DB.
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
sqlite3_stmt * selRepl
Precompiled SQL for replication selection.
sqlite3_stmt * delRow
Precompiled SQL for deletion.
sqlite3_stmt * get[8]
Precompiled SQL for selection.
struct GNUNET_PQ_Context * dbh
Native Postgres database handle.
sqlite3_stmt * selZeroAnon
Precompiled SQL for expiration selection.
sqlite3_stmt * selExpi
Precompiled SQL for expiration selection.
sqlite3_stmt * updRepl
Precompiled SQL for replication decrement.

References _, BUSY_TIMEOUT_MS, cfg, CHECK, GNUNET_DATACACHE_PluginEnvironment::cls, create_indices(), Plugin::dbh, Plugin::delRow, e, ENULL, Plugin::env, Plugin::fn, Plugin::get, 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, Plugin::insertContent, LOG_SQLITE, Plugin::maxRepl, plugin, Plugin::remove, RESULT_COLUMNS, Plugin::selExpi, Plugin::selRepl, Plugin::selZeroAnon, sq_prepare(), Plugin::update, and Plugin::updRepl.

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 494 of file plugin_datastore_sqlite.c.

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 (plugin->fn);
554 }
@ GNUNET_ERROR_TYPE_WARNING

References _, Plugin::dbh, Plugin::delRow, Plugin::fn, Plugin::get, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_from, Plugin::insertContent, LOG_SQLITE, Plugin::maxRepl, plugin, Plugin::remove, result, Plugin::selExpi, Plugin::selRepl, Plugin::selZeroAnon, Plugin::update, and Plugin::updRepl.

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 565 of file plugin_datastore_sqlite.c.

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  {
576  "sqlite3_step");
578  return GNUNET_SYSERR;
579  }
581  return GNUNET_OK;
582 }
int GNUNET_SQ_bind(sqlite3_stmt *stmt, const struct GNUNET_SQ_QueryParam *params)
Execute binding operations for a prepared statement.
Definition: sq.c:37
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint64(const uint64_t *x)
Generate query parameter for an uint16_t in host byte order.
void GNUNET_SQ_reset(sqlite3 *dbh, sqlite3_stmt *stmt)
Reset stmt and log error.
Definition: sq.c:132
#define GNUNET_SQ_query_param_end
End of query parameter specification.
Definition: gnunet_sq_lib.h:86
@ GNUNET_ERROR_TYPE_BULK
Description of a DB query parameter.
Definition: gnunet_sq_lib.h:55

References Plugin::dbh, Plugin::delRow, 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 602 of file plugin_datastore_sqlite.c.

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),
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  {
639  &msg,
641  "sqlite3_step");
642  cont (cont_cls, key, size, GNUNET_SYSERR, msg);
643  GNUNET_free (msg);
644  return;
645  }
646  int changes = sqlite3_changes (plugin->dbh);
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[] =
660  GNUNET_SQ_query_param_uint32 (&priority),
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);
712  &msg,
714  "sqlite3_step");
715  ret = GNUNET_SYSERR;
716  break;
717 
718  default:
720  &msg,
722  "sqlite3_step");
723  GNUNET_SQ_reset (plugin->dbh, stmt);
726  cont (cont_cls, key, size, GNUNET_SYSERR, msg);
727  GNUNET_free (msg);
728  return;
729  }
730  GNUNET_SQ_reset (plugin->dbh, stmt);
731  cont (cont_cls, key, size, ret, msg);
732  GNUNET_free (msg);
733 }
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.
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
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)
Random on unsigned 64-bit values.
@ 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
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:232
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:604
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:557
static unsigned int size
Size of the "table".
Definition: peer.c:67
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.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
A 512-bit hashcode.
Handle for a plugin.
Definition: block.c:38
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model

References _, anonymity, GNUNET_DATACACHE_PluginEnvironment::cfg, GNUNET_DATACACHE_PluginEnvironment::cls, data, database_setup(), database_shutdown(), Plugin::dbh, Plugin::env, 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, Plugin::insertContent, key, LOG_SQLITE_MSG, MAX_ITEM_SIZE, msg, plugin, replication, ret, size, type, and Plugin::update.

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 746 of file plugin_datastore_sqlite.c.

750 {
751  int n;
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[] =
765  GNUNET_SQ_result_spec_uint32 (&priority),
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:
814  "sqlite3_step");
815  if (SQLITE_OK != sqlite3_reset (stmt))
818  "sqlite3_reset");
819  GNUNET_break (0);
820  proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
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 }
static char * value
Value of the record to add/remove.
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
void GNUNET_SQ_cleanup_result(struct GNUNET_SQ_ResultSpec *rs)
Free all memory that was allocated in rs during GNUNET_SQ_extract_result().
Definition: sq.c:117
struct GNUNET_SQ_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, GNUNET_DATACACHE_PluginEnvironment::cfg, GNUNET_DATACACHE_PluginEnvironment::cls, database_setup(), database_shutdown(), Plugin::dbh, delete_by_rowid(), Plugin::env, 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 843 of file plugin_datastore_sqlite.c.

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 }
@ GNUNET_BLOCK_TYPE_ANY
Any type of block, used as a wildcard when searching.
#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, Plugin::selZeroAnon, 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 881 of file plugin_datastore_sqlite.c.

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 }

References execute_get(), Plugin::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 980 of file plugin_datastore_sqlite.c.

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 }
Context for repl_proc() 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 1026 of file plugin_datastore_sqlite.c.

1029 {
1030  struct Plugin *plugin = cls;
1031  struct ReplCtx rc;
1032  uint64_t rvalue = 0;
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  {
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);
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;
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");
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 }
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 Plugin::dbh, 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::maxRepl, plugin, ReplCtx::proc, ReplCtx::proc_cls, repl_proc(), Plugin::selRepl, ReplCtx::uid, and Plugin::updRepl.

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 1093 of file plugin_datastore_sqlite.c.

1096 {
1097  struct Plugin *plugin = cls;
1098  sqlite3_stmt *stmt;
1099  struct GNUNET_TIME_Absolute now = { 0 };
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 }
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86

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, plugin, and Plugin::selExpi.

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 1127 of file plugin_datastore_sqlite.c.

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  {
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 }
static unsigned int results
Definition: gnunet-search.c:52

References Plugin::dbh, 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 1165 of file plugin_datastore_sqlite.c.

1166 {
1167  struct Plugin *plugin = cls;
1168 
1170 }
int drop_on_shutdown
Should the database be dropped on shutdown?

References Plugin::drop_on_shutdown, 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 1184 of file plugin_datastore_sqlite.c.

1190 {
1191  struct Plugin *plugin = cls;
1192  struct GNUNET_SQ_QueryParam params[] =
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");
1208  cont (cont_cls, key, size, GNUNET_SYSERR, "sqlite3_step failed");
1209  return;
1210  }
1211  int changes = sqlite3_changes (plugin->dbh);
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 }

References GNUNET_DATACACHE_PluginEnvironment::cls, data, Plugin::dbh, Plugin::env, 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, Plugin::remove, 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 1233 of file plugin_datastore_sqlite.c.

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  if (SQLITE_OK != sq_prepare (plugin->dbh, "PRAGMA page_count", &stmt))
1262  {
1263  GNUNET_log_from (
1265  "datastore-sqlite",
1266  _("error preparing statement\n"));
1267  return;
1268  }
1269  if (SQLITE_ROW == sqlite3_step (stmt))
1270  pages = sqlite3_column_int64 (stmt, 0);
1271  else
1272  pages = 0;
1273  sqlite3_finalize (stmt);
1274  if (SQLITE_OK != sq_prepare (plugin->dbh, "PRAGMA page_size", &stmt))
1275  {
1276  GNUNET_log_from (
1278  "datastore-sqlite",
1279  _("error preparing statement\n"));
1280  return;
1281  }
1282  if (SQLITE_ROW != sqlite3_step (stmt))
1283  {
1284  GNUNET_log_from (
1286  "datastore-sqlite",
1287  _("error stepping\n"));
1288  return;
1289  }
1290  page_size = sqlite3_column_int64 (stmt, 0);
1291  sqlite3_finalize (stmt);
1292  GNUNET_log (
1294  _ (
1295  "Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"),
1296  (unsigned long long) pages,
1297  (unsigned long long) page_size);
1298  *estimate = pages * page_size;
1299 }
#define GNUNET_log(kind,...)
@ GNUNET_ERROR_TYPE_INFO

References _, CHECK, Plugin::dbh, 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 1309 of file plugin_datastore_sqlite.c.

1310 {
1311  static struct Plugin plugin;
1314 
1315  if (NULL != plugin.env)
1316  return NULL; /* can only initialize once! */
1317  memset (&plugin, 0, sizeof(struct Plugin));
1318  plugin.env = env;
1319  if (GNUNET_OK != database_setup (env->cfg, &plugin))
1320  {
1322  return NULL;
1323  }
1325  api->cls = &plugin;
1327  api->put = &sqlite_plugin_put;
1333  api->drop = &sqlite_plugin_drop;
1336  "sqlite",
1337  _ ("Sqlite database running\n"));
1338  return api;
1339 }
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, Plugin::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 1349 of file plugin_datastore_sqlite.c.

1350 {
1351  char *fn;
1352  struct GNUNET_DATASTORE_PluginFunctions *api = cls;
1353  struct Plugin *plugin = api->cls;
1354 
1356  "sqlite",
1357  "sqlite plugin is done\n");
1358  fn = NULL;
1359  if (plugin->drop_on_shutdown)
1360  fn = GNUNET_strdup (plugin->fn);
1362  plugin->env = NULL;
1363  GNUNET_free (api);
1364  if (NULL != fn)
1365  {
1366  if (0 != unlink (fn))
1368  GNUNET_free (fn);
1369  }
1370  return NULL;
1371 }
#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

References Plugin::api, GNUNET_BLOCK_PluginFunctions::cls, GNUNET_DATASTORE_PluginFunctions::cls, database_shutdown(), Plugin::drop_on_shutdown, Plugin::env, 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: