GNUnet 0.21.1
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; \
}
@ 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 struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:109
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(), 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:30
void GNUNET_SQ_reset(sqlite3 *dbh, sqlite3_stmt *stmt)
Reset stmt and log error.
Definition: sq.c:119
#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);
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[] =
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");
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);
729 return;
730 }
731 GNUNET_SQ_reset (plugin->dbh, stmt);
732 cont (cont_cls, key, size, ret, msg);
734}
static int ret
Final status code.
Definition: gnunet-arm.c:94
static unsigned int replication
Desired replication level.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static unsigned int anonymity
static uint32_t type
Type string converted to DNS type 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_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:570
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:617
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

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[] =
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,
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:75
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:104
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}
#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.
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.

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 {
910 if (! use_key)
911 {
913 if (! use_rvalue)
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,
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))
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
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 {
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 {
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 {
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 {
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 {
1279 "datastore-sqlite",
1280 _("error preparing statement\n"));
1281 return;
1282 }
1283 if (SQLITE_ROW != sqlite3_step (stmt))
1284 {
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, 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;
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: