aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-09-30 17:36:52 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2022-09-30 17:36:52 +0900
commitc3eca4a0aabe79be51c18fbe56a91b033b1f0549 (patch)
treedaae960b60cf0f055c1c07fae19a0dff9946e46a /src
parentc31abdb6dc1b6da4c23b203ffb96db0aa5646915 (diff)
downloadgnunet-c3eca4a0aabe79be51c18fbe56a91b033b1f0549.tar.gz
gnunet-c3eca4a0aabe79be51c18fbe56a91b033b1f0549.zip
NAMESTORE: Add DB setup utility with SQlite support; PQ broken
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_namestore_plugin.h22
-rw-r--r--src/namestore/.gitignore1
-rw-r--r--src/namestore/Makefile.am9
-rw-r--r--src/namestore/gnunet-namestore-dbtool.c189
-rw-r--r--src/namestore/gnunet-service-namestore.c77
-rw-r--r--src/namestore/plugin_namestore_sqlite.c243
-rw-r--r--src/namestore/test_common.c10
-rw-r--r--src/namestore/test_namestore_api_sqlite.conf1
8 files changed, 463 insertions, 89 deletions
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
205 GNUNET_NAMESTORE_RecordIterator iter, 205 GNUNET_NAMESTORE_RecordIterator iter,
206 void *iter_cls); 206 void *iter_cls);
207 207
208 /**
209 * Setup the database.
210 * Note that this will also fail if the database is already initialized.
211 * See reset_database().
212 *
213 * @param cls closure (internal context for the plugin)
214 * @param emsg error message on failure. Will be allocated, must be freed.
215 * @return #GNUNET_OK on success, else fails with #GNUNET_SYSERR
216 */
217 int
218 (*initialize_database) (void *cls, char **emsg);
219
220 /**
221 * Re-initializes the database.
222 * DANGEROUS: All existing data in the dabase will be lost!
223 *
224 * @param cls closure (internal context for the plugin)
225 * @param emsg error message on failure. Will be allocated, must be freed.
226 * @return #GNUNET_OK on success, else fails with #GNUNET_SYSERR
227 */
228 int
229 (*reset_database) (void *cls, char **emsg);
208}; 230};
209 231
210 232
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 @@
1gnunet-service-namestore 1gnunet-service-namestore
2gnunet-namestore 2gnunet-namestore
3gnunet-namestore-dbtool
3gnunet-namestore-fcfsd 4gnunet-namestore-fcfsd
4test_namestore_api_lookup_nick.nc 5test_namestore_api_lookup_nick.nc
5test_namestore_api_lookup_private.nc 6test_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 = \
90 90
91bin_PROGRAMS = \ 91bin_PROGRAMS = \
92 gnunet-namestore \ 92 gnunet-namestore \
93 gnunet-namestore-dbtool \
93 gnunet-zoneimport 94 gnunet-zoneimport
94 95
95libexec_PROGRAMS += \ 96libexec_PROGRAMS += \
@@ -153,6 +154,14 @@ gnunet_namestore_LDADD = \
153 libgnunetnamestore.la \ 154 libgnunetnamestore.la \
154 $(GN_LIBINTL) 155 $(GN_LIBINTL)
155 156
157gnunet_namestore_dbtool_SOURCES = \
158 gnunet-namestore-dbtool.c
159gnunet_namestore_dbtool_LDADD = \
160 $(top_builddir)/src/util/libgnunetutil.la \
161 libgnunetnamestore.la \
162 $(GN_LIBINTL)
163
164
156 165
157gnunet_namestore_fcfsd_SOURCES = \ 166gnunet_namestore_fcfsd_SOURCES = \
158 gnunet-namestore-fcfsd.c 167 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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 2019, 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file gnunet-namestore-dbtool.c
22 * @brief command line tool to manipulate the database backends for the namestore
23 * @author Martin Schanzenbach
24 *
25 */
26#include "platform.h"
27#include <gnunet_util_lib.h>
28#include <gnunet_namestore_plugin.h>
29
30/**
31 * Name of the plugin argument
32 */
33static char *pluginname;
34
35/**
36 * Reset argument
37 */
38static int reset;
39
40/**
41 * Initialize argument
42 */
43static int init;
44
45/**
46 * Return code
47 */
48static int ret = 0;
49
50/**
51 * Task run on shutdown. Cleans up everything.
52 *
53 * @param cls unused
54 */
55static void
56do_shutdown (void *cls)
57{
58 (void) cls;
59 if (NULL != pluginname)
60 GNUNET_free (pluginname);
61}
62/**
63 * Main function that will be run.
64 *
65 * @param cls closure
66 * @param args remaining command-line arguments
67 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
68 * @param cfg configuration
69 */
70static void
71run (void *cls,
72 char *const *args,
73 const char *cfgfile,
74 const struct GNUNET_CONFIGURATION_Handle *cfg)
75{
76 const char *pkey_str;
77 char *db_lib_name;
78 char *emsg;
79 struct GNUNET_NAMESTORE_PluginFunctions *plugin;
80
81 (void) cls;
82 (void) args;
83 (void) cfgfile;
84 if (NULL != args[0])
85 GNUNET_log (
86 GNUNET_ERROR_TYPE_WARNING,
87 _ ("Superfluous command line arguments (starting with `%s') ignored\n"),
88 args[0]);
89
90 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg);
91 if (NULL == pluginname)
92 {
93 fprintf (stderr, "No plugin given!\n");
94 ret = 1;
95 GNUNET_SCHEDULER_shutdown ();
96 return;
97 }
98 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", pluginname);
99 plugin = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
100 if (NULL == plugin)
101 {
102 fprintf (stderr, "Failed to load %s!\n", db_lib_name);
103 ret = 1;
104 GNUNET_SCHEDULER_shutdown ();
105 GNUNET_free (db_lib_name);
106 return;
107 }
108 if (reset)
109 {
110 if (GNUNET_OK != plugin->reset_database (plugin->cls, &emsg))
111 {
112 // FIXME do we want to return a reason?
113 fprintf (stderr, "Failed to reset database: %s\n",
114 emsg);
115 ret = 1;
116 GNUNET_free (emsg);
117 GNUNET_free (db_lib_name);
118 GNUNET_SCHEDULER_shutdown ();
119 return;
120 }
121 }
122 else if (init)
123 {
124 if (GNUNET_OK != plugin->initialize_database (plugin->cls, &emsg))
125 {
126 // FIXME do we want to return a reason?
127 fprintf (stderr, "Failed to initialize database: %s\n",
128 emsg);
129 ret = 1;
130 GNUNET_free (emsg);
131 GNUNET_free (db_lib_name);
132 GNUNET_SCHEDULER_shutdown ();
133 return;
134 }
135 }
136 GNUNET_SCHEDULER_shutdown ();
137 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, plugin));
138 GNUNET_free (db_lib_name);
139}
140
141
142/**
143 * The main function for gnunet-namestore-dbtool.
144 *
145 * @param argc number of arguments from the command line
146 * @param argv command line arguments
147 * @return 0 ok, 1 on error
148 */
149int
150main (int argc, char *const *argv)
151{
152 struct GNUNET_GETOPT_CommandLineOption options[] =
153 { GNUNET_GETOPT_option_flag ('i', "init", gettext_noop (
154 "initialize database"), &init),
155 GNUNET_GETOPT_option_flag ('r',
156 "reset",
157 gettext_noop (
158 "reset database (DANGEROUS: All existing data is lost!"),
159 &reset),
160 GNUNET_GETOPT_option_string (
161 'p',
162 "plugin",
163 "PLUGIN",
164 gettext_noop (
165 "the namestore plugin to work with, e.g. 'sqlite'"),
166 &pluginname),
167 GNUNET_GETOPT_OPTION_END };
168 int lret;
169
170 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
171 return 2;
172
173 GNUNET_log_setup ("gnunet-namestore-dbtool", "WARNING", NULL);
174 if (GNUNET_OK !=
175 (lret = GNUNET_PROGRAM_run (argc,
176 argv,
177 "gnunet-namestore-dbtool",
178 _ (
179 "GNUnet namestore database manipulation tool"),
180 options,
181 &run,
182 NULL)))
183 {
184 GNUNET_free_nz ((void *) argv);
185 return lret;
186 }
187 GNUNET_free_nz ((void *) argv);
188 return ret;
189}
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,11 +137,16 @@ struct NamestoreClient
137 struct GNUNET_SERVICE_Client *client; 137 struct GNUNET_SERVICE_Client *client;
138 138
139 /** 139 /**
140 * Database handle 140 * Database handle for client
141 */ 141 */
142 struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; 142 struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
143 143
144 /** 144 /**
145 * Name of loaded plugin (neeed for cleanup)
146 */
147 char *db_lib_name;
148
149 /**
145 * Message queue for transmission to @e client 150 * Message queue for transmission to @e client
146 */ 151 */
147 struct GNUNET_MQ_Handle *mq; 152 struct GNUNET_MQ_Handle *mq;
@@ -373,6 +378,12 @@ static struct GNUNET_NAMECACHE_Handle *namecache;
373static char *db_lib_name; 378static char *db_lib_name;
374 379
375/** 380/**
381 * Database handle for service
382 */
383struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
384
385
386/**
376 * Head of cop DLL. 387 * Head of cop DLL.
377 */ 388 */
378static struct CacheOperation *cop_head; 389static struct CacheOperation *cop_head;
@@ -446,8 +457,6 @@ cleanup_task (void *cls)
446 GNUNET_NAMECACHE_disconnect (namecache); 457 GNUNET_NAMECACHE_disconnect (namecache);
447 namecache = NULL; 458 namecache = NULL;
448 } 459 }
449 GNUNET_free (db_lib_name);
450 db_lib_name = NULL;
451 if (NULL != monitor_nc) 460 if (NULL != monitor_nc)
452 { 461 {
453 GNUNET_notification_context_destroy (monitor_nc); 462 GNUNET_notification_context_destroy (monitor_nc);
@@ -458,6 +467,9 @@ cleanup_task (void *cls)
458 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); 467 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
459 statistics = NULL; 468 statistics = NULL;
460 } 469 }
470 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
471 GNUNET_free (db_lib_name);
472 db_lib_name = NULL;
461} 473}
462 474
463 475
@@ -574,8 +586,7 @@ cache_nick (const struct GNUNET_IDENTITY_PrivateKey *zone,
574 * @return NULL if no NICK record was found 586 * @return NULL if no NICK record was found
575 */ 587 */
576static struct GNUNET_GNSRECORD_Data * 588static struct GNUNET_GNSRECORD_Data *
577get_nick_record (const struct NamestoreClient *nc, 589get_nick_record (const struct GNUNET_IDENTITY_PrivateKey *zone)
578 const struct GNUNET_IDENTITY_PrivateKey *zone)
579{ 590{
580 struct GNUNET_IDENTITY_PublicKey pub; 591 struct GNUNET_IDENTITY_PublicKey pub;
581 struct GNUNET_GNSRECORD_Data *nick; 592 struct GNUNET_GNSRECORD_Data *nick;
@@ -599,11 +610,11 @@ get_nick_record (const struct NamestoreClient *nc,
599 } 610 }
600 611
601 nick = NULL; 612 nick = NULL;
602 res = nc->GSN_database->lookup_records (nc->GSN_database->cls, 613 res = GSN_database->lookup_records (GSN_database->cls,
603 zone, 614 zone,
604 GNUNET_GNS_EMPTY_LABEL_AT, 615 GNUNET_GNS_EMPTY_LABEL_AT,
605 &lookup_nick_it, 616 &lookup_nick_it,
606 &nick); 617 &nick);
607 if ((GNUNET_OK != res) || (NULL == nick)) 618 if ((GNUNET_OK != res) || (NULL == nick))
608 { 619 {
609#if ! defined(GNUNET_CULL_LOGGING) 620#if ! defined(GNUNET_CULL_LOGGING)
@@ -753,7 +764,7 @@ send_lookup_response_with_filter (struct NamestoreClient *nc,
753 char *rd_ser; 764 char *rd_ser;
754 char *emsg; 765 char *emsg;
755 766
756 nick = get_nick_record (nc, zone_key); 767 nick = get_nick_record (zone_key);
757 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd)); 768 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd));
758 769
759 if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (name, 770 if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (name,
@@ -996,7 +1007,7 @@ refresh_block (struct NamestoreClient *nc,
996 rd_clean[rd_count_clean++] = rd[i]; 1007 rd_clean[rd_count_clean++] = rd[i];
997 } 1008 }
998 1009
999 nick = get_nick_record (nc, zone_key); 1010 nick = get_nick_record (zone_key);
1000 res_count = rd_count_clean; 1011 res_count = rd_count_clean;
1001 res = (struct GNUNET_GNSRECORD_Data *) rd_clean; /* fixme: a bit unclean... */ 1012 res = (struct GNUNET_GNSRECORD_Data *) rd_clean; /* fixme: a bit unclean... */
1002 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) 1013 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
@@ -1229,7 +1240,8 @@ client_disconnect_cb (void *cls,
1229 for (cop = cop_head; NULL != cop; cop = cop->next) 1240 for (cop = cop_head; NULL != cop; cop = cop->next)
1230 if (nc == cop->nc) 1241 if (nc == cop->nc)
1231 cop->nc = NULL; 1242 cop->nc = NULL;
1232 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, nc->GSN_database)); 1243 GNUNET_break (NULL == GNUNET_PLUGIN_unload (nc->db_lib_name, nc->GSN_database));
1244 GNUNET_free (nc->db_lib_name);
1233 GNUNET_free (nc); 1245 GNUNET_free (nc);
1234} 1246}
1235 1247
@@ -1249,7 +1261,6 @@ client_connect_cb (void *cls,
1249{ 1261{
1250 struct NamestoreClient *nc; 1262 struct NamestoreClient *nc;
1251 char *database; 1263 char *database;
1252 char *db_lib_name;
1253 1264
1254 (void) cls; 1265 (void) cls;
1255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); 1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
@@ -1261,9 +1272,12 @@ client_connect_cb (void *cls,
1261 "namestore", 1272 "namestore",
1262 "database", 1273 "database",
1263 &database)) 1274 &database))
1275 {
1264 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); 1276 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1265 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); 1277 GNUNET_free (nc);
1266 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading %s\n", db_lib_name); 1278 return NULL;
1279 }
1280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name);
1267 nc->GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); 1281 nc->GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1268 GNUNET_free (database); 1282 GNUNET_free (database);
1269 if (NULL == nc->GSN_database) 1283 if (NULL == nc->GSN_database)
@@ -1271,12 +1285,11 @@ client_connect_cb (void *cls,
1271 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1285 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1272 "Could not load database backend `%s'\n", 1286 "Could not load database backend `%s'\n",
1273 db_lib_name); 1287 db_lib_name);
1274 GNUNET_free (db_lib_name);
1275 GNUNET_free (nc); 1288 GNUNET_free (nc);
1276 return NULL; 1289 return NULL;
1277 } 1290 }
1278 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loaded %s\n", db_lib_name); 1291 nc->db_lib_name = GNUNET_strdup (db_lib_name);
1279 GNUNET_free (db_lib_name); 1292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded %s\n", db_lib_name);
1280 return nc; 1293 return nc;
1281} 1294}
1282 1295
@@ -1487,7 +1500,7 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1487 rlc.res_rd_count = 0; 1500 rlc.res_rd_count = 0;
1488 rlc.res_rd = NULL; 1501 rlc.res_rd = NULL;
1489 rlc.rd_ser_len = 0; 1502 rlc.rd_ser_len = 0;
1490 rlc.nick = get_nick_record (nc, &ll_msg->zone); 1503 rlc.nick = get_nick_record (&ll_msg->zone);
1491 if (GNUNET_YES != ntohl (ll_msg->is_edit_request)) 1504 if (GNUNET_YES != ntohl (ll_msg->is_edit_request))
1492 res = nc->GSN_database->lookup_records (nc->GSN_database->cls, 1505 res = nc->GSN_database->lookup_records (nc->GSN_database->cls,
1493 &ll_msg->zone, 1506 &ll_msg->zone,
@@ -2469,6 +2482,7 @@ run (void *cls,
2469 const struct GNUNET_CONFIGURATION_Handle *cfg, 2482 const struct GNUNET_CONFIGURATION_Handle *cfg,
2470 struct GNUNET_SERVICE_Handle *service) 2483 struct GNUNET_SERVICE_Handle *service)
2471{ 2484{
2485 char *database;
2472 (void) cls; 2486 (void) cls;
2473 (void) service; 2487 (void) service;
2474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); 2488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
@@ -2484,6 +2498,29 @@ run (void *cls,
2484 GNUNET_assert (NULL != namecache); 2498 GNUNET_assert (NULL != namecache);
2485 } 2499 }
2486 statistics = GNUNET_STATISTICS_create ("namestore", cfg); 2500 statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2501 /* Loading database plugin */
2502 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2503 "namestore",
2504 "database",
2505 &database))
2506 {
2507 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2508 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2509 return;
2510 }
2511 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name);
2513 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
2514 GNUNET_free (database);
2515 if (NULL == GSN_database)
2516 {
2517 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2518 "Could not load database backend `%s'\n",
2519 db_lib_name);
2520 GNUNET_free (db_lib_name);
2521 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2522 return;
2523 }
2487 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); 2524 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
2488} 2525}
2489 2526
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
@@ -75,6 +75,11 @@ struct Plugin
75 char *fn; 75 char *fn;
76 76
77 /** 77 /**
78 * Statements prepared, we are ready to go if GNUNET_YES
79 */
80 int ready;
81
82 /**
78 * Native SQLite database handle. 83 * Native SQLite database handle.
79 */ 84 */
80 sqlite3 *dbh; 85 sqlite3 *dbh;
@@ -120,9 +125,10 @@ struct Plugin
120 * @return #GNUNET_OK on success 125 * @return #GNUNET_OK on success
121 */ 126 */
122static int 127static int
123database_setup (struct Plugin *plugin) 128database_prepare (struct Plugin *plugin)
124{ 129{
125 char *sqlite_filename; 130 if (GNUNET_YES == plugin->ready)
131 return GNUNET_OK;
126 struct GNUNET_SQ_ExecuteStatement es[] = { 132 struct GNUNET_SQ_ExecuteStatement es[] = {
127 GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"), 133 GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
128 GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"), 134 GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
@@ -132,19 +138,6 @@ database_setup (struct Plugin *plugin)
132 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"), 138 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"),
133 GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"), 139 GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
134 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"), 140 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)"),
148 GNUNET_SQ_EXECUTE_STATEMENT_END 141 GNUNET_SQ_EXECUTE_STATEMENT_END
149 }; 142 };
150 struct GNUNET_SQ_PrepareStatement ps[] = { 143 struct GNUNET_SQ_PrepareStatement ps[] = {
@@ -180,65 +173,25 @@ database_setup (struct Plugin *plugin)
180 }; 173 };
181 174
182 if (GNUNET_OK != 175 if (GNUNET_OK !=
183 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
184 "namestore-sqlite",
185 "FILENAME",
186 &sqlite_filename))
187 {
188 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
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 {
210 LOG (GNUNET_ERROR_TYPE_ERROR,
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 !=
220 GNUNET_SQ_exec_statements (plugin->dbh, 176 GNUNET_SQ_exec_statements (plugin->dbh,
221 es)) 177 es))
222 { 178 {
223 GNUNET_break (0);
224 LOG (GNUNET_ERROR_TYPE_ERROR, 179 LOG (GNUNET_ERROR_TYPE_ERROR,
225 _ ("Failed to setup database at `%s'\n"), 180 _("Failed to setup database with: `%s'\n"),
226 sqlite_filename); 181 sqlite3_errmsg (plugin->dbh));
227 GNUNET_free (sqlite_filename);
228 return GNUNET_SYSERR; 182 return GNUNET_SYSERR;
229 } 183 }
230
231 if (GNUNET_OK != 184 if (GNUNET_OK !=
232 GNUNET_SQ_prepare (plugin->dbh, 185 GNUNET_SQ_prepare (plugin->dbh,
233 ps)) 186 ps))
234 { 187 {
235 GNUNET_break (0); 188 GNUNET_break (0);
236 LOG (GNUNET_ERROR_TYPE_ERROR, 189 LOG (GNUNET_ERROR_TYPE_ERROR,
237 _ ("Failed to setup database at `%s'\n"), 190 _ ("Failed to setup database with: `%s'\n"),
238 sqlite_filename); 191 sqlite3_errmsg (plugin->dbh));
239 GNUNET_free (sqlite_filename);
240 return GNUNET_SYSERR; 192 return GNUNET_SYSERR;
241 } 193 }
194 plugin->ready = GNUNET_YES;
242 return GNUNET_OK; 195 return GNUNET_OK;
243} 196}
244 197
@@ -325,6 +278,7 @@ namestore_sqlite_store_records (void *cls,
325 uint64_t rvalue; 278 uint64_t rvalue;
326 ssize_t data_size; 279 ssize_t data_size;
327 280
281 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
328 memset (&pkey, 282 memset (&pkey,
329 0, 283 0,
330 sizeof(pkey)); 284 sizeof(pkey));
@@ -594,6 +548,7 @@ namestore_sqlite_lookup_records (void *cls,
594 void *iter_cls) 548 void *iter_cls)
595{ 549{
596 struct Plugin *plugin = cls; 550 struct Plugin *plugin = cls;
551 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
597 struct GNUNET_SQ_QueryParam params[] = { 552 struct GNUNET_SQ_QueryParam params[] = {
598 GNUNET_SQ_query_param_auto_from_type (zone), 553 GNUNET_SQ_query_param_auto_from_type (zone),
599 GNUNET_SQ_query_param_string (label), 554 GNUNET_SQ_query_param_string (label),
@@ -649,6 +604,7 @@ namestore_sqlite_iterate_records (void *cls,
649 sqlite3_stmt *stmt; 604 sqlite3_stmt *stmt;
650 int err; 605 int err;
651 606
607 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
652 if (NULL == zone) 608 if (NULL == zone)
653 { 609 {
654 struct GNUNET_SQ_QueryParam params[] = { 610 struct GNUNET_SQ_QueryParam params[] = {
@@ -712,6 +668,7 @@ namestore_sqlite_zone_to_name (void *cls,
712 void *iter_cls) 668 void *iter_cls)
713{ 669{
714 struct Plugin *plugin = cls; 670 struct Plugin *plugin = cls;
671 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
715 struct GNUNET_SQ_QueryParam params[] = { 672 struct GNUNET_SQ_QueryParam params[] = {
716 GNUNET_SQ_query_param_auto_from_type (zone), 673 GNUNET_SQ_query_param_auto_from_type (zone),
717 GNUNET_SQ_query_param_auto_from_type (value_zone), 674 GNUNET_SQ_query_param_auto_from_type (value_zone),
@@ -755,8 +712,11 @@ namestore_sqlite_transaction_begin (void *cls,
755 char **emsg) 712 char **emsg)
756{ 713{
757 struct Plugin *plugin = cls; 714 struct Plugin *plugin = cls;
758 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "BEGIN IMMEDIATE TRANSACTION;", NULL, 715 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
759 NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES; 716 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh,
717 "BEGIN IMMEDIATE TRANSACTION;", NULL,
718 NULL, emsg)) ? GNUNET_SYSERR :
719 GNUNET_YES;
760} 720}
761 721
762/** 722/**
@@ -772,8 +732,10 @@ namestore_sqlite_transaction_rollback (void *cls,
772 char **emsg) 732 char **emsg)
773{ 733{
774 struct Plugin *plugin = cls; 734 struct Plugin *plugin = cls;
735 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
775 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "ROLLBACK;", NULL, 736 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "ROLLBACK;", NULL,
776 NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES; 737 NULL, emsg)) ? GNUNET_SYSERR :
738 GNUNET_YES;
777} 739}
778 740
779/** 741/**
@@ -789,11 +751,151 @@ namestore_sqlite_transaction_commit (void *cls,
789 char **emsg) 751 char **emsg)
790{ 752{
791 struct Plugin *plugin = cls; 753 struct Plugin *plugin = cls;
754 GNUNET_assert (GNUNET_OK == database_prepare (plugin));
792 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "END TRANSACTION;", NULL, 755 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "END TRANSACTION;", NULL,
793 NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES; 756 NULL, emsg)) ? GNUNET_SYSERR :
757 GNUNET_YES;
758}
759
760static enum GNUNET_GenericReturnValue
761init_database (void *cls, char **emsg, int drop)
762{
763 struct Plugin *plugin = cls;
764 struct GNUNET_SQ_ExecuteStatement es_drop[] = {
765 GNUNET_SQ_make_execute ("DROP TABLE IF EXISTS ns098records"),
766 GNUNET_SQ_EXECUTE_STATEMENT_END
767 };
768 struct GNUNET_SQ_ExecuteStatement es[] = {
769 GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
770 GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
771 GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
772 GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
773 GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
774 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"),
775 GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
776 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
777 GNUNET_SQ_make_execute ("CREATE TABLE ns098records ("
778 " uid INTEGER PRIMARY KEY,"
779 " zone_private_key BLOB NOT NULL,"
780 " pkey BLOB,"
781 " rvalue INT8 NOT NULL,"
782 " record_count INT NOT NULL,"
783 " record_data BLOB NOT NULL,"
784 " label TEXT NOT NULL"
785 ")"),
786 GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_reverse "
787 "ON ns098records (zone_private_key,pkey)"),
788 GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_iter "
789 "ON ns098records (zone_private_key,uid)"),
790 GNUNET_SQ_EXECUTE_STATEMENT_END
791 };
792 if ((GNUNET_YES == drop) &&
793 (GNUNET_OK != GNUNET_SQ_exec_statements (plugin->dbh,
794 es_drop)))
795 {
796 GNUNET_asprintf (emsg,
797 _ ("Failed to drop database with: `%s'\n"),
798 sqlite3_errmsg (plugin->dbh));
799 return GNUNET_SYSERR;
800 }
801 if (GNUNET_OK !=
802 GNUNET_SQ_exec_statements (plugin->dbh,
803 es))
804 {
805 GNUNET_asprintf (emsg,
806 _ ("Failed to setup database with: `%s'\n"),
807 sqlite3_errmsg (plugin->dbh));
808 return GNUNET_SYSERR;
809 }
810 return GNUNET_OK;
811}
812
813enum GNUNET_GenericReturnValue
814namestore_sqlite_initialize_database (void *cls, char **emsg)
815{
816 return init_database (cls, emsg, GNUNET_NO);
817}
818
819enum GNUNET_GenericReturnValue
820namestore_sqlite_reset_database (void *cls, char **emsg)
821{
822 return init_database (cls, emsg, GNUNET_YES);
794} 823}
795 824
796/** 825/**
826 * Initialize the database connections and associated
827 * data structures (create tables and indices
828 * as needed as well).
829 *
830 * @param plugin the plugin context (state for this module)
831 * @return #GNUNET_OK on success
832 */
833static int
834database_connect (struct Plugin *plugin)
835{
836 char *sqlite_filename;
837 char *emsg;
838 int try_create = GNUNET_NO;
839
840 if (GNUNET_OK !=
841 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
842 "namestore-sqlite",
843 "FILENAME",
844 &sqlite_filename))
845 {
846 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
847 "namestore-sqlite",
848 "FILENAME");
849 return GNUNET_SYSERR;
850 }
851 if (GNUNET_OK !=
852 GNUNET_DISK_file_test (sqlite_filename))
853 {
854 if (GNUNET_OK !=
855 GNUNET_DISK_directory_create_for_file (sqlite_filename))
856 {
857 GNUNET_break (0);
858 GNUNET_free (sqlite_filename);
859 return GNUNET_SYSERR;
860 }
861 }
862
863 /* Open database and precompile statements */
864 if ((NULL == plugin->dbh) &&
865 (SQLITE_OK != sqlite3_open (sqlite_filename,
866 &plugin->dbh)))
867 {
868 LOG (GNUNET_ERROR_TYPE_ERROR,
869 _ ("Unable to initialize SQLite: %s.\n"),
870 sqlite3_errmsg (plugin->dbh));
871 GNUNET_free (sqlite_filename);
872 return GNUNET_SYSERR;
873 }
874 GNUNET_break (SQLITE_OK ==
875 sqlite3_busy_timeout (plugin->dbh,
876 BUSY_TIMEOUT_MS));
877 if (GNUNET_YES ==
878 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
879 "namestore-sqlite",
880 "INIT_ON_CONNECT"))
881 {
882 /**
883 * Gracefully fail as this should not be a critical error if the
884 * database is already created
885 */
886 if (GNUNET_OK != init_database (plugin, &emsg, GNUNET_NO))
887 {
888 LOG (GNUNET_ERROR_TYPE_WARNING,
889 "Failed to initialize database on connect: `%s'\n",
890 emsg);
891 GNUNET_free (emsg);
892 }
893 }
894 return GNUNET_OK;
895}
896
897
898/**
797 * Entry point for the plugin. 899 * Entry point for the plugin.
798 * 900 *
799 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" 901 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
@@ -808,9 +910,10 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
808 910
809 plugin = GNUNET_new (struct Plugin); 911 plugin = GNUNET_new (struct Plugin);
810 plugin->cfg = cfg; 912 plugin->cfg = cfg;
811 if (GNUNET_OK != database_setup (plugin)) 913 if (GNUNET_OK != database_connect (plugin))
812 { 914 {
813 database_shutdown (plugin); 915 LOG (GNUNET_ERROR_TYPE_ERROR,
916 "Database could not be connected to.\n");
814 GNUNET_free (plugin); 917 GNUNET_free (plugin);
815 return NULL; 918 return NULL;
816 } 919 }
@@ -823,14 +926,16 @@ libgnunet_plugin_namestore_sqlite_init (void *cls)
823 api->transaction_begin = &namestore_sqlite_transaction_begin; 926 api->transaction_begin = &namestore_sqlite_transaction_begin;
824 api->transaction_commit = &namestore_sqlite_transaction_commit; 927 api->transaction_commit = &namestore_sqlite_transaction_commit;
825 api->transaction_rollback = &namestore_sqlite_transaction_rollback; 928 api->transaction_rollback = &namestore_sqlite_transaction_rollback;
929 api->initialize_database = &namestore_sqlite_initialize_database;
930 api->reset_database = &namestore_sqlite_reset_database;
826 /** 931 /**
827 * NOTE: Since SQlite does not support SELECT ... FOR UPDATE this is 932 * NOTE: Since SQlite does not support SELECT ... FOR UPDATE this is
828 * just an alias to lookup_records. The BEGIN IMMEDIATE mechanic currently 933 * just an alias to lookup_records. The BEGIN IMMEDIATE mechanic currently
829 * implicitly ensures this API behaves as it should 934 * implicitly ensures this API behaves as it should
830 */ 935 */
831 api->edit_records = &namestore_sqlite_lookup_records; 936 api->edit_records = &namestore_sqlite_lookup_records;
832 LOG (GNUNET_ERROR_TYPE_INFO, 937 LOG (GNUNET_ERROR_TYPE_DEBUG,
833 _ ("Sqlite database running\n")); 938 _ ("SQlite database running\n"));
834 return api; 939 return api;
835} 940}
836 941
@@ -852,7 +957,7 @@ libgnunet_plugin_namestore_sqlite_done (void *cls)
852 GNUNET_free (plugin); 957 GNUNET_free (plugin);
853 GNUNET_free (api); 958 GNUNET_free (api);
854 LOG (GNUNET_ERROR_TYPE_DEBUG, 959 LOG (GNUNET_ERROR_TYPE_DEBUG,
855 "sqlite plugin is finished\n"); 960 "SQlite plugin is finished\n");
856 return NULL; 961 return NULL;
857} 962}
858 963
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 @@
21 * @file namestore/test_common.c 21 * @file namestore/test_common.c
22 * @brief common functions for testcase setup 22 * @brief common functions for testcase setup
23 */ 23 */
24#include <gnunet_namestore_plugin.h>
24 25
25/** 26/**
26 * test if we can load the plugin @a name. 27 * test if we can load the plugin @a name.
@@ -30,6 +31,7 @@ TNC_test_plugin (const char *cfg_name)
30{ 31{
31 char *database; 32 char *database;
32 char *db_lib_name; 33 char *db_lib_name;
34 char *emsg;
33 struct GNUNET_NAMESTORE_PluginFunctions *db; 35 struct GNUNET_NAMESTORE_PluginFunctions *db;
34 struct GNUNET_CONFIGURATION_Handle *cfg; 36 struct GNUNET_CONFIGURATION_Handle *cfg;
35 37
@@ -53,7 +55,15 @@ TNC_test_plugin (const char *cfg_name)
53 GNUNET_free (database); 55 GNUNET_free (database);
54 db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); 56 db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
55 if (NULL != db) 57 if (NULL != db)
58 {
59 if (GNUNET_OK != db->reset_database (db->cls, &emsg))
60 {
61 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error resetting database: %s\n", emsg);
62 GNUNET_free (emsg);
63 return GNUNET_SYSERR;
64 }
56 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db)); 65 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db));
66 }
57 GNUNET_free (db_lib_name); 67 GNUNET_free (db_lib_name);
58 GNUNET_CONFIGURATION_destroy (cfg); 68 GNUNET_CONFIGURATION_destroy (cfg);
59 if (NULL == db) 69 if (NULL == db)
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
6 6
7[namestore-sqlite] 7[namestore-sqlite]
8FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db 8FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
9INIT_ON_CONNECT = YES