GNUnet 0.22.2
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
#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:108
static struct GNUNET_TESTING_PluginFunctions * plugin
Plugin to dynamically load a test case.
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:506
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:606
@ 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
void * cls
Closure to pass to start_testcase.

References _, BUSY_TIMEOUT_MS, cfg, CHECK, GNUNET_TESTING_PluginFunctions::cls, 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 {
648 int changes = sqlite3_changes (plugin->dbh);
649 GNUNET_SQ_reset (plugin->dbh, plugin->update);
650 if (0 != changes)
651 {
652 cont (cont_cls, key, size, GNUNET_NO, NULL);
653 return;
654 }
655 }
656 }
657
658 {
659 // FIXME Refactor?
660 uint64_t rvalue;
661 uint32_t type32 = (uint32_t) type;
662 struct GNUNET_SQ_QueryParam params[] =
673 int n;
674 int ret;
675 sqlite3_stmt *stmt;
676
677 if (size > MAX_ITEM_SIZE)
678 {
679 cont (cont_cls, key, size, GNUNET_SYSERR, _ ("Data too large"));
680 return;
681 }
684 "sqlite",
685 "Storing in database block with type %u/key `%s'/priority %u/expiration in %s (%s).\n",
686 type,
687 GNUNET_h2s (key),
688 priority,
690 (
691 expiration),
692 GNUNET_YES),
694 stmt = plugin->insertContent;
696 if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
697 {
698 cont (cont_cls, key, size, GNUNET_SYSERR, NULL);
699 return;
700 }
701 n = sqlite3_step (stmt);
702 switch (n)
703 {
704 case SQLITE_DONE:
705 if (NULL != plugin->env->duc)
706 plugin->env->duc (plugin->env->cls,
709 "sqlite",
710 "Stored new entry (%u bytes)\n",
712 ret = GNUNET_OK;
713 break;
714
715 case SQLITE_BUSY:
716 GNUNET_break (0);
718 &msg,
720 "sqlite3_step");
722 break;
723
724 default:
726 &msg,
728 "sqlite3_step");
729 GNUNET_SQ_reset (plugin->dbh, stmt);
731 database_setup (plugin->env->cfg, plugin);
732 cont (cont_cls, key, size, GNUNET_SYSERR, msg);
734 return;
735 }
736 GNUNET_SQ_reset (plugin->dbh, stmt);
737 cont (cont_cls, key, size, ret, msg);
739 }
740}
static int ret
Final status code.
Definition: gnunet-arm.c:93
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:406
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:579
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:640
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, GNUNET_TESTING_PluginFunctions::cls, 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 753 of file plugin_datastore_sqlite.c.

757{
758 int n;
760 uint32_t replication;
761 uint32_t type;
762 uint32_t priority;
763 uint32_t anonymity;
764 uint64_t rowid;
765 void *value;
766 size_t value_size;
767 struct GNUNET_HashCode key;
768 int ret;
769 struct GNUNET_SQ_ResultSpec rs[] =
779
780 n = sqlite3_step (stmt);
781 switch (n)
782 {
783 case SQLITE_ROW:
784 if (GNUNET_OK != GNUNET_SQ_extract_result (stmt, rs))
785 {
786 GNUNET_break (0);
787 break;
788 }
790 "sqlite",
791 "Found reply in database with expiration %s\n",
793 ret = proc (proc_cls,
794 &key,
795 value_size,
796 value,
797 type,
798 priority,
799 anonymity,
802 rowid);
804 GNUNET_SQ_reset (plugin->dbh, stmt);
805 if ((GNUNET_NO == ret) && (GNUNET_OK == delete_by_rowid (plugin, rowid)) &&
806 (NULL != plugin->env->duc))
807 plugin->env->duc (plugin->env->cls,
808 -(value_size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
809 return;
810
811 case SQLITE_DONE:
812 /* database must be empty */
813 break;
814
815 case SQLITE_BUSY:
816 case SQLITE_ERROR:
817 case SQLITE_MISUSE:
818 default:
821 "sqlite3_step");
822 if (SQLITE_OK != sqlite3_reset (stmt))
825 "sqlite3_reset");
826 GNUNET_break (0);
827 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
829 database_setup (plugin->env->cfg, plugin);
830 return;
831 }
832 GNUNET_SQ_reset (plugin->dbh, stmt);
833 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
834}
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, GNUNET_TESTING_PluginFunctions::cls, 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 850 of file plugin_datastore_sqlite.c.

855{
856 struct Plugin *plugin = cls;
857 uint32_t type32 = type;
859 &next_uid),
861 &type32),
863
865 if (GNUNET_OK != GNUNET_SQ_bind (plugin->selZeroAnon, params))
866 {
867 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
868 return;
869 }
870 execute_get (plugin, plugin->selZeroAnon, proc, proc_cls);
871}
#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 888 of file plugin_datastore_sqlite.c.

895{
896 struct Plugin *plugin = cls;
897 uint64_t rvalue;
898 int use_rvalue = random;
899 uint32_t type32 = (uint32_t) type;
900 int use_type = GNUNET_BLOCK_TYPE_ANY != type;
901 int use_key = NULL != key;
902 sqlite3_stmt *stmt = plugin->get[use_rvalue * 4 + use_key * 2 + use_type];
903 struct GNUNET_SQ_QueryParam params[] =
904 { GNUNET_SQ_query_param_uint64 (&next_uid),
909
910 /* SQLite doesn't like it when you try to bind a parameter greater than the
911 * last numbered parameter, but unused parameters in the middle are OK.
912 */
913 if (! use_type)
914 {
916 if (! use_key)
917 {
919 if (! use_rvalue)
921 }
922 }
923 if (random)
924 {
926 next_uid = 0;
927 }
928 else
929 rvalue = 0;
930
931 if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
932 {
933 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
934 return;
935 }
936 execute_get (plugin, stmt, proc, proc_cls);
937}

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

997{
998 struct ReplCtx *rc = cls;
999 int ret;
1000
1001 if (GNUNET_SYSERR == rc->have_uid)
1002 rc->have_uid = GNUNET_NO;
1003 ret = rc->proc (rc->proc_cls,
1004 key,
1005 size,
1006 data,
1007 type,
1008 priority,
1009 anonymity,
1011 expiration,
1012 uid);
1013 if (NULL != key)
1014 {
1015 rc->uid = uid;
1016 rc->have_uid = GNUNET_YES;
1017 }
1018 return ret;
1019}
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 1033 of file plugin_datastore_sqlite.c.

1036{
1037 struct Plugin *plugin = cls;
1038 struct ReplCtx rc;
1039 uint64_t rvalue = 0;
1040 uint32_t repl;
1041 struct GNUNET_SQ_QueryParam params_sel_repl[] =
1042 { GNUNET_SQ_query_param_uint64 (&rvalue),
1045 struct GNUNET_SQ_QueryParam params_upd_repl[] =
1047
1049 "datastore-sqlite",
1050 "Getting random block based on replication order.\n");
1051 if (SQLITE_ROW != sqlite3_step (plugin->maxRepl))
1052 {
1053 GNUNET_SQ_reset (plugin->dbh, plugin->maxRepl);
1054 /* DB empty */
1055 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1056 return;
1057 }
1058 repl = sqlite3_column_int (plugin->maxRepl, 0);
1059 GNUNET_SQ_reset (plugin->dbh, plugin->maxRepl);
1061 if (GNUNET_OK != GNUNET_SQ_bind (plugin->selRepl, params_sel_repl))
1062 {
1063 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1064 return;
1065 }
1066 rc.have_uid = GNUNET_SYSERR;
1067 rc.proc = proc;
1068 rc.proc_cls = proc_cls;
1069 execute_get (plugin, plugin->selRepl, &repl_proc, &rc);
1070 if (GNUNET_YES == rc.have_uid)
1071 {
1072 if (GNUNET_OK != GNUNET_SQ_bind (plugin->updRepl, params_upd_repl))
1073 {
1074 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1075 return;
1076 }
1077 if (SQLITE_DONE != sqlite3_step (plugin->updRepl))
1080 "sqlite3_step");
1081 GNUNET_SQ_reset (plugin->dbh, plugin->updRepl);
1082 }
1083 if (GNUNET_SYSERR == rc.have_uid)
1084 {
1085 /* proc was not called at all so far, do it now. */
1086 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1087 }
1088}
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 1100 of file plugin_datastore_sqlite.c.

1103{
1104 struct Plugin *plugin = cls;
1105 sqlite3_stmt *stmt;
1106 struct GNUNET_TIME_Absolute now = { 0 };
1108 &now),
1110
1113 "sqlite",
1114 "Getting random block based on expiration and priority order.\n");
1115 now = GNUNET_TIME_absolute_get ();
1116 stmt = plugin->selExpi;
1117 if (GNUNET_OK != GNUNET_SQ_bind (stmt, params))
1118 {
1119 proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1120 return;
1121 }
1122 execute_get (plugin, stmt, proc, proc_cls);
1123}
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 1134 of file plugin_datastore_sqlite.c.

1135{
1136 struct Plugin *plugin = cls;
1137 struct GNUNET_HashCode key;
1138 struct GNUNET_SQ_ResultSpec results[] =
1140 sqlite3_stmt *stmt;
1141 int ret;
1142
1143 GNUNET_assert (NULL != proc);
1144 if (SQLITE_OK != sq_prepare (plugin->dbh, "SELECT hash FROM gn091", &stmt))
1145 {
1148 "sqlite_prepare");
1149 proc (proc_cls, NULL, 0);
1150 return;
1151 }
1152 while (SQLITE_ROW == (ret = sqlite3_step (stmt)))
1153 {
1155 proc (proc_cls, &key, 1);
1156 else
1157 GNUNET_break (0);
1158 }
1159 if (SQLITE_DONE != ret)
1160 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step");
1161 sqlite3_finalize (stmt);
1162 proc (proc_cls, NULL, 0);
1163}
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 1172 of file plugin_datastore_sqlite.c.

1173{
1174 struct Plugin *plugin = cls;
1175
1176 plugin->drop_on_shutdown = GNUNET_YES;
1177}

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

1197{
1198 struct Plugin *plugin = cls;
1199 struct GNUNET_SQ_QueryParam params[] =
1203
1204 if (GNUNET_OK != GNUNET_SQ_bind (plugin->remove, params))
1205 {
1206 cont (cont_cls, key, size, GNUNET_SYSERR, "bind failed");
1207 return;
1208 }
1209 if (SQLITE_DONE != sqlite3_step (plugin->remove))
1210 {
1213 "sqlite3_step");
1214 GNUNET_SQ_reset (plugin->dbh, plugin->remove);
1215 cont (cont_cls, key, size, GNUNET_SYSERR, "sqlite3_step failed");
1216 return;
1217 }
1218 {
1219 int changes = sqlite3_changes (plugin->dbh);
1220 GNUNET_SQ_reset (plugin->dbh, plugin->remove);
1221 if (0 == changes)
1222 {
1223 cont (cont_cls, key, size, GNUNET_NO, NULL);
1224 return;
1225 }
1226 }
1227 if (NULL != plugin->env->duc)
1228 plugin->env->duc (plugin->env->cls,
1230 cont (cont_cls, key, size, GNUNET_OK, NULL);
1231}

References GNUNET_TESTING_PluginFunctions::cls, 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 1242 of file plugin_datastore_sqlite.c.

1243{
1244 struct Plugin *plugin = cls;
1245 sqlite3_stmt *stmt;
1246 uint64_t pages;
1247 uint64_t page_size;
1248
1249#if ENULL_DEFINED
1250 char *e;
1251#endif
1252
1253 if (NULL == estimate)
1254 return;
1255 if (SQLITE_VERSION_NUMBER < 3006000)
1256 {
1259 "datastore-sqlite",
1260 _ ("sqlite version to old to determine size, assuming zero\n"));
1261 *estimate = 0;
1262 return;
1263 }
1264 CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "VACUUM", NULL, NULL, ENULL));
1265 CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh,
1266 "PRAGMA auto_vacuum=INCREMENTAL",
1267 NULL,
1268 NULL,
1269 ENULL));
1270 if (SQLITE_OK != sq_prepare (plugin->dbh, "PRAGMA page_count", &stmt))
1271 {
1274 "datastore-sqlite",
1275 _ ("error preparing statement\n"));
1276 return;
1277 }
1278 if (SQLITE_ROW == sqlite3_step (stmt))
1279 pages = sqlite3_column_int64 (stmt, 0);
1280 else
1281 pages = 0;
1282 sqlite3_finalize (stmt);
1283 if (SQLITE_OK != sq_prepare (plugin->dbh, "PRAGMA page_size", &stmt))
1284 {
1287 "datastore-sqlite",
1288 _ ("error preparing statement\n"));
1289 return;
1290 }
1291 if (SQLITE_ROW != sqlite3_step (stmt))
1292 {
1295 "datastore-sqlite",
1296 _ ("error stepping\n"));
1297 return;
1298 }
1299 page_size = sqlite3_column_int64 (stmt, 0);
1300 sqlite3_finalize (stmt);
1301 GNUNET_log (
1303 _ (
1304 "Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"),
1305 (unsigned long long) pages,
1306 (unsigned long long) page_size);
1307 *estimate = pages * page_size;
1308}
#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 1321 of file plugin_datastore_sqlite.c.

1322{
1323 static struct Plugin plugin;
1326
1327 if (NULL != plugin.env)
1328 return NULL; /* can only initialize once! */
1329 memset (&plugin, 0, sizeof(struct Plugin));
1330 plugin.env = env;
1331 if (GNUNET_OK != database_setup (env->cfg, &plugin))
1332 {
1334 return NULL;
1335 }
1337 api->cls = &plugin;
1339 api->put = &sqlite_plugin_put;
1345 api->drop = &sqlite_plugin_drop;
1348 "sqlite",
1349 _ ("Sqlite database running\n"));
1350 return api;
1351}
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 1364 of file plugin_datastore_sqlite.c.

1365{
1366 char *fn;
1368 struct Plugin *plugin = api->cls;
1369
1371 "sqlite",
1372 "sqlite plugin is done\n");
1373 fn = NULL;
1374 if (plugin->drop_on_shutdown)
1375 fn = GNUNET_strdup (plugin->fn);
1377 plugin->env = NULL;
1378 GNUNET_free (api);
1379 if (NULL != fn)
1380 {
1381 if (0 != unlink (fn))
1383 GNUNET_free (fn);
1384 }
1385 return NULL;
1386}
#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: