GNUnet  0.17.6
Data Structures | Macros | Functions
plugin_namestore_sqlite.c File Reference

sqlite-based namestore backend More...

#include "platform.h"
#include "gnunet_namestore_plugin.h"
#include "gnunet_namestore_service.h"
#include "gnunet_gnsrecord_lib.h"
#include "gnunet_sq_lib.h"
#include "namestore.h"
#include <sqlite3.h>
Include dependency graph for plugin_namestore_sqlite.c:

Go to the source code of this file.

Data Structures

struct  Plugin
 Handle for a plugin. More...
 

Macros

#define BUSY_TIMEOUT_MS   1000
 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(kind, ...)   GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__)
 

Functions

static int database_setup (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 namestore_sqlite_store_records (void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 Store a record in the datastore. More...
 
static int get_records_and_call_iterator (struct Plugin *plugin, sqlite3_stmt *stmt, const struct GNUNET_IDENTITY_PrivateKey *zone_key, uint64_t limit, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
 The given 'sqlite' statement has been prepared to be run. More...
 
static int namestore_sqlite_lookup_records (void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
 Lookup records in the datastore for which we are the authority. More...
 
static int namestore_sqlite_iterate_records (void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, uint64_t serial, uint64_t limit, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
 Iterate over the results for a particular key and zone in the datastore. More...
 
static int namestore_sqlite_zone_to_name (void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const struct GNUNET_IDENTITY_PublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
 Look for an existing PKEY delegation record for a given public key. More...
 
static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_begin (void *cls, char **emsg)
 Begin a transaction for a client. More...
 
static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_rollback (void *cls, char **emsg)
 Commit a transaction for a client. More...
 
static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_commit (void *cls, char **emsg)
 Roll back a transaction for a client. More...
 
void * libgnunet_plugin_namestore_sqlite_init (void *cls)
 Entry point for the plugin. More...
 
void * libgnunet_plugin_namestore_sqlite_done (void *cls)
 Exit point from the plugin. More...
 

Detailed Description

sqlite-based namestore backend

Author
Christian Grothoff

Definition in file plugin_namestore_sqlite.c.

Macro Definition Documentation

◆ BUSY_TIMEOUT_MS

#define BUSY_TIMEOUT_MS   1000

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 1s should ensure that users do not experience huge latencies while at the same time allowing operations to succeed with reasonable probability.

Definition at line 45 of file plugin_namestore_sqlite.c.

◆ LOG_SQLITE

#define LOG_SQLITE (   db,
  level,
  cmd 
)
Value:
do { GNUNET_log_from (level, \
"namestore-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:94
#define GNUNET_log_from(kind, comp,...)
#define _(String)
GNU gettext support macro.
Definition: platform.h:177

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

Definition at line 53 of file plugin_namestore_sqlite.c.

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__)

Definition at line 62 of file plugin_namestore_sqlite.c.

Function Documentation

◆ database_setup()

static int database_setup ( struct Plugin plugin)
static

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

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

Definition at line 123 of file plugin_namestore_sqlite.c.

124 {
125  char *sqlite_filename;
126  struct GNUNET_SQ_ExecuteStatement es[] = {
127  GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
128  GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
129  GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
130  GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
131  GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
132  GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"),
133  GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
134  GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
135  GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
136  " uid INTEGER PRIMARY KEY,"
137  " zone_private_key BLOB NOT NULL,"
138  " pkey BLOB,"
139  " rvalue INT8 NOT NULL,"
140  " record_count INT NOT NULL,"
141  " record_data BLOB NOT NULL,"
142  " label TEXT NOT NULL"
143  ")"),
144  GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
145  "ON ns098records (zone_private_key,pkey)"),
146  GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
147  "ON ns098records (zone_private_key,uid)"),
149  };
150  struct GNUNET_SQ_PrepareStatement ps[] = {
151  GNUNET_SQ_make_prepare ("INSERT INTO ns098records "
152  "(zone_private_key,pkey,rvalue,record_count,record_data,label)"
153  " VALUES (?, ?, ?, ?, ?, ?)",
155  GNUNET_SQ_make_prepare ("DELETE FROM ns098records "
156  "WHERE zone_private_key=? AND label=?",
158  GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
159  " FROM ns098records"
160  " WHERE zone_private_key=? AND pkey=?",
161  &plugin->zone_to_name),
162  GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
163  " FROM ns098records"
164  " WHERE zone_private_key=? AND uid > ?"
165  " ORDER BY uid ASC"
166  " LIMIT ?",
167  &plugin->iterate_zone),
169  "SELECT uid,record_count,record_data,label,zone_private_key"
170  " FROM ns098records"
171  " WHERE uid > ?"
172  " ORDER BY uid ASC"
173  " LIMIT ?",
175  GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
176  " FROM ns098records"
177  " WHERE zone_private_key=? AND label=?",
178  &plugin->lookup_label),
180  };
181 
182  if (GNUNET_OK !=
184  "namestore-sqlite",
185  "FILENAME",
186  &sqlite_filename))
187  {
189  "namestore-sqlite",
190  "FILENAME");
191  return GNUNET_SYSERR;
192  }
193  if (GNUNET_OK !=
194  GNUNET_DISK_file_test (sqlite_filename))
195  {
196  if (GNUNET_OK !=
197  GNUNET_DISK_directory_create_for_file (sqlite_filename))
198  {
199  GNUNET_break (0);
200  GNUNET_free (sqlite_filename);
201  return GNUNET_SYSERR;
202  }
203  }
204 
205  /* Open database and precompile statements */
206  if (SQLITE_OK !=
207  sqlite3_open (sqlite_filename,
208  &plugin->dbh))
209  {
211  _ ("Unable to initialize SQLite: %s.\n"),
212  sqlite3_errmsg (plugin->dbh));
213  GNUNET_free (sqlite_filename);
214  return GNUNET_SYSERR;
215  }
216  GNUNET_break (SQLITE_OK ==
217  sqlite3_busy_timeout (plugin->dbh,
218  BUSY_TIMEOUT_MS));
219  if (GNUNET_OK !=
221  es))
222  {
223  GNUNET_break (0);
225  _ ("Failed to setup database at `%s'\n"),
226  sqlite_filename);
227  GNUNET_free (sqlite_filename);
228  return GNUNET_SYSERR;
229  }
230 
231  if (GNUNET_OK !=
233  ps))
234  {
235  GNUNET_break (0);
237  _ ("Failed to setup database at `%s'\n"),
238  sqlite_filename);
239  GNUNET_free (sqlite_filename);
240  return GNUNET_SYSERR;
241  }
242  return GNUNET_OK;
243 }
struct Plugin * plugin
The process handle to the testbed service.
struct GNUNET_SQ_PrepareStatement GNUNET_SQ_make_prepare(const char *sql, sqlite3_stmt **pstmt)
Create a struct GNUNET_SQ_PrepareStatement
Definition: sq_prepare.c:37
struct GNUNET_SQ_ExecuteStatement GNUNET_SQ_make_execute(const char *sql)
Create a struct GNUNET_SQ_ExecuteStatement where errors are fatal.
Definition: sq_exec.c:36
struct GNUNET_SQ_ExecuteStatement GNUNET_SQ_make_try_execute(const char *sql)
Create a struct GNUNET_SQ_ExecuteStatement where errors should be tolerated.
Definition: sq_exec.c:55
#define GNUNET_SQ_PREPARE_END
Terminator for executable statement list.
enum GNUNET_GenericReturnValue GNUNET_SQ_exec_statements(sqlite3 *dbh, const struct GNUNET_SQ_ExecuteStatement *es)
Request execution of an array of statements es from Postgres.
Definition: sq_exec.c:76
enum GNUNET_GenericReturnValue GNUNET_SQ_prepare(sqlite3 *dbh, const struct GNUNET_SQ_PrepareStatement *ps)
Prepare all statements given in the (NULL,NULL)-terminated array at ps.
Definition: sq_prepare.c:58
#define GNUNET_SQ_EXECUTE_STATEMENT_END
Terminator for executable statement list.
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
Definition: gnunet_common.h:99
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#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.
@ GNUNET_ERROR_TYPE_ERROR
#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 LOG(kind,...)
Information needed to run a list of SQL statements using GNUNET_SQ_exec_statements().
Information needed to run a list of SQL statements using GNUNET_SQ_exec_statements().
sqlite3_stmt * iterate_all_zones
Precompiled SQL for iterate all records within all zones.
sqlite3_stmt * delete_records
Precompiled SQL to deltete existing records.
sqlite3_stmt * store_records
Precompiled SQL to store records.
sqlite3_stmt * zone_to_name
Precompiled SQL to for reverse lookup based on PKEY.
sqlite3_stmt * lookup_label
Precompiled SQL to lookup records based on label.
struct GNUNET_PQ_Context * dbh
Native Postgres database handle.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
sqlite3_stmt * iterate_zone
Precompiled SQL for iterate records within a zone.

References _, BUSY_TIMEOUT_MS, Plugin::cfg, Plugin::dbh, Plugin::delete_records, 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_OK, GNUNET_SQ_exec_statements(), GNUNET_SQ_EXECUTE_STATEMENT_END, GNUNET_SQ_make_execute(), GNUNET_SQ_make_prepare(), GNUNET_SQ_make_try_execute(), GNUNET_SQ_prepare(), GNUNET_SQ_PREPARE_END, GNUNET_SYSERR, Plugin::iterate_all_zones, Plugin::iterate_zone, LOG, Plugin::lookup_label, plugin, Plugin::store_records, and Plugin::zone_to_name.

Referenced by libgnunet_plugin_namestore_sqlite_init().

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 252 of file plugin_namestore_sqlite.c.

253 {
254  int result;
255  sqlite3_stmt *stmt;
256 
257  if (NULL != plugin->store_records)
258  sqlite3_finalize (plugin->store_records);
259  if (NULL != plugin->delete_records)
260  sqlite3_finalize (plugin->delete_records);
261  if (NULL != plugin->iterate_zone)
262  sqlite3_finalize (plugin->iterate_zone);
263  if (NULL != plugin->iterate_all_zones)
264  sqlite3_finalize (plugin->iterate_all_zones);
265  if (NULL != plugin->zone_to_name)
266  sqlite3_finalize (plugin->zone_to_name);
267  if (NULL != plugin->lookup_label)
268  sqlite3_finalize (plugin->lookup_label);
269  result = sqlite3_close (plugin->dbh);
270  if (result == SQLITE_BUSY)
271  {
273  _ (
274  "Tried to close sqlite without finalizing all prepared statements.\n"));
275  stmt = sqlite3_next_stmt (plugin->dbh,
276  NULL);
277  while (NULL != stmt)
278  {
280  "sqlite",
281  "Closing statement %p\n",
282  stmt);
283  result = sqlite3_finalize (stmt);
284  if (result != SQLITE_OK)
286  "sqlite",
287  "Failed to close statement %p: %d\n",
288  stmt,
289  result);
290  stmt = sqlite3_next_stmt (plugin->dbh,
291  NULL);
292  }
293  result = sqlite3_close (plugin->dbh);
294  }
295  if (SQLITE_OK != result)
298  "sqlite3_close");
299 
300 }
static int result
Global testing status.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
#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...

References _, Plugin::dbh, Plugin::delete_records, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_log_from, Plugin::iterate_all_zones, Plugin::iterate_zone, LOG, LOG_SQLITE, Plugin::lookup_label, plugin, result, Plugin::store_records, and Plugin::zone_to_name.

Referenced by libgnunet_plugin_namestore_sqlite_done(), and libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ namestore_sqlite_store_records()

static int namestore_sqlite_store_records ( void *  cls,
const struct GNUNET_IDENTITY_PrivateKey zone_key,
const char *  label,
unsigned int  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

Store a record in the datastore.

Removes any existing record in the same zone with the same name.

Parameters
clsclosure (internal context for the plugin)
zone_keyprivate key of the zone
labelname that is being mapped (at most 255 characters long)
rd_countnumber of entries in rd array
rdarray of records with data to store
Returns
GNUNET_OK on success, else GNUNET_SYSERR

Definition at line 315 of file plugin_namestore_sqlite.c.

321 {
322  struct Plugin *plugin = cls;
323  int n;
325  uint64_t rvalue;
326  ssize_t data_size;
327 
328  memset (&pkey,
329  0,
330  sizeof(pkey));
331  for (unsigned int i = 0; i < rd_count; i++)
332  {
334  "Checking if `%d' is zonekey type\n",
335  rd[i].record_type);
336 
337  if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
338  {
341  rd[i].data_size,
342  rd[i].record_type,
343  &pkey));
345  "Storing delegation zone record value `%s'\n",
347 
348  break;
349  }
350  }
352  UINT64_MAX);
354  rd);
355  if (data_size < 0)
356  {
357  GNUNET_break (0);
358  return GNUNET_SYSERR;
359  }
360  if (data_size > 64 * 65536)
361  {
362  GNUNET_break (0);
363  return GNUNET_SYSERR;
364  }
365  {
366  /* First delete 'old' records */
367  char data[data_size];
368  struct GNUNET_SQ_QueryParam dparams[] = {
372  };
373  ssize_t ret;
374 
376  rd,
377  data_size,
378  data);
379  if ((ret < 0) ||
380  (data_size != ret))
381  {
382  GNUNET_break (0);
383  return GNUNET_SYSERR;
384  }
385  if (GNUNET_OK !=
387  dparams))
388  {
391  "sqlite3_bind_XXXX");
394  return GNUNET_SYSERR;
395  }
396  n = sqlite3_step (plugin->delete_records);
399 
400  if (0 != rd_count)
401  {
402  uint32_t rd_count32 = (uint32_t) rd_count;
403  struct GNUNET_SQ_QueryParam sparams[] = {
407  GNUNET_SQ_query_param_uint32 (&rd_count32),
411  };
412 
413  if (GNUNET_OK !=
415  sparams))
416  {
419  "sqlite3_bind_XXXX");
422  return GNUNET_SYSERR;
423  }
424  n = sqlite3_step (plugin->store_records);
427  }
428  }
429  switch (n)
430  {
431  case SQLITE_DONE:
432  if (0 != rd_count)
434  "sqlite",
435  "Record stored\n");
436  else
438  "sqlite",
439  "Record deleted\n");
440  return GNUNET_OK;
441 
442  case SQLITE_BUSY:
445  "sqlite3_step");
446  return GNUNET_NO;
447 
448  default:
451  "sqlite3_step");
452  return GNUNET_SYSERR;
453  }
454 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
uint32_t data
The data value.
static char * pkey
Public key of the zone to look in, in ASCII.
static const struct GNUNET_IDENTITY_PrivateKey * zone_key
Private key of the zone.
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_uint64(const uint64_t *x)
Generate query parameter for an uint16_t in host byte order.
#define GNUNET_SQ_query_param_auto_from_type(x)
Generate fixed-size query parameter with size determined by variable type.
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:37
void GNUNET_SQ_reset(sqlite3 *dbh, sqlite3_stmt *stmt)
Reset stmt and log error.
Definition: sq.c:132
#define GNUNET_SQ_query_param_end
End of query parameter specification.
Definition: gnunet_sq_lib.h:86
struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_string(const char *ptr)
Generate query parameter for a string.
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).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_IDENTITY_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_zonekey_type(uint32_t type)
Check if this type is one of the supported GNS zone types.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_IDENTITY_PublicKey *z)
Convert a zone key to a string (for printing debug messages).
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
@ GNUNET_ERROR_TYPE_BULK
An identity key as per LSD0001.
Description of a DB query parameter.
Definition: gnunet_sq_lib.h:55
Handle for a plugin.
Definition: block.c:38
char * n
The number of the namespace this node is in.

References data, data_size, Plugin::dbh, Plugin::delete_records, GNUNET_break, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_GNSRECORD_identity_from_data(), GNUNET_GNSRECORD_is_zonekey_type(), GNUNET_GNSRECORD_records_get_size(), GNUNET_GNSRECORD_records_serialize(), GNUNET_GNSRECORD_z2s(), GNUNET_log_from, 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_query_param_string(), GNUNET_SQ_query_param_uint32(), GNUNET_SQ_query_param_uint64(), GNUNET_SQ_reset(), GNUNET_SYSERR, GNUNET_YES, LOG, LOG_SQLITE, Plugin::n, pkey, plugin, ret, Plugin::store_records, and zone_key.

Referenced by libgnunet_plugin_namestore_sqlite_init().

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

◆ get_records_and_call_iterator()

static int get_records_and_call_iterator ( struct Plugin plugin,
sqlite3_stmt *  stmt,
const struct GNUNET_IDENTITY_PrivateKey zone_key,
uint64_t  limit,
GNUNET_NAMESTORE_RecordIterator  iter,
void *  iter_cls 
)
static

The given 'sqlite' statement has been prepared to be run.

It will return a record which should be given to the iterator. Runs the statement and parses the returned record.

Parameters
pluginplugin context
stmtto run (and then clean up)
zone_keyprivate key of the zone
limitmaximum number of results to fetch
iteriterator to call with the result
iter_clsclosure for iter
Returns
GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error

Definition at line 471 of file plugin_namestore_sqlite.c.

478 {
479  int ret;
480  int sret;
481 
482  ret = GNUNET_OK;
483  for (uint64_t i = 0; i < limit; i++)
484  {
485  sret = sqlite3_step (stmt);
486 
487  if (SQLITE_DONE == sret)
488  {
490  "Iteration done (no results)\n");
491  ret = GNUNET_NO;
492  break;
493  }
494  if (SQLITE_ROW != sret)
495  {
498  "sqlite_step");
499  ret = GNUNET_SYSERR;
500  break;
501  }
502 
503  {
504  uint64_t seq;
505  uint32_t record_count;
506  size_t data_size;
507  void *data;
508  char *label;
509  struct GNUNET_IDENTITY_PrivateKey zk;
510  struct GNUNET_SQ_ResultSpec rs[] = {
514  &data_size),
517  };
518  struct GNUNET_SQ_ResultSpec rsx[] = {
522  &data_size),
526  };
527 
529  (NULL == zone_key)
530  ? rsx
531  : rs);
532  if ((GNUNET_OK != ret) ||
533  (record_count > 64 * 1024))
534  {
535  /* sanity check, don't stack allocate far too much just
536  because database might contain a large value here */
537  GNUNET_break (0);
538  ret = GNUNET_SYSERR;
539  break;
540  }
541  else
542  {
544 
545  GNUNET_assert (0 != seq);
546  if (GNUNET_OK !=
548  data,
549  record_count,
550  rd))
551  {
552  GNUNET_break (0);
553  ret = GNUNET_SYSERR;
554  break;
555  }
556  else
557  {
558  if (NULL != zone_key)
559  zk = *zone_key;
560  if (NULL != iter)
561  iter (iter_cls,
562  seq,
563  &zk,
564  label,
565  record_count,
566  rd);
567  }
568  }
570  }
571  }
573  stmt);
574  return ret;
575 }
static uint64_t record_count
Record count.
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:82
void GNUNET_SQ_cleanup_result(struct GNUNET_SQ_ResultSpec *rs)
Free all memory that was allocated in rs during GNUNET_SQ_extract_result().
Definition: sq.c:117
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_string(char **dst)
0-terminated string 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.
int GNUNET_GNSRECORD_records_deserialize(size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest)
Deserialize the given records to the given destination.
#define GNUNET_log(kind,...)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
A private key for an identity as per LSD0001.
Description of a DB result cell.

References data, data_size, Plugin::dbh, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_GNSRECORD_records_deserialize(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SQ_cleanup_result(), GNUNET_SQ_extract_result(), GNUNET_SQ_reset(), GNUNET_SQ_result_spec_auto_from_type, GNUNET_SQ_result_spec_end, GNUNET_SQ_result_spec_string(), GNUNET_SQ_result_spec_uint32(), GNUNET_SQ_result_spec_uint64(), GNUNET_SQ_result_spec_variable_size(), GNUNET_SYSERR, LOG_SQLITE, plugin, record_count, ret, and zone_key.

Referenced by namestore_sqlite_iterate_records(), namestore_sqlite_lookup_records(), and namestore_sqlite_transaction_begin().

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

◆ namestore_sqlite_lookup_records()

static int namestore_sqlite_lookup_records ( void *  cls,
const struct GNUNET_IDENTITY_PrivateKey zone,
const char *  label,
GNUNET_NAMESTORE_RecordIterator  iter,
void *  iter_cls 
)
static

Lookup records in the datastore for which we are the authority.

Parameters
clsclosure (internal context for the plugin)
zoneprivate key of the zone
labelname of the record in the zone
iterfunction to call with the result
iter_clsclosure for iter
Returns
GNUNET_OK on success, GNUNET_NO for no results, else GNUNET_SYSERR

Definition at line 589 of file plugin_namestore_sqlite.c.

595 {
596  struct Plugin *plugin = cls;
597  struct GNUNET_SQ_QueryParam params[] = {
601  };
602 
603  if (NULL == zone)
604  {
605  GNUNET_break (0);
606  return GNUNET_SYSERR;
607  }
608  if (GNUNET_OK !=
610  params))
611  {
613  "sqlite3_bind_XXXX");
616  return GNUNET_SYSERR;
617  }
620  zone,
621  1,
622  iter,
623  iter_cls);
624 }
static char * zone
Name of the zone being managed.
static int get_records_and_call_iterator(struct Plugin *plugin, sqlite3_stmt *stmt, const struct GNUNET_IDENTITY_PrivateKey *zone_key, uint64_t limit, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
The given 'sqlite' statement has been prepared to be run.

References Plugin::dbh, get_records_and_call_iterator(), GNUNET_break, GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_ERROR, GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_auto_from_type, GNUNET_SQ_query_param_end, GNUNET_SQ_query_param_string(), GNUNET_SQ_reset(), GNUNET_SYSERR, LOG_SQLITE, Plugin::lookup_label, plugin, and zone.

Referenced by libgnunet_plugin_namestore_sqlite_init().

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

◆ namestore_sqlite_iterate_records()

static int namestore_sqlite_iterate_records ( void *  cls,
const struct GNUNET_IDENTITY_PrivateKey zone,
uint64_t  serial,
uint64_t  limit,
GNUNET_NAMESTORE_RecordIterator  iter,
void *  iter_cls 
)
static

Iterate over the results for a particular key and zone in the datastore.

Will return at most one result to the iterator.

Parameters
clsclosure (internal context for the plugin)
zonehash of public key of the zone, NULL to iterate over all zones
serialserial number to exclude in the list of all matching records
limitmaximum number of results to return
iterfunction to call with the result
iter_clsclosure for iter
Returns
GNUNET_OK on success, GNUNET_NO if there were no more results, GNUNET_SYSERR on error

Definition at line 640 of file plugin_namestore_sqlite.c.

647 {
648  struct Plugin *plugin = cls;
649  sqlite3_stmt *stmt;
650  int err;
651 
652  if (NULL == zone)
653  {
654  struct GNUNET_SQ_QueryParam params[] = {
658  };
659 
660  stmt = plugin->iterate_all_zones;
661  err = GNUNET_SQ_bind (stmt,
662  params);
663  }
664  else
665  {
666  struct GNUNET_SQ_QueryParam params[] = {
671  };
672 
673  stmt = plugin->iterate_zone;
674  err = GNUNET_SQ_bind (stmt,
675  params);
676  }
677  if (GNUNET_OK != err)
678  {
681  "sqlite3_bind_XXXX");
683  stmt);
684  return GNUNET_SYSERR;
685  }
687  stmt,
688  zone,
689  limit,
690  iter,
691  iter_cls);
692 }

References Plugin::dbh, get_records_and_call_iterator(), GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_ERROR, GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_auto_from_type, GNUNET_SQ_query_param_end, GNUNET_SQ_query_param_uint64(), GNUNET_SQ_reset(), GNUNET_SYSERR, Plugin::iterate_all_zones, Plugin::iterate_zone, LOG_SQLITE, plugin, and zone.

Referenced by libgnunet_plugin_namestore_sqlite_init().

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

◆ namestore_sqlite_zone_to_name()

static int namestore_sqlite_zone_to_name ( void *  cls,
const struct GNUNET_IDENTITY_PrivateKey zone,
const struct GNUNET_IDENTITY_PublicKey value_zone,
GNUNET_NAMESTORE_RecordIterator  iter,
void *  iter_cls 
)
static

Look for an existing PKEY delegation record for a given public key.

Returns at most one result to the iterator.

Parameters
clsclosure (internal context for the plugin)
zoneprivate key of the zone to look up in, never NULL
value_zonepublic key of the target zone (value), never NULL
iterfunction to call with the result
iter_clsclosure for iter
Returns
GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error

Definition at line 707 of file plugin_namestore_sqlite.c.

713 {
714  struct Plugin *plugin = cls;
715  struct GNUNET_SQ_QueryParam params[] = {
719  };
720 
721  if (GNUNET_OK !=
723  params))
724  {
727  "sqlite3_bind_XXXX");
730  return GNUNET_SYSERR;
731  }
733  "Performing reverse lookup for `%s'\n",
734  GNUNET_GNSRECORD_z2s (value_zone));
737  zone,
738  1,
739  iter,
740  iter_cls);
741 }

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ namestore_sqlite_transaction_begin()

static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_begin ( void *  cls,
char **  emsg 
)
static

Begin a transaction for a client.

This locks the database. SQLite is unable to discern between different rows with a specific zone key but the API looks like this anyway. https://www.sqlite.org/lang_transaction.html

Parameters
clsclosure (internal context for the plugin)
emsgerror message set of return code is GNUNET_SYSERR
Returns
GNUNET_YES on success, GNUNET_SYSERR if transaction cannot be started.

Definition at line 707 of file plugin_namestore_sqlite.c.

756 {
757  struct Plugin *plugin = cls;
758  return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "BEGIN IMMEDIATE TRANSACTION;", NULL,
759  NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES;
760 }

References Plugin::dbh, get_records_and_call_iterator(), GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_GNSRECORD_z2s(), GNUNET_OK, GNUNET_SQ_bind(), GNUNET_SQ_query_param_auto_from_type, GNUNET_SQ_query_param_end, GNUNET_SQ_reset(), GNUNET_SYSERR, LOG, LOG_SQLITE, plugin, zone, and Plugin::zone_to_name.

Referenced by libgnunet_plugin_namestore_sqlite_init().

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

◆ namestore_sqlite_transaction_rollback()

static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_rollback ( void *  cls,
char **  emsg 
)
static

Commit a transaction for a client.

This releases the lock on the database.

Parameters
clsclosure (internal context for the plugin)
emsgerror message set of return code is GNUNET_SYSERR
Returns
GNUNET_YES on success, GNUNET_SYSERR if transaction cannot be started.

Definition at line 707 of file plugin_namestore_sqlite.c.

773 {
774  struct Plugin *plugin = cls;
775  return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "ROLLBACK;", NULL,
776  NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES;
777 }

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ namestore_sqlite_transaction_commit()

static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_commit ( void *  cls,
char **  emsg 
)
static

Roll back a transaction for a client.

This releases the lock on the database.

Parameters
clsclosure (internal context for the plugin)
emsgerror message set of return code is GNUNET_SYSERR
Returns
GNUNET_YES on success, GNUNET_SYSERR if transaction cannot be started.

Definition at line 707 of file plugin_namestore_sqlite.c.

790 {
791  struct Plugin *plugin = cls;
792  return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "END TRANSACTION;", NULL,
793  NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES;
794 }

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ libgnunet_plugin_namestore_sqlite_init()

void* libgnunet_plugin_namestore_sqlite_init ( void *  cls)

Entry point for the plugin.

Parameters
clsthe "struct GNUNET_NAMESTORE_PluginEnvironment*"
Returns
NULL on error, otherwise the plugin context

NOTE: Since SQlite does not support SELECT ... FOR UPDATE this is just an alias to lookup_records. The BEGIN IMMEDIATE mechanic currently implicitly ensures this API behaves as it should

Definition at line 803 of file plugin_namestore_sqlite.c.

804 {
805  struct Plugin *plugin;
806  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
808 
809  plugin = GNUNET_new (struct Plugin);
810  plugin->cfg = cfg;
812  {
815  return NULL;
816  }
818  api->cls = plugin;
833  _ ("Sqlite database running\n"));
834  return api;
835 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static int namestore_sqlite_zone_to_name(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const struct GNUNET_IDENTITY_PublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Look for an existing PKEY delegation record for a given public key.
static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_begin(void *cls, char **emsg)
Begin a transaction for a client.
static int namestore_sqlite_iterate_records(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, uint64_t serial, uint64_t limit, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Iterate over the results for a particular key and zone in the datastore.
static void database_shutdown(struct Plugin *plugin)
Shutdown database connection and associate data structures.
static int namestore_sqlite_store_records(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Store a record in the datastore.
static int database_setup(struct Plugin *plugin)
Initialize the database connections and associated data structures (create tables and indices as need...
static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_rollback(void *cls, char **emsg)
Commit a transaction for a client.
static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_commit(void *cls, char **emsg)
Roll back a transaction for a client.
static int namestore_sqlite_lookup_records(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Lookup records in the datastore for which we are the authority.
struct returned by the initialization function of the plugin
int(* lookup_records)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Lookup records in the datastore for which we are the authority.
int(* zone_to_name)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const struct GNUNET_IDENTITY_PublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Look for an existing PKEY delegation record for a given public key.
int(* iterate_records)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, uint64_t serial, uint64_t limit, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Iterate over the results for a particular zone in the datastore.
enum GNUNET_GenericReturnValue(* transaction_begin)(void *cls, char **emsg)
Transaction-based API draft.
int(* store_records)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Store a record in the datastore for which we are the authority.
enum GNUNET_GenericReturnValue(* transaction_commit)(void *cls, char **emsg)
Commit a transaction in the database.
void * cls
Closure to pass to all plugin functions.
enum GNUNET_GenericReturnValue(* transaction_rollback)(void *cls, char **emsg)
Abort and roll back a transaction in the database.
int(* edit_records)(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
Edit records in the datastore for which we are the authority.

References _, cfg, Plugin::cfg, GNUNET_NAMESTORE_PluginFunctions::cls, database_setup(), database_shutdown(), GNUNET_NAMESTORE_PluginFunctions::edit_records, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_new, GNUNET_OK, GNUNET_NAMESTORE_PluginFunctions::iterate_records, LOG, GNUNET_NAMESTORE_PluginFunctions::lookup_records, namestore_sqlite_iterate_records(), namestore_sqlite_lookup_records(), namestore_sqlite_store_records(), namestore_sqlite_transaction_begin(), namestore_sqlite_transaction_commit(), namestore_sqlite_transaction_rollback(), namestore_sqlite_zone_to_name(), plugin, GNUNET_NAMESTORE_PluginFunctions::store_records, GNUNET_NAMESTORE_PluginFunctions::transaction_begin, GNUNET_NAMESTORE_PluginFunctions::transaction_commit, GNUNET_NAMESTORE_PluginFunctions::transaction_rollback, and GNUNET_NAMESTORE_PluginFunctions::zone_to_name.

Here is the call graph for this function:

◆ libgnunet_plugin_namestore_sqlite_done()

void* libgnunet_plugin_namestore_sqlite_done ( void *  cls)

Exit point from the plugin.

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

Definition at line 845 of file plugin_namestore_sqlite.c.

846 {
848  struct Plugin *plugin = api->cls;
849 
851  plugin->cfg = NULL;
853  GNUNET_free (api);
855  "sqlite plugin is finished\n");
856  return NULL;
857 }
void * cls
Closure for all of the callbacks.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47

References Plugin::api, Plugin::cfg, GNUNET_BLOCK_PluginFunctions::cls, GNUNET_NAMESTORE_PluginFunctions::cls, database_shutdown(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, LOG, and plugin.

Here is the call graph for this function: