GNUnet  0.20.0
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 enum GNUNET_GenericReturnValue database_prepare (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 enum GNUNET_GenericReturnValue 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 enum GNUNET_GenericReturnValue 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 enum GNUNET_GenericReturnValue 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 enum GNUNET_GenericReturnValue 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 enum GNUNET_GenericReturnValue 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...
 
static enum GNUNET_GenericReturnValue namestore_sqlite_create_tables (void *cls)
 
static enum GNUNET_GenericReturnValue namestore_sqlite_drop_tables (void *cls)
 
static enum GNUNET_GenericReturnValue database_connect (struct Plugin *plugin)
 Initialize the database connections and associated data structures (create tables and indices as needed as well). 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:97
#define _(String)
GNU gettext support macro.
Definition: platform.h:178

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

Definition at line 53 of file plugin_namestore_sqlite.c.

◆ LOG

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

Definition at line 63 of file plugin_namestore_sqlite.c.

Function Documentation

◆ database_prepare()

static enum GNUNET_GenericReturnValue database_prepare ( 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 1 of file plugin_namestore_sqlite.c.

130 {
131  if (plugin->ready)
132  return GNUNET_OK;
133  struct GNUNET_SQ_ExecuteStatement es[] = {
134  GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
135  GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
136  GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
137  GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
138  GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
139  GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"),
140  GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
141  GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
143  };
144  struct GNUNET_SQ_PrepareStatement ps[] = {
145  GNUNET_SQ_make_prepare ("INSERT INTO ns098records "
146  "(zone_private_key,pkey,rvalue,record_count,record_data,label)"
147  " VALUES (?, ?, ?, ?, ?, ?)",
148  &plugin->store_records),
149  GNUNET_SQ_make_prepare ("DELETE FROM ns098records "
150  "WHERE zone_private_key=? AND label=?",
151  &plugin->delete_records),
152  GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
153  " FROM ns098records"
154  " WHERE zone_private_key=? AND pkey=?",
155  &plugin->zone_to_name),
156  GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
157  " FROM ns098records"
158  " WHERE zone_private_key=? AND uid > ?"
159  " ORDER BY uid ASC"
160  " LIMIT ?",
161  &plugin->iterate_zone),
163  "SELECT uid,record_count,record_data,label,zone_private_key"
164  " FROM ns098records"
165  " WHERE uid > ?"
166  " ORDER BY uid ASC"
167  " LIMIT ?",
168  &plugin->iterate_all_zones),
169  GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
170  " FROM ns098records"
171  " WHERE zone_private_key=? AND label=?",
172  &plugin->lookup_label),
174  };
175 
176  if (GNUNET_OK !=
178  es))
179  {
181  _ ("Failed to setup database with: `%s'\n"),
182  sqlite3_errmsg (plugin->dbh));
183  return GNUNET_SYSERR;
184  }
185  if (GNUNET_OK !=
187  ps))
188  {
189  GNUNET_break (0);
191  _ ("Failed to setup database with: `%s'\n"),
192  sqlite3_errmsg (plugin->dbh));
193  return GNUNET_SYSERR;
194  }
195  plugin->ready = GNUNET_YES;
196  return GNUNET_OK;
197 }
struct TestcasePlugin * 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:38
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:51
#define GNUNET_SQ_EXECUTE_STATEMENT_END
Terminator for executable statement list.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
#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().

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

207 {
208  int result;
209  sqlite3_stmt *stmt;
210 
211  if (NULL != plugin->store_records)
212  sqlite3_finalize (plugin->store_records);
213  if (NULL != plugin->delete_records)
214  sqlite3_finalize (plugin->delete_records);
215  if (NULL != plugin->iterate_zone)
216  sqlite3_finalize (plugin->iterate_zone);
217  if (NULL != plugin->iterate_all_zones)
218  sqlite3_finalize (plugin->iterate_all_zones);
219  if (NULL != plugin->zone_to_name)
220  sqlite3_finalize (plugin->zone_to_name);
221  if (NULL != plugin->lookup_label)
222  sqlite3_finalize (plugin->lookup_label);
223  result = sqlite3_close (plugin->dbh);
224  if (result == SQLITE_BUSY)
225  {
227  _ (
228  "Tried to close sqlite without finalizing all prepared statements.\n"));
229  stmt = sqlite3_next_stmt (plugin->dbh,
230  NULL);
231  while (NULL != stmt)
232  {
234  "sqlite",
235  "Closing statement %p\n",
236  stmt);
237  result = sqlite3_finalize (stmt);
238  if (result != SQLITE_OK)
240  "sqlite",
241  "Failed to close statement %p: %d\n",
242  stmt,
243  result);
244  stmt = sqlite3_next_stmt (plugin->dbh,
245  NULL);
246  }
247  result = sqlite3_close (plugin->dbh);
248  }
249  if (SQLITE_OK != result)
252  "sqlite3_close");
253 
254 }
static int result
Global testing status.
#define GNUNET_log_from(kind, comp,...)
@ 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...

Referenced by libgnunet_plugin_namestore_sqlite_done().

Here is the caller graph for this function:

◆ namestore_sqlite_store_records()

static enum GNUNET_GenericReturnValue 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 206 of file plugin_namestore_sqlite.c.

275 {
276  struct Plugin *plugin = cls;
277  int n;
279  uint64_t rvalue;
280  ssize_t data_size;
281 
283  memset (&pkey,
284  0,
285  sizeof(pkey));
286  for (unsigned int i = 0; i < rd_count; i++)
287  {
289  "Checking if `%d' is zonekey type\n",
290  rd[i].record_type);
291 
292  if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
293  {
296  rd[i].data_size,
297  rd[i].record_type,
298  &pkey));
300  "Storing delegation zone record value `%s'\n",
302 
303  break;
304  }
305  }
307  UINT64_MAX);
309  rd);
310  if (data_size < 0)
311  {
312  GNUNET_break (0);
313  return GNUNET_SYSERR;
314  }
315  if (data_size > 64 * 65536)
316  {
317  GNUNET_break (0);
318  return GNUNET_SYSERR;
319  }
320  {
321  /* First delete 'old' records */
322  char data[data_size];
323  struct GNUNET_SQ_QueryParam dparams[] = {
327  };
328  ssize_t ret;
329 
331  rd,
332  data_size,
333  data);
334  if ((ret < 0) ||
335  (data_size != ret))
336  {
337  GNUNET_break (0);
338  return GNUNET_SYSERR;
339  }
340  if (GNUNET_OK !=
341  GNUNET_SQ_bind (plugin->delete_records,
342  dparams))
343  {
346  "sqlite3_bind_XXXX");
347  GNUNET_SQ_reset (plugin->dbh,
348  plugin->delete_records);
349  return GNUNET_SYSERR;
350  }
351  n = sqlite3_step (plugin->delete_records);
352  GNUNET_SQ_reset (plugin->dbh,
353  plugin->delete_records);
354 
355  if (0 != rd_count)
356  {
357  uint32_t rd_count32 = (uint32_t) rd_count;
358  struct GNUNET_SQ_QueryParam sparams[] = {
362  GNUNET_SQ_query_param_uint32 (&rd_count32),
366  };
367 
368  if (GNUNET_OK !=
369  GNUNET_SQ_bind (plugin->store_records,
370  sparams))
371  {
374  "sqlite3_bind_XXXX");
375  GNUNET_SQ_reset (plugin->dbh,
376  plugin->store_records);
377  return GNUNET_SYSERR;
378  }
379  n = sqlite3_step (plugin->store_records);
380  GNUNET_SQ_reset (plugin->dbh,
381  plugin->store_records);
382  }
383  }
384  switch (n)
385  {
386  case SQLITE_DONE:
387  if (0 != rd_count)
389  "sqlite",
390  "Record stored\n");
391  else
393  "sqlite",
394  "Record deleted\n");
395  return GNUNET_OK;
396 
397  case SQLITE_BUSY:
400  "sqlite3_step");
401  return GNUNET_NO;
402 
403  default:
406  "sqlite3_step");
407  return GNUNET_SYSERR;
408  }
409 }
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.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
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:31
void GNUNET_SQ_reset(sqlite3 *dbh, sqlite3_stmt *stmt)
Reset stmt and log error.
Definition: sq.c:120
#define GNUNET_SQ_query_param_end
End of query parameter specification.
Definition: gnunet_sq_lib.h:87
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 to a string (for printing debug messages).
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_BULK
static enum GNUNET_GenericReturnValue database_prepare(struct Plugin *plugin)
Initialize the database connections and associated data structures (create tables and indices as need...
An identity key as per LSD0001.
Description of a DB query parameter.
Definition: gnunet_sq_lib.h:56
Handle for a plugin.
Definition: block.c:38

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ get_records_and_call_iterator()

static enum GNUNET_GenericReturnValue 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 206 of file plugin_namestore_sqlite.c.

433 {
434  int ret;
435  int sret;
436 
437  ret = GNUNET_OK;
438  for (uint64_t i = 0; i < limit; i++)
439  {
440  sret = sqlite3_step (stmt);
441 
442  if (SQLITE_DONE == sret)
443  {
445  "Iteration done (no results)\n");
446  ret = GNUNET_NO;
447  break;
448  }
449  if (SQLITE_ROW != sret)
450  {
453  "sqlite_step");
454  ret = GNUNET_SYSERR;
455  break;
456  }
457 
458  {
459  uint64_t seq;
460  uint32_t record_count;
461  size_t data_size;
462  void *data;
463  char *label;
464  struct GNUNET_IDENTITY_PrivateKey zk;
465  struct GNUNET_SQ_ResultSpec rs[] = {
469  &data_size),
472  };
473  struct GNUNET_SQ_ResultSpec rsx[] = {
477  &data_size),
481  };
482 
484  (NULL == zone_key)
485  ? rsx
486  : rs);
487  if ((GNUNET_OK != ret) ||
488  (record_count > 64 * 1024))
489  {
490  /* sanity check, don't stack allocate far too much just
491  because database might contain a large value here */
492  GNUNET_break (0);
493  ret = GNUNET_SYSERR;
494  break;
495  }
496  else
497  {
499 
500  GNUNET_assert (0 != seq);
501  if (GNUNET_OK !=
503  data,
504  record_count,
505  rd))
506  {
507  GNUNET_break (0);
508  ret = GNUNET_SYSERR;
509  break;
510  }
511  else
512  {
513  if (NULL != zone_key)
514  zk = *zone_key;
515  if (NULL != iter)
516  iter (iter_cls,
517  seq,
518  &zk,
519  label,
520  record_count,
521  rd);
522  }
523  }
525  }
526  }
527  GNUNET_SQ_reset (plugin->dbh,
528  stmt);
529  return ret;
530 }
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:76
void GNUNET_SQ_cleanup_result(struct GNUNET_SQ_ResultSpec *rs)
Free all memory that was allocated in rs during GNUNET_SQ_extract_result().
Definition: sq.c:105
struct GNUNET_SQ_ResultSpec GNUNET_SQ_result_spec_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,...)
A private key for an identity as per LSD0001.
Description of a DB result cell.

◆ namestore_sqlite_lookup_records()

static enum GNUNET_GenericReturnValue 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 206 of file plugin_namestore_sqlite.c.

550 {
551  struct Plugin *plugin = cls;
553  struct GNUNET_SQ_QueryParam params[] = {
557  };
558 
559  if (NULL == zone)
560  {
561  GNUNET_break (0);
562  return GNUNET_SYSERR;
563  }
564  if (GNUNET_OK !=
565  GNUNET_SQ_bind (plugin->lookup_label,
566  params))
567  {
569  "sqlite3_bind_XXXX");
570  GNUNET_SQ_reset (plugin->dbh,
571  plugin->lookup_label);
572  return GNUNET_SYSERR;
573  }
575  plugin->lookup_label,
576  zone,
577  1,
578  iter,
579  iter_cls);
580 }
static char * zone
Name of the zone being managed.
static enum GNUNET_GenericReturnValue 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.

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ namestore_sqlite_iterate_records()

static enum GNUNET_GenericReturnValue 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 206 of file plugin_namestore_sqlite.c.

603 {
604  struct Plugin *plugin = cls;
605  sqlite3_stmt *stmt;
606  int err;
607 
609  if (NULL == zone)
610  {
611  struct GNUNET_SQ_QueryParam params[] = {
615  };
616 
617  stmt = plugin->iterate_all_zones;
618  err = GNUNET_SQ_bind (stmt,
619  params);
620  }
621  else
622  {
623  struct GNUNET_SQ_QueryParam params[] = {
628  };
629 
630  stmt = plugin->iterate_zone;
631  err = GNUNET_SQ_bind (stmt,
632  params);
633  }
634  if (GNUNET_OK != err)
635  {
638  "sqlite3_bind_XXXX");
639  GNUNET_SQ_reset (plugin->dbh,
640  stmt);
641  return GNUNET_SYSERR;
642  }
644  stmt,
645  zone,
646  limit,
647  iter,
648  iter_cls);
649 }

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ namestore_sqlite_zone_to_name()

static enum GNUNET_GenericReturnValue 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 206 of file plugin_namestore_sqlite.c.

670 {
671  struct Plugin *plugin = cls;
673  struct GNUNET_SQ_QueryParam params[] = {
677  };
678 
679  if (GNUNET_OK !=
680  GNUNET_SQ_bind (plugin->zone_to_name,
681  params))
682  {
685  "sqlite3_bind_XXXX");
686  GNUNET_SQ_reset (plugin->dbh,
687  plugin->zone_to_name);
688  return GNUNET_SYSERR;
689  }
691  "Performing reverse lookup for `%s'\n",
692  GNUNET_GNSRECORD_z2s (value_zone));
694  plugin->zone_to_name,
695  zone,
696  1,
697  iter,
698  iter_cls);
699 }

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

715 {
716  struct Plugin *plugin = cls;
717  int rc;
718  char *sqlEmsg;
719 
721  rc = sqlite3_exec (plugin->dbh, "BEGIN IMMEDIATE TRANSACTION;",
722  NULL, NULL, &sqlEmsg);
723  if (SQLITE_OK != rc)
724  {
725  *emsg = GNUNET_strdup (sqlEmsg);
726  sqlite3_free (sqlEmsg);
727  }
728  return (SQLITE_OK != rc) ? GNUNET_SYSERR : GNUNET_YES;
729 }
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.

Referenced by libgnunet_plugin_namestore_sqlite_init().

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

743 {
744  struct Plugin *plugin = cls;
745  int rc;
746  char *sqlEmsg;
747 
749  rc = sqlite3_exec (plugin->dbh, "ROLLBACK;",
750  NULL, NULL, &sqlEmsg);
751  if (SQLITE_OK != rc)
752  {
753  *emsg = GNUNET_strdup (sqlEmsg);
754  sqlite3_free (sqlEmsg);
755  }
756  return (SQLITE_OK != rc) ? GNUNET_SYSERR : GNUNET_YES;
757 }

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

771 {
772  struct Plugin *plugin = cls;
773  int rc;
774  char *sqlEmsg;
775 
777  rc = sqlite3_exec (plugin->dbh, "END TRANSACTION;",
778  NULL, NULL, &sqlEmsg);
779  if (SQLITE_OK != rc)
780  {
781  *emsg = GNUNET_strdup (sqlEmsg);
782  sqlite3_free (sqlEmsg);
783  }
784  return (SQLITE_OK != rc) ? GNUNET_SYSERR : GNUNET_YES;
785 }

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ namestore_sqlite_create_tables()

static enum GNUNET_GenericReturnValue namestore_sqlite_create_tables ( void *  cls)
static

Definition at line 206 of file plugin_namestore_sqlite.c.

790 {
791  struct Plugin *plugin = cls;
792  struct GNUNET_SQ_ExecuteStatement es[] = {
793  GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
794  GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
795  GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
796  GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
797  GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
798  GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"),
799  GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
800  GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
801  GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
802  " uid INTEGER PRIMARY KEY,"
803  " zone_private_key BLOB NOT NULL,"
804  " pkey BLOB,"
805  " rvalue INT8 NOT NULL,"
806  " record_count INT NOT NULL,"
807  " record_data BLOB NOT NULL,"
808  " label TEXT NOT NULL"
809  ")"),
810  GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_reverse "
811  "ON ns098records (zone_private_key,pkey)"),
812  GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_iter "
813  "ON ns098records (zone_private_key,uid)"),
815  };
816 
817  if (GNUNET_OK !=
819  es))
820  {
822  "Failed to setup database with: `%s'\n",
823  sqlite3_errmsg (plugin->dbh));
824  return GNUNET_SYSERR;
825  }
826  return GNUNET_OK;
827 }
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

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ namestore_sqlite_drop_tables()

static enum GNUNET_GenericReturnValue namestore_sqlite_drop_tables ( void *  cls)
static

Definition at line 206 of file plugin_namestore_sqlite.c.

832 {
833  struct Plugin *plugin = cls;
834  struct GNUNET_SQ_ExecuteStatement es_drop[] = {
835  GNUNET_SQ_make_execute ("DROP TABLE IF EXISTS ns098records"),
837  };
838 
839  if (GNUNET_OK !=
841  es_drop))
842  {
844  "Failed to drop database with: `%s'\n",
845  sqlite3_errmsg (plugin->dbh));
846  return GNUNET_SYSERR;
847  }
848  return GNUNET_OK;
849 }

Referenced by libgnunet_plugin_namestore_sqlite_init().

Here is the caller graph for this function:

◆ database_connect()

static enum GNUNET_GenericReturnValue database_connect ( 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 206 of file plugin_namestore_sqlite.c.

862 {
863  char *sqlite_filename;
864 
865  if (GNUNET_OK !=
867  "namestore-sqlite",
868  "FILENAME",
869  &sqlite_filename))
870  {
872  "namestore-sqlite",
873  "FILENAME");
874  return GNUNET_SYSERR;
875  }
876  if (GNUNET_OK !=
877  GNUNET_DISK_file_test (sqlite_filename))
878  {
879  if (GNUNET_OK !=
880  GNUNET_DISK_directory_create_for_file (sqlite_filename))
881  {
882  GNUNET_break (0);
883  GNUNET_free (sqlite_filename);
884  return GNUNET_SYSERR;
885  }
886  }
887 
888  /* Open database and precompile statements */
889  if ((NULL == plugin->dbh) &&
890  (SQLITE_OK != sqlite3_open (sqlite_filename,
891  &plugin->dbh)))
892  {
894  _ ("Unable to initialize SQLite: %s.\n"),
895  sqlite3_errmsg (plugin->dbh));
896  GNUNET_free (sqlite_filename);
897  return GNUNET_SYSERR;
898  }
899  GNUNET_free (sqlite_filename);
900  GNUNET_break (SQLITE_OK ==
901  sqlite3_busy_timeout (plugin->dbh,
902  BUSY_TIMEOUT_MS));
903  if (GNUNET_YES ==
905  "namestore-sqlite",
906  "INIT_ON_CONNECT"))
907  {
908  if (GNUNET_OK !=
910  return GNUNET_SYSERR;
911  }
912  return GNUNET_OK;
913 }
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_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
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
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...
static enum GNUNET_GenericReturnValue namestore_sqlite_create_tables(void *cls)

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

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

924 {
925  struct Plugin *plugin;
926  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
928 
929  plugin = GNUNET_new (struct Plugin);
930  plugin->cfg = cfg;
932  {
934  "Database could not be connected to.\n");
936  return NULL;
937  }
939  api->cls = plugin;
956  _ ("SQlite database running\n"));
957  return api;
958 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static enum GNUNET_GenericReturnValue namestore_sqlite_transaction_begin(void *cls, char **emsg)
Begin a transaction for a client.
static enum GNUNET_GenericReturnValue 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.
static enum GNUNET_GenericReturnValue namestore_sqlite_drop_tables(void *cls)
static enum GNUNET_GenericReturnValue 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 enum GNUNET_GenericReturnValue 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 enum GNUNET_GenericReturnValue namestore_sqlite_transaction_rollback(void *cls, char **emsg)
Commit a transaction for a client.
static enum GNUNET_GenericReturnValue 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_commit(void *cls, char **emsg)
Roll back a transaction for a client.
static enum GNUNET_GenericReturnValue database_connect(struct Plugin *plugin)
Initialize the database connections and associated data structures (create tables and indices as need...
struct returned by the initialization function of the plugin
enum GNUNET_GenericReturnValue(* create_tables)(void *cls)
Setup the database.
enum GNUNET_GenericReturnValue(* 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(* 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.
enum GNUNET_GenericReturnValue(* transaction_begin)(void *cls, char **emsg)
Transaction-based API draft.
enum GNUNET_GenericReturnValue(* 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(* 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.
enum GNUNET_GenericReturnValue(* drop_tables)(void *cls)
Drop existing tables.
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.
enum GNUNET_GenericReturnValue(* 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, GNUNET_NAMESTORE_PluginFunctions::cls, GNUNET_NAMESTORE_PluginFunctions::create_tables, database_connect(), GNUNET_NAMESTORE_PluginFunctions::drop_tables, GNUNET_NAMESTORE_PluginFunctions::edit_records, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_new, GNUNET_OK, GNUNET_NAMESTORE_PluginFunctions::iterate_records, LOG, GNUNET_NAMESTORE_PluginFunctions::lookup_records, namestore_sqlite_create_tables(), namestore_sqlite_drop_tables(), 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 968 of file plugin_namestore_sqlite.c.

969 {
971  struct Plugin *plugin = api->cls;
972 
974  plugin->cfg = NULL;
976  GNUNET_free (api);
978  "SQlite plugin is finished\n");
979  return NULL;
980 }
static void database_shutdown(struct Plugin *plugin)
Shutdown database connection and associate data structures.
void * cls
Closure for all of the callbacks.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47

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

Here is the call graph for this function: