gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated (003cc0ea2 -> dcc8fea2f)


From: gnunet
Subject: [gnunet] branch master updated (003cc0ea2 -> dcc8fea2f)
Date: Fri, 30 Sep 2022 17:42:05 +0200

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a change to branch master
in repository gnunet.

    from 003cc0ea2 [history] Mark old logos in `contrib/branding/logo/` as 
`old-` and add svg
     new c3eca4a0a NAMESTORE: Add DB setup utility with SQlite support; PQ 
broken
     new 51b6cf4d3 NAMESTORE: Add postgres functions for DB setup utility
     new 2754420df -fix
     new 6021469a1 NAMESTORE: Add manpage for new database CLI
     new 821fc8866 -file
     new dcc8fea2f Merge branch 'master' of git+ssh://git.gnunet.org/gnunet

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 doc/man/Makefile.am                                |   1 +
 ...gnunet-resolver.1 => gnunet-namestore-dbtool.1} |  38 ++--
 src/include/gnunet_namestore_plugin.h              |  22 ++
 src/namestore/.gitignore                           |   1 +
 src/namestore/Makefile.am                          |   9 +
 src/namestore/gnunet-namestore-dbtool.c            | 189 ++++++++++++++++
 src/namestore/gnunet-service-namestore.c           |  77 +++++--
 src/namestore/plugin_namestore_postgres.c          | 215 +++++++++++++-----
 src/namestore/plugin_namestore_sqlite.c            | 243 +++++++++++++++------
 src/namestore/test_common.c                        |  10 +
 src/namestore/test_namestore_api_postgres.conf     |   1 +
 src/namestore/test_namestore_api_sqlite.conf       |   1 +
 12 files changed, 650 insertions(+), 157 deletions(-)
 copy doc/man/{gnunet-resolver.1 => gnunet-namestore-dbtool.1} (73%)
 create mode 100644 src/namestore/gnunet-namestore-dbtool.c

diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 4050ae896..af781bba4 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -61,6 +61,7 @@ man_MANS = \
   gnunet-namecache.1 \
   gnunet-namestore.1 \
   gnunet-namestore-fcfsd.1 \
+  gnunet-namestore-dbtool.1 \
   gnunet-nat.1 \
   gnunet-nat-auto.1 \
   gnunet-nat-server.1 \
diff --git a/doc/man/gnunet-resolver.1 b/doc/man/gnunet-namestore-dbtool.1
similarity index 73%
copy from doc/man/gnunet-resolver.1
copy to doc/man/gnunet-namestore-dbtool.1
index 8dc63ff06..af882209b 100644
--- a/doc/man/gnunet-resolver.1
+++ b/doc/man/gnunet-namestore-dbtool.1
@@ -1,5 +1,5 @@
 .\" This file is part of GNUnet.
-.\" Copyright (C) 2001-2019 GNUnet e.V.
+.\" Copyright (C) 2001-2022 GNUnet e.V.
 .\"
 .\" Permission is granted to copy, distribute and/or modify this document
 .\" under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -21,42 +21,48 @@
 .\"
 .\" SPDX-License-Identifier: GPL3.0-or-later OR FDL1.3-or-later
 .\"
-.Dd January 4, 2012
-.Dt GNUNET-RESOLVER 1
+.Dd September 30, 2022
+.Dt GNUNET-NAMESTORE-DBTOOL 1
 .Os
 .Sh NAME
-.Nm gnunet-resolver
-.Nd built-in GNUnet stub resolver
+.Nm gnunet-namestore-dbtool
+.Nd manipulate GNU Name System (GNS) namestore database
 .Sh SYNOPSIS
 .Nm
+.Op Fl i | -initialize
 .Op Fl c Ar FILENAME | Fl -config= Ns Ar FILENAME
+.Op Fl r | -reset
 .Op Fl h | -help
 .Op Fl L Ar LOGLEVEL | Fl -loglevel= Ns Ar LOGLEVEL
-.Op Fl l Ar LOGFILE | Fl -logfile= Ns Ar LOGFILE
-.Op Fl r | -reverse
+.Op Fl p Ar PLUGIN | Fl -plugin= Ns Ar PLUGIN
 .Op Fl v | -version
-.Ao Ar hostname Ac
 .Sh DESCRIPTION
 .Nm
-allows you to use the built-in GNUnet stub resolver.
+can be used to initialize or reset the namestore database.
+.Pp
+The options are as follows:
 .Bl -tag -width indent
-.It Fl c Ar FILENAME | Fl -config= Ns Ar FILENAME
-Use the configuration file FILENAME.
+.It Fl i | -initialize
+Desired operation is initialization of a database.
+.It Fl p Ar PLUGINNAME | Fl -plugin= Ns Ar PLUGINNAME
+Use the plugin PLUGINNAME.
+.It Fl r | -reset
+Desired operation is reset and reinitialization of a database
 .It Fl h | -help
 Print short help on options.
 .It Fl L Ar LOGLEVEL | Fl -loglevel= Ns Ar LOGLEVEL
 Use LOGLEVEL for logging.
 Valid values are DEBUG, INFO, WARNING and ERROR.
-.It Fl l Ar LOGFILE | Fl -logfile= Ns Ar LOGFILE
-Configure logging to write logs to LOGFILE.
-.It Fl r | -reverse
-Perform a reverse lookup.
 .It Fl v | -version
 Print GNUnet version number.
 .El
 .\".Sh EXAMPLES
+.\".Sh FILES
 .Sh SEE ALSO
-The full documentation for gnunet is maintained as a Texinfo manual.
+.Xr gnunet-gns 1 ,
+.Xr gnunet-namestore 1
+.sp
+The full documentation for GNUnet is maintained as a Texinfo manual.
 If the
 .Xr info 1
 and gnunet programs are properly installed at your site, the command
diff --git a/src/include/gnunet_namestore_plugin.h 
b/src/include/gnunet_namestore_plugin.h
index 5e8ac3203..1df0a5eb0 100644
--- a/src/include/gnunet_namestore_plugin.h
+++ b/src/include/gnunet_namestore_plugin.h
@@ -205,6 +205,28 @@ struct GNUNET_NAMESTORE_PluginFunctions
                      GNUNET_NAMESTORE_RecordIterator iter,
                      void *iter_cls);
 
+  /**
+   * Setup the database.
+   * Note that this will also fail if the database is already initialized.
+   * See reset_database().
+   *
+   * @param cls closure (internal context for the plugin)
+   * @param emsg error message on failure. Will be allocated, must be freed.
+   * @return #GNUNET_OK on success, else fails with #GNUNET_SYSERR
+   */
+  int
+  (*initialize_database) (void *cls, char **emsg);
+
+  /**
+   * Re-initializes the database.
+   * DANGEROUS: All existing data in the dabase will be lost!
+   *
+   * @param cls closure (internal context for the plugin)
+   * @param emsg error message on failure. Will be allocated, must be freed.
+   * @return #GNUNET_OK on success, else fails with #GNUNET_SYSERR
+   */
+  int
+  (*reset_database) (void *cls, char **emsg);
 };
 
 
diff --git a/src/namestore/.gitignore b/src/namestore/.gitignore
index b6a968d61..907361276 100644
--- a/src/namestore/.gitignore
+++ b/src/namestore/.gitignore
@@ -1,5 +1,6 @@
 gnunet-service-namestore
 gnunet-namestore
+gnunet-namestore-dbtool
 gnunet-namestore-fcfsd
 test_namestore_api_lookup_nick.nc
 test_namestore_api_lookup_private.nc
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index 5142058ad..d5e110206 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -90,6 +90,7 @@ libexec_PROGRAMS = \
 
 bin_PROGRAMS = \
  gnunet-namestore \
+ gnunet-namestore-dbtool \
  gnunet-zoneimport
 
 libexec_PROGRAMS += \
@@ -153,6 +154,14 @@ gnunet_namestore_LDADD = \
   libgnunetnamestore.la \
   $(GN_LIBINTL)
 
+gnunet_namestore_dbtool_SOURCES = \
+ gnunet-namestore-dbtool.c
+gnunet_namestore_dbtool_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  libgnunetnamestore.la \
+  $(GN_LIBINTL)
+
+
 
 gnunet_namestore_fcfsd_SOURCES = \
  gnunet-namestore-fcfsd.c
diff --git a/src/namestore/gnunet-namestore-dbtool.c 
b/src/namestore/gnunet-namestore-dbtool.c
new file mode 100644
index 000000000..b0f7e2ab9
--- /dev/null
+++ b/src/namestore/gnunet-namestore-dbtool.c
@@ -0,0 +1,189 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012, 2013, 2014, 2019, 2022 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file gnunet-namestore-dbtool.c
+ * @brief command line tool to manipulate the database backends for the 
namestore
+ * @author Martin Schanzenbach
+ *
+ */
+#include "platform.h"
+#include <gnunet_util_lib.h>
+#include <gnunet_namestore_plugin.h>
+
+/**
+ * Name of the plugin argument
+ */
+static char *pluginname;
+
+/**
+ * Reset argument
+ */
+static int reset;
+
+/**
+ * Initialize argument
+ */
+static int init;
+
+/**
+ * Return code
+ */
+static int ret = 0;
+
+/**
+ * Task run on shutdown.  Cleans up everything.
+ *
+ * @param cls unused
+ */
+static void
+do_shutdown (void *cls)
+{
+  (void) cls;
+  if (NULL != pluginname)
+    GNUNET_free (pluginname);
+}
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  const char *pkey_str;
+  char *db_lib_name;
+  char *emsg;
+  struct GNUNET_NAMESTORE_PluginFunctions *plugin;
+
+  (void) cls;
+  (void) args;
+  (void) cfgfile;
+  if (NULL != args[0])
+    GNUNET_log (
+      GNUNET_ERROR_TYPE_WARNING,
+      _ ("Superfluous command line arguments (starting with `%s') ignored\n"),
+      args[0]);
+
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg);
+  if (NULL == pluginname)
+  {
+    fprintf (stderr, "No plugin given!\n");
+    ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", pluginname);
+  plugin = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
+  if (NULL == plugin)
+  {
+    fprintf (stderr, "Failed to load %s!\n", db_lib_name);
+    ret = 1;
+    GNUNET_SCHEDULER_shutdown ();
+    GNUNET_free (db_lib_name);
+    return;
+  }
+  if (reset)
+  {
+    if (GNUNET_OK != plugin->reset_database (plugin->cls, &emsg))
+    {
+      // FIXME do we want to return a reason?
+      fprintf (stderr, "Failed to reset database: %s\n",
+               emsg);
+      ret = 1;
+      GNUNET_free (emsg);
+      GNUNET_free (db_lib_name);
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+  }
+  else if (init)
+  {
+    if (GNUNET_OK != plugin->initialize_database (plugin->cls, &emsg))
+    {
+      // FIXME do we want to return a reason?
+      fprintf (stderr, "Failed to initialize database: %s\n",
+               emsg);
+      ret = 1;
+      GNUNET_free (emsg);
+      GNUNET_free (db_lib_name);
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+  }
+  GNUNET_SCHEDULER_shutdown ();
+  GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, plugin));
+  GNUNET_free (db_lib_name);
+}
+
+
+/**
+ * The main function for gnunet-namestore-dbtool.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] =
+  { GNUNET_GETOPT_option_flag ('i', "init", gettext_noop (
+                                 "initialize database"), &init),
+    GNUNET_GETOPT_option_flag ('r',
+                               "reset",
+                               gettext_noop (
+                                 "reset database (DANGEROUS: All existing data 
is lost!"),
+                               &reset),
+    GNUNET_GETOPT_option_string (
+      'p',
+      "plugin",
+      "PLUGIN",
+      gettext_noop (
+        "the namestore plugin to work with, e.g. 'sqlite'"),
+      &pluginname),
+    GNUNET_GETOPT_OPTION_END };
+  int lret;
+
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+    return 2;
+
+  GNUNET_log_setup ("gnunet-namestore-dbtool", "WARNING", NULL);
+  if (GNUNET_OK !=
+      (lret = GNUNET_PROGRAM_run (argc,
+                                  argv,
+                                  "gnunet-namestore-dbtool",
+                                  _ (
+                                    "GNUnet namestore database manipulation 
tool"),
+                                  options,
+                                  &run,
+                                  NULL)))
+  {
+    GNUNET_free_nz ((void *) argv);
+    return lret;
+  }
+  GNUNET_free_nz ((void *) argv);
+  return ret;
+}
diff --git a/src/namestore/gnunet-service-namestore.c 
b/src/namestore/gnunet-service-namestore.c
index 0a3dfea25..36f6d337c 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -137,10 +137,15 @@ struct NamestoreClient
   struct GNUNET_SERVICE_Client *client;
 
   /**
-   * Database handle
+   * Database handle for client
    */
   struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
 
+  /**
+   * Name of loaded plugin (neeed for cleanup)
+   */
+  char *db_lib_name;
+
   /**
    * Message queue for transmission to @e client
    */
@@ -372,6 +377,12 @@ static struct GNUNET_NAMECACHE_Handle *namecache;
  */
 static char *db_lib_name;
 
+/**
+ * Database handle for service
+ */
+struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
+
+
 /**
  * Head of cop DLL.
  */
@@ -446,8 +457,6 @@ cleanup_task (void *cls)
     GNUNET_NAMECACHE_disconnect (namecache);
     namecache = NULL;
   }
-  GNUNET_free (db_lib_name);
-  db_lib_name = NULL;
   if (NULL != monitor_nc)
   {
     GNUNET_notification_context_destroy (monitor_nc);
@@ -458,6 +467,9 @@ cleanup_task (void *cls)
     GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
     statistics = NULL;
   }
+  GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
+  GNUNET_free (db_lib_name);
+  db_lib_name = NULL;
 }
 
 
@@ -574,8 +586,7 @@ cache_nick (const struct GNUNET_IDENTITY_PrivateKey *zone,
  * @return NULL if no NICK record was found
  */
 static struct GNUNET_GNSRECORD_Data *
-get_nick_record (const struct NamestoreClient *nc,
-                 const struct GNUNET_IDENTITY_PrivateKey *zone)
+get_nick_record (const struct GNUNET_IDENTITY_PrivateKey *zone)
 {
   struct GNUNET_IDENTITY_PublicKey pub;
   struct GNUNET_GNSRECORD_Data *nick;
@@ -599,11 +610,11 @@ get_nick_record (const struct NamestoreClient *nc,
   }
 
   nick = NULL;
-  res = nc->GSN_database->lookup_records (nc->GSN_database->cls,
-                                          zone,
-                                          GNUNET_GNS_EMPTY_LABEL_AT,
-                                          &lookup_nick_it,
-                                          &nick);
+  res = GSN_database->lookup_records (GSN_database->cls,
+                                      zone,
+                                      GNUNET_GNS_EMPTY_LABEL_AT,
+                                      &lookup_nick_it,
+                                      &nick);
   if ((GNUNET_OK != res) || (NULL == nick))
   {
 #if ! defined(GNUNET_CULL_LOGGING)
@@ -753,7 +764,7 @@ send_lookup_response_with_filter (struct NamestoreClient 
*nc,
   char *rd_ser;
   char *emsg;
 
-  nick = get_nick_record (nc, zone_key);
+  nick = get_nick_record (zone_key);
   GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd));
 
   if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (name,
@@ -996,7 +1007,7 @@ refresh_block (struct NamestoreClient *nc,
     rd_clean[rd_count_clean++] = rd[i];
   }
 
-  nick = get_nick_record (nc, zone_key);
+  nick = get_nick_record (zone_key);
   res_count = rd_count_clean;
   res = (struct GNUNET_GNSRECORD_Data *) rd_clean;  /* fixme: a bit unclean... 
*/
   if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
@@ -1229,7 +1240,8 @@ client_disconnect_cb (void *cls,
   for (cop = cop_head; NULL != cop; cop = cop->next)
     if (nc == cop->nc)
       cop->nc = NULL;
-  GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, nc->GSN_database));
+  GNUNET_break (NULL == GNUNET_PLUGIN_unload (nc->db_lib_name, 
nc->GSN_database));
+  GNUNET_free (nc->db_lib_name);
   GNUNET_free (nc);
 }
 
@@ -1249,7 +1261,6 @@ client_connect_cb (void *cls,
 {
   struct NamestoreClient *nc;
   char *database;
-  char *db_lib_name;
 
   (void) cls;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
@@ -1261,9 +1272,12 @@ client_connect_cb (void *cls,
                                                           "namestore",
                                                           "database",
                                                           &database))
+  {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
-  GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading %s\n", db_lib_name);
+    GNUNET_free (nc);
+    return NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name);
   nc->GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
   GNUNET_free (database);
   if (NULL == nc->GSN_database)
@@ -1271,12 +1285,11 @@ client_connect_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Could not load database backend `%s'\n",
                 db_lib_name);
-    GNUNET_free (db_lib_name);
     GNUNET_free (nc);
     return NULL;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loaded %s\n", db_lib_name);
-  GNUNET_free (db_lib_name);
+  nc->db_lib_name = GNUNET_strdup (db_lib_name);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded %s\n", db_lib_name);
   return nc;
 }
 
@@ -1487,7 +1500,7 @@ handle_record_lookup (void *cls, const struct 
LabelLookupMessage *ll_msg)
   rlc.res_rd_count = 0;
   rlc.res_rd = NULL;
   rlc.rd_ser_len = 0;
-  rlc.nick = get_nick_record (nc, &ll_msg->zone);
+  rlc.nick = get_nick_record (&ll_msg->zone);
   if (GNUNET_YES != ntohl (ll_msg->is_edit_request))
     res = nc->GSN_database->lookup_records (nc->GSN_database->cls,
                                             &ll_msg->zone,
@@ -2469,6 +2482,7 @@ run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *cfg,
      struct GNUNET_SERVICE_Handle *service)
 {
+  char *database;
   (void) cls;
   (void) service;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
@@ -2484,6 +2498,29 @@ run (void *cls,
     GNUNET_assert (NULL != namecache);
   }
   statistics = GNUNET_STATISTICS_create ("namestore", cfg);
+  /* Loading database plugin */
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                          "namestore",
+                                                          "database",
+                                                          &database))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
+    GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
+    return;
+  }
+  GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name);
+  GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
+  GNUNET_free (database);
+  if (NULL == GSN_database)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Could not load database backend `%s'\n",
+                db_lib_name);
+    GNUNET_free (db_lib_name);
+    GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
+    return;
+  }
   GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
 }
 
diff --git a/src/namestore/plugin_namestore_postgres.c 
b/src/namestore/plugin_namestore_postgres.c
index 510d24496..6e5c1c718 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_postgres.c
@@ -44,6 +44,11 @@ struct Plugin
    */
   const struct GNUNET_CONFIGURATION_Handle *cfg;
 
+  /**
+   * Database is prepared and ready
+   */
+  int ready;
+
   /**
    * Postgres database handle.
    */
@@ -60,11 +65,11 @@ struct Plugin
  * @return #GNUNET_OK on success
  */
 static int
-database_setup (struct Plugin *plugin)
+init_database (struct Plugin *plugin, char **emsg, int drop)
 {
   struct GNUNET_PQ_ExecuteStatement es_temporary =
     GNUNET_PQ_make_execute (
-      "CREATE TEMPORARY TABLE IF NOT EXISTS ns098records ("
+      "CREATE TEMPORARY TABLE ns098records ("
       " seq BIGSERIAL PRIMARY KEY,"
       " zone_private_key BYTEA NOT NULL DEFAULT '',"
       " pkey BYTEA DEFAULT '',"
@@ -75,7 +80,7 @@ database_setup (struct Plugin *plugin)
       " CONSTRAINT zl UNIQUE (zone_private_key,label)"
       ")");
   struct GNUNET_PQ_ExecuteStatement es_default =
-    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
+    GNUNET_PQ_make_execute ("CREATE TABLE ns098records ("
                             " seq BIGSERIAL PRIMARY KEY,"
                             " zone_private_key BYTEA NOT NULL DEFAULT '',"
                             " pkey BYTEA DEFAULT '',"
@@ -87,18 +92,15 @@ database_setup (struct Plugin *plugin)
                             ")");
   const struct GNUNET_PQ_ExecuteStatement *cr;
   struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END;
-
+  struct GNUNET_PQ_ExecuteStatement es_drop =
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS ns098records");
   if (GNUNET_YES ==
       GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
                                             "namestore-postgres",
                                             "TEMPORARY_TABLE"))
-  {
     cr = &es_temporary;
-  }
   else
-  {
     cr = &es_default;
-  }
 
   if (GNUNET_YES ==
       GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
@@ -120,50 +122,134 @@ database_setup (struct Plugin *plugin)
       sc,
       GNUNET_PQ_EXECUTE_STATEMENT_END
     };
-    struct GNUNET_PQ_PreparedStatement ps[] = {
-      GNUNET_PQ_make_prepare ("store_records",
-                              "INSERT INTO ns098records"
-                              " (zone_private_key, pkey, rvalue, record_count, 
record_data, label)"
-                              " VALUES ($1, $2, $3, $4, $5, $6)"
-                              " ON CONFLICT ON CONSTRAINT zl"
-                              " DO UPDATE"
-                              "    SET 
pkey=$2,rvalue=$3,record_count=$4,record_data=$5"
-                              "    WHERE ns098records.zone_private_key = $1"
-                              "          AND ns098records.label = $6",
-                              6),
-      GNUNET_PQ_make_prepare ("delete_records",
-                              "DELETE FROM ns098records "
-                              "WHERE zone_private_key=$1 AND label=$2",
-                              2),
-      GNUNET_PQ_make_prepare ("zone_to_name",
-                              "SELECT seq,record_count,record_data,label FROM 
ns098records"
-                              " WHERE zone_private_key=$1 AND pkey=$2",
-                              2),
-      GNUNET_PQ_make_prepare ("iterate_zone",
-                              "SELECT seq,record_count,record_data,label FROM 
ns098records "
-                              "WHERE zone_private_key=$1 AND seq > $2 ORDER BY 
seq ASC LIMIT $3",
-                              3),
-      GNUNET_PQ_make_prepare ("iterate_all_zones",
-                              "SELECT 
seq,record_count,record_data,label,zone_private_key"
-                              " FROM ns098records WHERE seq > $1 ORDER BY seq 
ASC LIMIT $2",
-                              2),
-      GNUNET_PQ_make_prepare ("lookup_label",
-                              "SELECT seq,record_count,record_data,label "
-                              "FROM ns098records WHERE zone_private_key=$1 AND 
label=$2",
-                              2),
-      GNUNET_PQ_make_prepare ("edit_set",
-                              "SELECT seq,record_count,record_data,label "
-                              "FROM ns098records WHERE zone_private_key=$1 AND 
label=$2 FOR UPDATE NOWAIT",
-                              2),
-      GNUNET_PQ_PREPARED_STATEMENT_END
+    struct GNUNET_PQ_ExecuteStatement es_alt[] = {
+      es_drop,
+      *cr,
+      GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
+                                  "ON ns098records (zone_private_key,pkey)"),
+      GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
+                                  "ON ns098records (zone_private_key,seq)"),
+      GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label "
+                                  "ON ns098records (label)"),
+      GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label "
+                                  "ON ns098records (zone_private_key,label)"),
+      sc,
+      GNUNET_PQ_EXECUTE_STATEMENT_END
     };
+    if (GNUNET_NO == drop)
+    {
+      plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
+                                                "namestore-postgres",
+                                                NULL,
+                                                es,
+                                                NULL);
+    }
+    else {
+      plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
+                                                "namestore-postgres",
+                                                NULL,
+                                                es_alt,
+                                                NULL);
+    }
+  }
+  if (NULL == plugin->dbh)
+  {
+    *emsg = GNUNET_strdup ("Failed to connect to PQ database");
+    return GNUNET_SYSERR;
+  }
+  GNUNET_PQ_disconnect (plugin->dbh);
+  plugin->dbh = NULL;
+  return GNUNET_OK;
+}
 
-    plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
-                                              "namestore-postgres",
-                                              NULL,
-                                              es,
-                                              ps);
+static int
+database_prepare (struct Plugin *plugin)
+{
+  enum GNUNET_GenericReturnValue ret;
+  if (GNUNET_YES == plugin->ready)
+    return GNUNET_OK;
+  struct GNUNET_PQ_PreparedStatement ps[] = {
+    GNUNET_PQ_make_prepare ("store_records",
+                            "INSERT INTO ns098records"
+                            " (zone_private_key, pkey, rvalue, record_count, 
record_data, label)"
+                            " VALUES ($1, $2, $3, $4, $5, $6)"
+                            " ON CONFLICT ON CONSTRAINT zl"
+                            " DO UPDATE"
+                            "    SET 
pkey=$2,rvalue=$3,record_count=$4,record_data=$5"
+                            "    WHERE ns098records.zone_private_key = $1"
+                            "          AND ns098records.label = $6",
+                            6),
+    GNUNET_PQ_make_prepare ("delete_records",
+                            "DELETE FROM ns098records "
+                            "WHERE zone_private_key=$1 AND label=$2",
+                            2),
+    GNUNET_PQ_make_prepare ("zone_to_name",
+                            "SELECT seq,record_count,record_data,label FROM 
ns098records"
+                            " WHERE zone_private_key=$1 AND pkey=$2",
+                            2),
+    GNUNET_PQ_make_prepare ("iterate_zone",
+                            "SELECT seq,record_count,record_data,label FROM 
ns098records "
+                            "WHERE zone_private_key=$1 AND seq > $2 ORDER BY 
seq ASC LIMIT $3",
+                            3),
+    GNUNET_PQ_make_prepare ("iterate_all_zones",
+                            "SELECT 
seq,record_count,record_data,label,zone_private_key"
+                            " FROM ns098records WHERE seq > $1 ORDER BY seq 
ASC LIMIT $2",
+                            2),
+    GNUNET_PQ_make_prepare ("lookup_label",
+                            "SELECT seq,record_count,record_data,label "
+                            "FROM ns098records WHERE zone_private_key=$1 AND 
label=$2",
+                            2),
+    GNUNET_PQ_make_prepare ("edit_set",
+                            "SELECT seq,record_count,record_data,label "
+                            "FROM ns098records WHERE zone_private_key=$1 AND 
label=$2 FOR UPDATE NOWAIT",
+                            2),
+    GNUNET_PQ_PREPARED_STATEMENT_END
+  };
+  ret = GNUNET_PQ_prepare_statements (plugin->dbh, ps);
+  if (GNUNET_OK != ret)
+    return ret;
+  plugin->ready = GNUNET_YES;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Initialize the database connections and associated
+ * data structures (create tables and indices
+ * as needed as well).
+ *
+ * @param plugin the plugin context (state for this module)
+ * @return #GNUNET_OK on success
+ */
+static int
+database_connect (struct Plugin *plugin)
+{
+  const struct GNUNET_PQ_ExecuteStatement *cr;
+  char *emsg;
+  struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
+                                            "namestore-postgres",
+                                            "INIT_ON_CONNECT"))
+  {
+    /**
+     * Gracefully fail as this should not be a critical error if the
+     * database is already created
+     */
+    if (GNUNET_OK != init_database (plugin, &emsg, GNUNET_NO))
+    {
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+           "Failed to initialize database on connect: `%s'\n",
+           emsg);
+      GNUNET_free (emsg);
+    }
   }
+  plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
+                                            "namestore-postgres",
+                                            NULL,
+                                            NULL,
+                                            NULL);
   if (NULL == plugin->dbh)
     return GNUNET_SYSERR;
   return GNUNET_OK;
@@ -195,6 +281,7 @@ namestore_postgres_store_records (void *cls,
   uint32_t rd_count32 = (uint32_t) rd_count;
   ssize_t data_size;
 
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   memset (&pkey,
           0,
           sizeof(pkey));
@@ -327,7 +414,7 @@ parse_result_call_iterator (void *cls,
   struct ParserContext *pc = cls;
 
   if (NULL == pc->iter)
-    return; /* no need to do more work */
+    return;   /* no need to do more work */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Got %d results from PQ.\n", num_results);
   for (unsigned int i = 0; i < num_results; i++)
@@ -400,7 +487,6 @@ parse_result_call_iterator (void *cls,
   pc->limit -= num_results;
 }
 
-
 /**
  * Lookup records in the datastore for which we are the authority.
  *
@@ -422,6 +508,7 @@ lookup_records (void *cls,
                 const char*method)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (zone),
     GNUNET_PQ_query_param_string (label),
@@ -518,6 +605,7 @@ namestore_postgres_iterate_records (void *cls,
   enum GNUNET_DB_QueryStatus res;
   struct ParserContext pc;
 
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   pc.iter = iter;
   pc.iter_cls = iter_cls;
   pc.zone_key = zone;
@@ -582,6 +670,7 @@ namestore_postgres_zone_to_name (void *cls,
                                  void *iter_cls)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (zone),
     GNUNET_PQ_query_param_auto_from_type (value_zone),
@@ -615,6 +704,7 @@ namestore_postgres_transaction_begin (void *cls,
                                       char **emsg)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   struct GNUNET_PQ_ExecuteStatement es[] = {
     GNUNET_PQ_make_execute ("BEGIN"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
@@ -636,6 +726,7 @@ namestore_postgres_transaction_rollback (void *cls,
                                          char **emsg)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   struct GNUNET_PQ_ExecuteStatement es[] = {
     GNUNET_PQ_make_execute ("ROLLBACK"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
@@ -657,6 +748,7 @@ namestore_postgres_transaction_commit (void *cls,
                                        char **emsg)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   struct GNUNET_PQ_ExecuteStatement es[] = {
     GNUNET_PQ_make_execute ("COMMIT"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
@@ -666,6 +758,23 @@ namestore_postgres_transaction_commit (void *cls,
 }
 
 
+static enum GNUNET_GenericReturnValue
+namestore_postgres_initialize_database (void *cls,
+                                        char **emsg)
+{
+  return init_database (cls, emsg, GNUNET_NO);
+}
+
+
+static enum GNUNET_GenericReturnValue
+namestore_postgres_reset_database (void *cls,
+                                   char **emsg)
+{
+  return init_database (cls, emsg, GNUNET_YES);
+}
+
+
+
 /**
  * Shutdown database connection and associate data
  * structures.
@@ -695,7 +804,7 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
 
   plugin = GNUNET_new (struct Plugin);
   plugin->cfg = cfg;
-  if (GNUNET_OK != database_setup (plugin))
+  if (GNUNET_OK != database_connect (plugin))
   {
     database_shutdown (plugin);
     GNUNET_free (plugin);
@@ -710,6 +819,8 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
   api->transaction_begin = &namestore_postgres_transaction_begin;
   api->transaction_commit = &namestore_postgres_transaction_commit;
   api->transaction_rollback = &namestore_postgres_transaction_rollback;
+  api->initialize_database = &namestore_postgres_initialize_database;
+  api->reset_database = &namestore_postgres_reset_database;
   api->edit_records = &namestore_postgres_edit_records;
   LOG (GNUNET_ERROR_TYPE_INFO,
        "Postgres namestore plugin running\n");
diff --git a/src/namestore/plugin_namestore_sqlite.c 
b/src/namestore/plugin_namestore_sqlite.c
index c63339db7..f1097ad0a 100644
--- a/src/namestore/plugin_namestore_sqlite.c
+++ b/src/namestore/plugin_namestore_sqlite.c
@@ -74,6 +74,11 @@ struct Plugin
    */
   char *fn;
 
+  /**
+   * Statements prepared, we are ready to go if GNUNET_YES
+   */
+  int ready;
+
   /**
    * Native SQLite database handle.
    */
@@ -120,9 +125,10 @@ struct Plugin
  * @return #GNUNET_OK on success
  */
 static int
-database_setup (struct Plugin *plugin)
+database_prepare (struct Plugin *plugin)
 {
-  char *sqlite_filename;
+  if (GNUNET_YES == plugin->ready)
+    return GNUNET_OK;
   struct GNUNET_SQ_ExecuteStatement es[] = {
     GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
     GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
@@ -132,19 +138,6 @@ database_setup (struct Plugin *plugin)
     GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"),
     GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
     GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
-    GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
-                            " uid INTEGER PRIMARY KEY,"
-                            " zone_private_key BLOB NOT NULL,"
-                            " pkey BLOB,"
-                            " rvalue INT8 NOT NULL,"
-                            " record_count INT NOT NULL,"
-                            " record_data BLOB NOT NULL,"
-                            " label TEXT NOT NULL"
-                            ")"),
-    GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
-                                "ON ns098records (zone_private_key,pkey)"),
-    GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
-                                "ON ns098records (zone_private_key,uid)"),
     GNUNET_SQ_EXECUTE_STATEMENT_END
   };
   struct GNUNET_SQ_PrepareStatement ps[] = {
@@ -179,66 +172,26 @@ database_setup (struct Plugin *plugin)
     GNUNET_SQ_PREPARE_END
   };
 
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
-                                               "namestore-sqlite",
-                                               "FILENAME",
-                                               &sqlite_filename))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "namestore-sqlite",
-                               "FILENAME");
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK !=
-      GNUNET_DISK_file_test (sqlite_filename))
-  {
-    if (GNUNET_OK !=
-        GNUNET_DISK_directory_create_for_file (sqlite_filename))
-    {
-      GNUNET_break (0);
-      GNUNET_free (sqlite_filename);
-      return GNUNET_SYSERR;
-    }
-  }
-
-  /* Open database and precompile statements */
-  if (SQLITE_OK !=
-      sqlite3_open (sqlite_filename,
-                    &plugin->dbh))
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-         _ ("Unable to initialize SQLite: %s.\n"),
-         sqlite3_errmsg (plugin->dbh));
-    GNUNET_free (sqlite_filename);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_break (SQLITE_OK ==
-                sqlite3_busy_timeout (plugin->dbh,
-                                      BUSY_TIMEOUT_MS));
   if (GNUNET_OK !=
       GNUNET_SQ_exec_statements (plugin->dbh,
                                  es))
   {
-    GNUNET_break (0);
     LOG (GNUNET_ERROR_TYPE_ERROR,
-         _ ("Failed to setup database at `%s'\n"),
-         sqlite_filename);
-    GNUNET_free (sqlite_filename);
+         _("Failed to setup database with: `%s'\n"),
+                     sqlite3_errmsg (plugin->dbh));
     return GNUNET_SYSERR;
   }
-
   if (GNUNET_OK !=
       GNUNET_SQ_prepare (plugin->dbh,
                          ps))
   {
     GNUNET_break (0);
     LOG (GNUNET_ERROR_TYPE_ERROR,
-         _ ("Failed to setup database at `%s'\n"),
-         sqlite_filename);
-    GNUNET_free (sqlite_filename);
+         _ ("Failed to setup database with: `%s'\n"),
+         sqlite3_errmsg (plugin->dbh));
     return GNUNET_SYSERR;
   }
+  plugin->ready = GNUNET_YES;
   return GNUNET_OK;
 }
 
@@ -325,6 +278,7 @@ namestore_sqlite_store_records (void *cls,
   uint64_t rvalue;
   ssize_t data_size;
 
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   memset (&pkey,
           0,
           sizeof(pkey));
@@ -594,6 +548,7 @@ namestore_sqlite_lookup_records (void *cls,
                                  void *iter_cls)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   struct GNUNET_SQ_QueryParam params[] = {
     GNUNET_SQ_query_param_auto_from_type (zone),
     GNUNET_SQ_query_param_string (label),
@@ -649,6 +604,7 @@ namestore_sqlite_iterate_records (void *cls,
   sqlite3_stmt *stmt;
   int err;
 
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   if (NULL == zone)
   {
     struct GNUNET_SQ_QueryParam params[] = {
@@ -712,6 +668,7 @@ namestore_sqlite_zone_to_name (void *cls,
                                void *iter_cls)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   struct GNUNET_SQ_QueryParam params[] = {
     GNUNET_SQ_query_param_auto_from_type (zone),
     GNUNET_SQ_query_param_auto_from_type (value_zone),
@@ -755,8 +712,11 @@ namestore_sqlite_transaction_begin (void *cls,
                                     char **emsg)
 {
   struct Plugin *plugin = cls;
-  return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "BEGIN IMMEDIATE 
TRANSACTION;", NULL,
-                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_YES;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
+  return (SQLITE_BUSY == sqlite3_exec (plugin->dbh,
+                                       "BEGIN IMMEDIATE TRANSACTION;", NULL,
+                                       NULL, emsg)) ? GNUNET_SYSERR :
+         GNUNET_YES;
 }
 
 /**
@@ -772,8 +732,10 @@ namestore_sqlite_transaction_rollback (void *cls,
                                        char **emsg)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "ROLLBACK;", NULL,
-                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_YES;
+                                       NULL, emsg)) ? GNUNET_SYSERR :
+         GNUNET_YES;
 }
 
 /**
@@ -789,10 +751,150 @@ namestore_sqlite_transaction_commit (void *cls,
                                      char **emsg)
 {
   struct Plugin *plugin = cls;
+  GNUNET_assert (GNUNET_OK == database_prepare (plugin));
   return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "END TRANSACTION;", NULL,
-                                       NULL, emsg)) ? GNUNET_SYSERR : 
GNUNET_YES;
+                                       NULL, emsg)) ? GNUNET_SYSERR :
+         GNUNET_YES;
+}
+
+static enum GNUNET_GenericReturnValue
+init_database (void *cls, char **emsg, int drop)
+{
+  struct Plugin *plugin = cls;
+  struct GNUNET_SQ_ExecuteStatement es_drop[] = {
+    GNUNET_SQ_make_execute ("DROP TABLE IF EXISTS ns098records"),
+    GNUNET_SQ_EXECUTE_STATEMENT_END
+  };
+  struct GNUNET_SQ_ExecuteStatement es[] = {
+    GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
+    GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
+    GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
+    GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
+    GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
+    GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"),
+    GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
+    GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
+    GNUNET_SQ_make_execute ("CREATE TABLE ns098records ("
+                            " uid INTEGER PRIMARY KEY,"
+                            " zone_private_key BLOB NOT NULL,"
+                            " pkey BLOB,"
+                            " rvalue INT8 NOT NULL,"
+                            " record_count INT NOT NULL,"
+                            " record_data BLOB NOT NULL,"
+                            " label TEXT NOT NULL"
+                            ")"),
+    GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_reverse "
+                                "ON ns098records (zone_private_key,pkey)"),
+    GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_iter "
+                                "ON ns098records (zone_private_key,uid)"),
+    GNUNET_SQ_EXECUTE_STATEMENT_END
+  };
+  if ((GNUNET_YES == drop) &&
+      (GNUNET_OK != GNUNET_SQ_exec_statements (plugin->dbh,
+                                               es_drop)))
+  {
+    GNUNET_asprintf (emsg,
+                     _ ("Failed to drop database with: `%s'\n"),
+                     sqlite3_errmsg (plugin->dbh));
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_SQ_exec_statements (plugin->dbh,
+                                 es))
+  {
+    GNUNET_asprintf (emsg,
+                     _ ("Failed to setup database with: `%s'\n"),
+                     sqlite3_errmsg (plugin->dbh));
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+enum GNUNET_GenericReturnValue
+namestore_sqlite_initialize_database (void *cls, char **emsg)
+{
+  return init_database (cls, emsg, GNUNET_NO);
+}
+
+enum GNUNET_GenericReturnValue
+namestore_sqlite_reset_database (void *cls, char **emsg)
+{
+  return init_database (cls, emsg, GNUNET_YES);
 }
 
+/**
+ * Initialize the database connections and associated
+ * data structures (create tables and indices
+ * as needed as well).
+ *
+ * @param plugin the plugin context (state for this module)
+ * @return #GNUNET_OK on success
+ */
+static int
+database_connect (struct Plugin *plugin)
+{
+  char *sqlite_filename;
+  char *emsg;
+  int try_create = GNUNET_NO;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
+                                               "namestore-sqlite",
+                                               "FILENAME",
+                                               &sqlite_filename))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "namestore-sqlite",
+                               "FILENAME");
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_DISK_file_test (sqlite_filename))
+  {
+    if (GNUNET_OK !=
+        GNUNET_DISK_directory_create_for_file (sqlite_filename))
+    {
+      GNUNET_break (0);
+      GNUNET_free (sqlite_filename);
+      return GNUNET_SYSERR;
+    }
+  }
+
+  /* Open database and precompile statements */
+  if ((NULL == plugin->dbh) &&
+      (SQLITE_OK != sqlite3_open (sqlite_filename,
+                                  &plugin->dbh)))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         _ ("Unable to initialize SQLite: %s.\n"),
+         sqlite3_errmsg (plugin->dbh));
+    GNUNET_free (sqlite_filename);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_break (SQLITE_OK ==
+                sqlite3_busy_timeout (plugin->dbh,
+                                      BUSY_TIMEOUT_MS));
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
+                                            "namestore-sqlite",
+                                            "INIT_ON_CONNECT"))
+  {
+    /**
+     * Gracefully fail as this should not be a critical error if the
+     * database is already created
+     */
+    if (GNUNET_OK != init_database (plugin, &emsg, GNUNET_NO))
+    {
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+           "Failed to initialize database on connect: `%s'\n",
+           emsg);
+      GNUNET_free (emsg);
+    }
+  }
+  return GNUNET_OK;
+}
+
+
 /**
  * Entry point for the plugin.
  *
@@ -808,9 +910,10 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
 
   plugin = GNUNET_new (struct Plugin);
   plugin->cfg = cfg;
-  if (GNUNET_OK != database_setup (plugin))
+  if (GNUNET_OK != database_connect (plugin))
   {
-    database_shutdown (plugin);
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Database could not be connected to.\n");
     GNUNET_free (plugin);
     return NULL;
   }
@@ -823,14 +926,16 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
   api->transaction_begin = &namestore_sqlite_transaction_begin;
   api->transaction_commit = &namestore_sqlite_transaction_commit;
   api->transaction_rollback = &namestore_sqlite_transaction_rollback;
+  api->initialize_database = &namestore_sqlite_initialize_database;
+  api->reset_database = &namestore_sqlite_reset_database;
   /**
    * 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
    */
   api->edit_records = &namestore_sqlite_lookup_records;
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       _ ("Sqlite database running\n"));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       _ ("SQlite database running\n"));
   return api;
 }
 
@@ -852,7 +957,7 @@ libgnunet_plugin_namestore_sqlite_done (void *cls)
   GNUNET_free (plugin);
   GNUNET_free (api);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "sqlite plugin is finished\n");
+       "SQlite plugin is finished\n");
   return NULL;
 }
 
diff --git a/src/namestore/test_common.c b/src/namestore/test_common.c
index 58afb0a32..24a88c180 100644
--- a/src/namestore/test_common.c
+++ b/src/namestore/test_common.c
@@ -21,6 +21,7 @@
  * @file namestore/test_common.c
  * @brief common functions for testcase setup
  */
+#include <gnunet_namestore_plugin.h>
 
 /**
  * test if we can load the plugin @a name.
@@ -30,6 +31,7 @@ TNC_test_plugin (const char *cfg_name)
 {
   char *database;
   char *db_lib_name;
+  char *emsg;
   struct GNUNET_NAMESTORE_PluginFunctions *db;
   struct GNUNET_CONFIGURATION_Handle *cfg;
 
@@ -53,7 +55,15 @@ TNC_test_plugin (const char *cfg_name)
   GNUNET_free (database);
   db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
   if (NULL != db)
+  {
+    if (GNUNET_OK != db->reset_database (db->cls, &emsg))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error resetting database: %s\n", 
emsg);
+      GNUNET_free (emsg);
+      return GNUNET_SYSERR;
+    }
     GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db));
+  }
   GNUNET_free (db_lib_name);
   GNUNET_CONFIGURATION_destroy (cfg);
   if (NULL == db)
diff --git a/src/namestore/test_namestore_api_postgres.conf 
b/src/namestore/test_namestore_api_postgres.conf
index c648a6ab9..007168280 100644
--- a/src/namestore/test_namestore_api_postgres.conf
+++ b/src/namestore/test_namestore_api_postgres.conf
@@ -7,3 +7,4 @@ DATABASE = postgres
 [namestore-postgres]
 CONFIG = connect_timeout=10 dbname=gnunetcheck
 TEMPORARY_TABLE = NO
+INIT_ON_CONNECT = YES
diff --git a/src/namestore/test_namestore_api_sqlite.conf 
b/src/namestore/test_namestore_api_sqlite.conf
index cd4822097..342356247 100644
--- a/src/namestore/test_namestore_api_sqlite.conf
+++ b/src/namestore/test_namestore_api_sqlite.conf
@@ -6,3 +6,4 @@ DATABASE = sqlite
 
 [namestore-sqlite]
 FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
+INIT_ON_CONNECT = YES

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]