aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_namestore_plugin.h52
-rw-r--r--src/include/gnunet_namestore_service.h96
-rw-r--r--src/include/gnunet_protocols.h22
-rw-r--r--src/namestore/Makefile.am222
-rw-r--r--src/namestore/gnunet-service-namestore.c201
-rw-r--r--src/namestore/namestore.h48
-rw-r--r--src/namestore/namestore_api.c128
-rw-r--r--src/namestore/perf_namestore_api_flat.conf10
-rw-r--r--src/namestore/plugin_namestore_flat.c818
-rw-r--r--src/namestore/plugin_namestore_postgres.c81
-rw-r--r--src/namestore/plugin_namestore_sqlite.c95
-rw-r--r--src/namestore/test_namestore_api_flat.conf7
-rw-r--r--src/namestore/test_namestore_api_monitoring_existing.c38
-rw-r--r--src/namestore/test_plugin_namestore_flat.conf2
14 files changed, 529 insertions, 1291 deletions
diff --git a/src/include/gnunet_namestore_plugin.h b/src/include/gnunet_namestore_plugin.h
index 9301c29fe..82bac1f9e 100644
--- a/src/include/gnunet_namestore_plugin.h
+++ b/src/include/gnunet_namestore_plugin.h
@@ -160,63 +160,31 @@ struct GNUNET_NAMESTORE_PluginFunctions
160 * Start a transaction in the database 160 * Start a transaction in the database
161 * 161 *
162 * @param cls closure (internal context for the plugin) 162 * @param cls closure (internal context for the plugin)
163 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error 163 * @param emsg message. On error, string will be allocated and must be freed.
164 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
164 */ 165 */
165 enum GNUNET_GenericReturnValue 166 enum GNUNET_GenericReturnValue
166 (*transaction_begin) (void *cls); 167 (*transaction_begin) (void *cls, char **emsg);
167 168
168 /** 169 /**
169 * Abort a transaction in the database 170 * Abort and roll back a transaction in the database
170 * 171 *
171 * @param cls closure (internal context for the plugin) 172 * @param cls closure (internal context for the plugin)
172 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error 173 * @param emsg message. On error, string will be allocated and must be freed.
174 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
173 */ 175 */
174 enum GNUNET_GenericReturnValue 176 enum GNUNET_GenericReturnValue
175 (*transaction_abort) (void *cls); 177 (*transaction_rollback) (void *cls, char **emsg);
176 178
177 /** 179 /**
178 * Commit a transaction in the database 180 * Commit a transaction in the database
179 * 181 *
180 * @param cls closure (internal context for the plugin) 182 * @param cls closure (internal context for the plugin)
181 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error 183 * @param emsg message. On error, string will be allocated and must be freed.
184 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
182 */ 185 */
183 enum GNUNET_GenericReturnValue 186 enum GNUNET_GenericReturnValue
184 (*transaction_commit) (void *cls); 187 (*transaction_commit) (void *cls, char **emsg);
185
186 /**
187 * Replace a record in the datastore for which we are the authority.
188 * Removes any existing record in the same zone with the same name.
189 *
190 * @param cls closure (internal context for the plugin)
191 * @param zone private key of the zone
192 * @param label name of the record in the zone
193 * @param rd_count number of entries in @a rd array, 0 to delete all records
194 * @param rd array of records with data to store
195 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
196 */
197 int
198 (*replace_records) (void *cls,
199 const struct GNUNET_IDENTITY_PrivateKey *zone,
200 const char *label,
201 unsigned int rd_count,
202 const struct GNUNET_GNSRECORD_Data *rd);
203
204 /**
205 * Lookup records in the datastore for which we are the authority.
206 *
207 * @param cls closure (internal context for the plugin)
208 * @param zone private key of the zone
209 * @param label name of the record in the zone
210 * @param iter function to call with the result
211 * @param iter_cls closure for @a iter
212 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
213 */
214 int
215 (*select_records) (void *cls,
216 const struct GNUNET_IDENTITY_PrivateKey *zone,
217 const char *label,
218 GNUNET_NAMESTORE_RecordIterator iter,
219 void *iter_cls);
220 188
221}; 189};
222 190
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h
index 15d3be727..68aeebef8 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -70,6 +70,16 @@ struct GNUNET_NAMESTORE_Handle;
70 */ 70 */
71struct GNUNET_NAMESTORE_ZoneIterator; 71struct GNUNET_NAMESTORE_ZoneIterator;
72 72
73/**
74 * Transaction control types.
75 * They roughly correspond to DB transaction controls
76 */
77enum GNUNET_NAMESTORE_TxControl
78{
79 GNUNET_NAMESTORE_TX_BEGIN = 0,
80 GNUNET_NAMESTORE_TX_COMMIT = 1,
81 GNUNET_NAMESTORE_TX_ROLLBACK = 2,
82};
73 83
74/** 84/**
75 * Connect to the namestore service. 85 * Connect to the namestore service.
@@ -404,98 +414,44 @@ GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
404 * Begin a namestore transaction. 414 * Begin a namestore transaction.
405 * 415 *
406 * @param h handle to the namestore 416 * @param h handle to the namestore
407 * @param error_cb function to call on error (i.e. disconnect or unable to get lock) 417 * @param cont function to call on result
408 * the handle is afterwards invalid 418 * @param cont_cls closure for @a cont
409 * @param error_cb_cls closure for @a error_cb
410 * @return handle to abort the request 419 * @return handle to abort the request
411 */ 420 */
412struct GNUNET_NAMESTORE_QueueEntry * 421struct GNUNET_NAMESTORE_QueueEntry *
413GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h, 422GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
414 GNUNET_SCHEDULER_TaskCallback error_cb, 423 GNUNET_NAMESTORE_ContinuationWithStatus
415 void *error_cb_cls); 424 cont,
425 void *cont_cls);
416 426
417/** 427/**
418 * Begin rollback all actions in a transaction. 428 * Begin rollback all actions in a transaction.
419 * Reverts all actions performed since #GNUNET_NAMESTORE_transaction_begin 429 * Reverts all actions performed since #GNUNET_NAMESTORE_transaction_begin
420 * 430 *
421 * @param h handle to the namestore 431 * @param h handle to the namestore
422 * @param error_cb function to call on error (i.e. disconnect or unable to get lock) 432 * @param cont function to call on result
423 * the handle is afterwards invalid 433 * @param cont_cls closure for @a cont
424 * @param error_cb_cls closure for @a error_cb
425 * @return handle to abort the request 434 * @return handle to abort the request
426 */ 435 */
427struct GNUNET_NAMESTORE_QueueEntry * 436struct GNUNET_NAMESTORE_QueueEntry *
428GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h, 437GNUNET_NAMESTORE_transaction_rollback (struct GNUNET_NAMESTORE_Handle *h,
429 GNUNET_SCHEDULER_TaskCallback error_cb, 438 GNUNET_NAMESTORE_ContinuationWithStatus
430 void *error_cb_cls); 439 cont,
440 void *cont_cls);
431/** 441/**
432 * Commit a namestore transaction. 442 * Commit a namestore transaction.
433 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin 443 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
434 * 444 *
435 * @param h handle to the namestore 445 * @param h handle to the namestore
436 * @param error_cb function to call on error (i.e. disconnect or unable to get lock) 446 * @param cont function to call on result
437 * the handle is afterwards invalid
438 * @param error_cb_cls closure for @a error_cb
439 * @return handle to abort the request
440 */
441struct GNUNET_NAMESTORE_QueueEntry *
442GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
443 GNUNET_SCHEDULER_TaskCallback error_cb,
444 void *error_cb_cls);
445
446/**
447 * Lookup an item in the namestore.
448 *
449 * @param h handle to the namestore
450 * @param pkey private key of the zone
451 * @param label name that is being mapped
452 * @param error_cb function to call on error (i.e. disconnect)
453 * the handle is afterwards invalid
454 * @param error_cb_cls closure for @a error_cb
455 * @param rm function to call with the result (with 0 records if we don't have that label);
456 * the handle is afterwards invalid
457 * @param rm_cls closure for @a rm
458 * @return handle to abort the request
459 */
460struct GNUNET_NAMESTORE_QueueEntry *
461GNUNET_NAMESTORE_records_select (struct GNUNET_NAMESTORE_Handle *h,
462 const struct
463 GNUNET_IDENTITY_PrivateKey *pkey,
464 const char *label,
465 GNUNET_SCHEDULER_TaskCallback error_cb,
466 void *error_cb_cls,
467 GNUNET_NAMESTORE_RecordMonitor rm,
468 void *rm_cls);
469
470
471/**
472 * Creates, deletes or updates an item in the namestore.
473 * If the item is already present, it is replaced with the new record set.
474 * Use an empty array to remove all records under the given name.
475 *
476 * The continuation is called after the value has been stored in the
477 * database. Monitors may be notified asynchronously (basically with
478 * a buffer). However, if any monitor is consistently too slow to
479 * keep up with the changes, calling @a cont will be delayed until the
480 * monitors do keep up.
481 *
482 * @param h handle to the namestore
483 * @param pkey private key of the zone
484 * @param label name that is being mapped
485 * @param rd_count number of records in the 'rd' array
486 * @param rd array of records with data to store
487 * @param cont continuation to call when done
488 * @param cont_cls closure for @a cont 447 * @param cont_cls closure for @a cont
489 * @return handle to abort the request 448 * @return handle to abort the request
490 */ 449 */
491struct GNUNET_NAMESTORE_QueueEntry * 450struct GNUNET_NAMESTORE_QueueEntry *
492GNUNET_NAMESTORE_records_replace (struct GNUNET_NAMESTORE_Handle *h, 451GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
493 const struct GNUNET_IDENTITY_PrivateKey *pkey, 452 GNUNET_NAMESTORE_ContinuationWithStatus
494 const char *label, 453 cont,
495 unsigned int rd_count, 454 void *cont_cls);
496 const struct GNUNET_GNSRECORD_Data *rd,
497 GNUNET_NAMESTORE_ContinuationWithStatus cont,
498 void *cont_cls);
499 455
500#if 0 /* keep Emacsens' auto-indent happy */ 456#if 0 /* keep Emacsens' auto-indent happy */
501{ 457{
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index dc66a0401..509c97fb2 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -3603,6 +3603,28 @@ extern "C" {
3603 3603
3604/*********************************************************************************/ 3604/*********************************************************************************/
3605 3605
3606/*********************************************************************************/
3607/********************************** NAMESTORE (cont.) **************************/
3608/*********************************************************************************/
3609/* NAMESTORE: message types 1750-1800
3610 */
3611
3612/**
3613 * Message type for Begin, Commit or Rollback
3614 */
3615#define GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL 1750
3616
3617/**
3618 * Return status message for control message
3619 */
3620#define GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT 1751
3621
3622/**
3623 * Open and lock records for editing message
3624 */
3625#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_EDIT 1752
3626
3627
3606/** 3628/**
3607 * Type used to match 'all' message types. 3629 * Type used to match 'all' message types.
3608 */ 3630 */
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index 51708dd67..32f2605ca 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -15,26 +15,6 @@ if USE_COVERAGE
15 XLIBS = -lgcov 15 XLIBS = -lgcov
16endif 16endif
17 17
18HEAP_PLUGIN = libgnunet_plugin_namestore_flat.la
19HEAP_TESTS = test_plugin_namestore_flat \
20 test_namestore_api_store_flat \
21 test_namestore_api_store_update_flat \
22 test_namestore_api_remove_flat \
23 test_namestore_api_zone_iteration_flat \
24 test_namestore_api_lookup_nick_flat \
25 test_namestore_api_monitoring_flat \
26 test_namestore_api_lookup_public_flat \
27 test_namestore_api_lookup_private_flat \
28 test_namestore_api_lookup_shadow_flat \
29 test_namestore_api_lookup_shadow_filter_flat \
30 test_namestore_api_remove_not_existing_record_flat \
31 test_namestore_api_zone_iteration_nick_flat \
32 test_namestore_api_zone_iteration_specific_zone_flat \
33 test_namestore_api_zone_iteration_stop_flat \
34 test_namestore_api_monitoring_existing_flat \
35 test_namestore_api_zone_to_name_flat \
36 perf_namestore_api_zone_iteration_flat
37
38if HAVE_SQLITE 18if HAVE_SQLITE
39SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la 19SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la
40SQLITE_TESTS = test_plugin_namestore_sqlite \ 20SQLITE_TESTS = test_plugin_namestore_sqlite \
@@ -54,7 +34,8 @@ SQLITE_TESTS = test_plugin_namestore_sqlite \
54 test_namestore_api_zone_iteration_stop_sqlite \ 34 test_namestore_api_zone_iteration_stop_sqlite \
55 test_namestore_api_monitoring_existing_sqlite \ 35 test_namestore_api_monitoring_existing_sqlite \
56 test_namestore_api_zone_to_name_sqlite \ 36 test_namestore_api_zone_to_name_sqlite \
57 perf_namestore_api_zone_iteration_sqlite 37 perf_namestore_api_zone_iteration_sqlite \
38 test_namestore_api_tx_rollback_sqlite
58endif 39endif
59 40
60if HAVE_POSTGRESQL 41if HAVE_POSTGRESQL
@@ -76,14 +57,14 @@ POSTGRES_TESTS = test_plugin_namestore_postgres \
76 test_namestore_api_zone_iteration_stop_postgres \ 57 test_namestore_api_zone_iteration_stop_postgres \
77 test_namestore_api_monitoring_existing_postgres \ 58 test_namestore_api_monitoring_existing_postgres \
78 test_namestore_api_zone_to_name_postgres \ 59 test_namestore_api_zone_to_name_postgres \
79 perf_namestore_api_zone_iteration_postgres 60 perf_namestore_api_zone_iteration_postgres \
61 test_namestore_api_tx_rollback_postgres
80endif 62endif
81 63
82if HAVE_SQLITE 64if HAVE_SQLITE
83check_PROGRAMS = \ 65check_PROGRAMS = \
84 $(SQLITE_TESTS) \ 66 $(SQLITE_TESTS) \
85 $(POSTGRES_TESTS) \ 67 $(POSTGRES_TESTS)
86 $(HEAP_TESTS)
87endif 68endif
88 69
89if ENABLE_TEST_RUN 70if ENABLE_TEST_RUN
@@ -113,7 +94,6 @@ libexec_PROGRAMS += \
113plugin_LTLIBRARIES = \ 94plugin_LTLIBRARIES = \
114 $(SQLITE_PLUGIN) \ 95 $(SQLITE_PLUGIN) \
115 $(POSTGRES_PLUGIN) \ 96 $(POSTGRES_PLUGIN) \
116 $(HEAP_PLUGIN) \
117 $(REST_PLUGIN) 97 $(REST_PLUGIN)
118 98
119 99
@@ -195,18 +175,6 @@ gnunet_service_namestore_LDADD = \
195 175
196 176
197 177
198libgnunet_plugin_namestore_flat_la_SOURCES = \
199 plugin_namestore_flat.c
200libgnunet_plugin_namestore_flat_la_LIBADD = \
201 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
202 $(top_builddir)/src/identity/libgnunetidentity.la \
203 $(top_builddir)/src/statistics/libgnunetstatistics.la \
204 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
205 $(LTLIBINTL)
206libgnunet_plugin_namestore_flat_la_LDFLAGS = \
207 $(GN_PLUGIN_LDFLAGS)
208
209
210libgnunet_plugin_namestore_sqlite_la_SOURCES = \ 178libgnunet_plugin_namestore_sqlite_la_SOURCES = \
211 plugin_namestore_sqlite.c 179 plugin_namestore_sqlite.c
212libgnunet_plugin_namestore_sqlite_la_LIBADD = \ 180libgnunet_plugin_namestore_sqlite_la_LIBADD = \
@@ -231,15 +199,6 @@ libgnunet_plugin_namestore_postgres_la_LIBADD = \
231libgnunet_plugin_namestore_postgres_la_LDFLAGS = \ 199libgnunet_plugin_namestore_postgres_la_LDFLAGS = \
232 $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS) 200 $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS)
233 201
234test_namestore_api_store_flat_SOURCES = \
235 test_namestore_api_store.c
236test_namestore_api_store_flat_LDADD = \
237 $(top_builddir)/src/testing/libgnunettesting.la \
238 $(top_builddir)/src/util/libgnunetutil.la \
239 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
240 $(top_builddir)/src/identity/libgnunetidentity.la \
241 libgnunetnamestore.la
242
243test_namestore_api_store_sqlite_SOURCES = \ 202test_namestore_api_store_sqlite_SOURCES = \
244 test_namestore_api_store.c 203 test_namestore_api_store.c
245test_namestore_api_store_sqlite_LDADD = \ 204test_namestore_api_store_sqlite_LDADD = \
@@ -258,16 +217,6 @@ test_namestore_api_store_postgres_LDADD = \
258 $(top_builddir)/src/identity/libgnunetidentity.la \ 217 $(top_builddir)/src/identity/libgnunetidentity.la \
259 libgnunetnamestore.la 218 libgnunetnamestore.la
260 219
261test_namestore_api_store_update_flat_SOURCES = \
262 test_namestore_api_store_update.c
263test_namestore_api_store_update_flat_LDADD = \
264 $(top_builddir)/src/testing/libgnunettesting.la \
265 $(top_builddir)/src/util/libgnunetutil.la \
266 $(top_builddir)/src/identity/libgnunetidentity.la \
267 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
268 $(top_builddir)/src/namecache/libgnunetnamecache.la \
269 libgnunetnamestore.la
270
271test_namestore_api_store_update_sqlite_SOURCES = \ 220test_namestore_api_store_update_sqlite_SOURCES = \
272 test_namestore_api_store_update.c 221 test_namestore_api_store_update.c
273test_namestore_api_store_update_sqlite_LDADD = \ 222test_namestore_api_store_update_sqlite_LDADD = \
@@ -288,16 +237,6 @@ test_namestore_api_store_update_postgres_LDADD = \
288 $(top_builddir)/src/namecache/libgnunetnamecache.la \ 237 $(top_builddir)/src/namecache/libgnunetnamecache.la \
289 libgnunetnamestore.la 238 libgnunetnamestore.la
290 239
291test_namestore_api_lookup_public_flat_SOURCES = \
292 test_namestore_api_lookup_public.c
293test_namestore_api_lookup_public_flat_LDADD = \
294 $(top_builddir)/src/testing/libgnunettesting.la \
295 $(top_builddir)/src/identity/libgnunetidentity.la \
296 $(top_builddir)/src/util/libgnunetutil.la \
297 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
298 $(top_builddir)/src/namecache/libgnunetnamecache.la \
299 libgnunetnamestore.la
300
301test_namestore_api_lookup_public_sqlite_SOURCES = \ 240test_namestore_api_lookup_public_sqlite_SOURCES = \
302 test_namestore_api_lookup_public.c 241 test_namestore_api_lookup_public.c
303test_namestore_api_lookup_public_sqlite_LDADD = \ 242test_namestore_api_lookup_public_sqlite_LDADD = \
@@ -338,26 +277,6 @@ test_namestore_api_lookup_nick_postgres_LDADD = \
338 $(top_builddir)/src/namecache/libgnunetnamecache.la \ 277 $(top_builddir)/src/namecache/libgnunetnamecache.la \
339 libgnunetnamestore.la 278 libgnunetnamestore.la
340 279
341test_namestore_api_lookup_nick_flat_SOURCES = \
342 test_namestore_api_lookup_nick.c
343test_namestore_api_lookup_nick_flat_LDADD = \
344 $(top_builddir)/src/testing/libgnunettesting.la \
345 $(top_builddir)/src/identity/libgnunetidentity.la \
346 $(top_builddir)/src/util/libgnunetutil.la \
347 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
348 $(top_builddir)/src/namecache/libgnunetnamecache.la \
349 libgnunetnamestore.la
350
351test_namestore_api_lookup_private_flat_SOURCES = \
352 test_namestore_api_lookup_private.c
353test_namestore_api_lookup_private_flat_LDADD = \
354 $(top_builddir)/src/testing/libgnunettesting.la \
355 $(top_builddir)/src/identity/libgnunetidentity.la \
356 $(top_builddir)/src/util/libgnunetutil.la \
357 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
358 $(top_builddir)/src/namecache/libgnunetnamecache.la \
359 libgnunetnamestore.la
360
361test_namestore_api_lookup_private_sqlite_SOURCES = \ 280test_namestore_api_lookup_private_sqlite_SOURCES = \
362 test_namestore_api_lookup_private.c 281 test_namestore_api_lookup_private.c
363test_namestore_api_lookup_private_sqlite_LDADD = \ 282test_namestore_api_lookup_private_sqlite_LDADD = \
@@ -378,16 +297,6 @@ test_namestore_api_lookup_private_postgres_LDADD = \
378 $(top_builddir)/src/namecache/libgnunetnamecache.la \ 297 $(top_builddir)/src/namecache/libgnunetnamecache.la \
379 libgnunetnamestore.la 298 libgnunetnamestore.la
380 299
381test_namestore_api_lookup_shadow_flat_SOURCES = \
382 test_namestore_api_lookup_shadow.c
383test_namestore_api_lookup_shadow_flat_LDADD = \
384 $(top_builddir)/src/testing/libgnunettesting.la \
385 $(top_builddir)/src/identity/libgnunetidentity.la \
386 $(top_builddir)/src/util/libgnunetutil.la \
387 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
388 $(top_builddir)/src/namecache/libgnunetnamecache.la \
389 libgnunetnamestore.la
390
391test_namestore_api_lookup_shadow_sqlite_SOURCES = \ 300test_namestore_api_lookup_shadow_sqlite_SOURCES = \
392 test_namestore_api_lookup_shadow.c 301 test_namestore_api_lookup_shadow.c
393test_namestore_api_lookup_shadow_sqlite_LDADD = \ 302test_namestore_api_lookup_shadow_sqlite_LDADD = \
@@ -408,16 +317,6 @@ test_namestore_api_lookup_shadow_postgres_LDADD = \
408 $(top_builddir)/src/namecache/libgnunetnamecache.la \ 317 $(top_builddir)/src/namecache/libgnunetnamecache.la \
409 libgnunetnamestore.la 318 libgnunetnamestore.la
410 319
411test_namestore_api_lookup_shadow_filter_flat_SOURCES = \
412 test_namestore_api_lookup_shadow_filter.c
413test_namestore_api_lookup_shadow_filter_flat_LDADD = \
414 $(top_builddir)/src/testing/libgnunettesting.la \
415 $(top_builddir)/src/util/libgnunetutil.la \
416 $(top_builddir)/src/identity/libgnunetidentity.la \
417 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
418 $(top_builddir)/src/namecache/libgnunetnamecache.la \
419 libgnunetnamestore.la
420
421test_namestore_api_lookup_shadow_filter_sqlite_SOURCES = \ 320test_namestore_api_lookup_shadow_filter_sqlite_SOURCES = \
422 test_namestore_api_lookup_shadow_filter.c 321 test_namestore_api_lookup_shadow_filter.c
423test_namestore_api_lookup_shadow_filter_sqlite_LDADD = \ 322test_namestore_api_lookup_shadow_filter_sqlite_LDADD = \
@@ -455,24 +354,6 @@ test_namestore_api_remove_postgres_LDADD = \
455 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 354 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
456 libgnunetnamestore.la 355 libgnunetnamestore.la
457 356
458test_namestore_api_remove_flat_SOURCES = \
459 test_namestore_api_remove.c
460test_namestore_api_remove_flat_LDADD = \
461 $(top_builddir)/src/testing/libgnunettesting.la \
462 $(top_builddir)/src/identity/libgnunetidentity.la \
463 $(top_builddir)/src/util/libgnunetutil.la \
464 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
465 libgnunetnamestore.la
466
467test_namestore_api_remove_not_existing_record_flat_SOURCES = \
468 test_namestore_api_remove_not_existing_record.c
469test_namestore_api_remove_not_existing_record_flat_LDADD = \
470 $(top_builddir)/src/testing/libgnunettesting.la \
471 $(top_builddir)/src/identity/libgnunetidentity.la \
472 $(top_builddir)/src/util/libgnunetutil.la \
473 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
474 libgnunetnamestore.la
475
476test_namestore_api_remove_not_existing_record_sqlite_SOURCES = \ 357test_namestore_api_remove_not_existing_record_sqlite_SOURCES = \
477 test_namestore_api_remove_not_existing_record.c 358 test_namestore_api_remove_not_existing_record.c
478test_namestore_api_remove_not_existing_record_sqlite_LDADD = \ 359test_namestore_api_remove_not_existing_record_sqlite_LDADD = \
@@ -491,14 +372,6 @@ test_namestore_api_remove_not_existing_record_postgres_LDADD = \
491 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 372 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
492 libgnunetnamestore.la 373 libgnunetnamestore.la
493 374
494test_namestore_api_zone_to_name_flat_SOURCES = \
495 test_namestore_api_zone_to_name.c
496test_namestore_api_zone_to_name_flat_LDADD = \
497 $(top_builddir)/src/identity/libgnunetidentity.la \
498 $(top_builddir)/src/testing/libgnunettesting.la \
499 $(top_builddir)/src/util/libgnunetutil.la \
500 libgnunetnamestore.la
501
502test_namestore_api_zone_to_name_sqlite_SOURCES = \ 375test_namestore_api_zone_to_name_sqlite_SOURCES = \
503 test_namestore_api_zone_to_name.c 376 test_namestore_api_zone_to_name.c
504test_namestore_api_zone_to_name_sqlite_LDADD = \ 377test_namestore_api_zone_to_name_sqlite_LDADD = \
@@ -515,15 +388,6 @@ test_namestore_api_zone_to_name_postgres_LDADD = \
515 $(top_builddir)/src/util/libgnunetutil.la \ 388 $(top_builddir)/src/util/libgnunetutil.la \
516 libgnunetnamestore.la 389 libgnunetnamestore.la
517 390
518test_namestore_api_monitoring_flat_SOURCES = \
519 test_namestore_api_monitoring.c
520test_namestore_api_monitoring_flat_LDADD = \
521 $(top_builddir)/src/testing/libgnunettesting.la \
522 libgnunetnamestore.la \
523 $(top_builddir)/src/identity/libgnunetidentity.la \
524 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
525 $(top_builddir)/src/util/libgnunetutil.la
526
527test_namestore_api_monitoring_sqlite_SOURCES = \ 391test_namestore_api_monitoring_sqlite_SOURCES = \
528 test_namestore_api_monitoring.c 392 test_namestore_api_monitoring.c
529test_namestore_api_monitoring_sqlite_LDADD = \ 393test_namestore_api_monitoring_sqlite_LDADD = \
@@ -542,15 +406,6 @@ test_namestore_api_monitoring_postgres_LDADD = \
542 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 406 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
543 $(top_builddir)/src/util/libgnunetutil.la 407 $(top_builddir)/src/util/libgnunetutil.la
544 408
545test_namestore_api_monitoring_existing_flat_SOURCES = \
546 test_namestore_api_monitoring_existing.c
547test_namestore_api_monitoring_existing_flat_LDADD = \
548 $(top_builddir)/src/testing/libgnunettesting.la \
549 $(top_builddir)/src/identity/libgnunetidentity.la \
550 libgnunetnamestore.la \
551 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
552 $(top_builddir)/src/util/libgnunetutil.la
553
554test_namestore_api_monitoring_existing_sqlite_SOURCES = \ 409test_namestore_api_monitoring_existing_sqlite_SOURCES = \
555 test_namestore_api_monitoring_existing.c 410 test_namestore_api_monitoring_existing.c
556test_namestore_api_monitoring_existing_sqlite_LDADD = \ 411test_namestore_api_monitoring_existing_sqlite_LDADD = \
@@ -569,14 +424,25 @@ test_namestore_api_monitoring_existing_postgres_LDADD = \
569 $(top_builddir)/src/identity/libgnunetidentity.la \ 424 $(top_builddir)/src/identity/libgnunetidentity.la \
570 $(top_builddir)/src/util/libgnunetutil.la 425 $(top_builddir)/src/util/libgnunetutil.la
571 426
572test_namestore_api_zone_iteration_flat_SOURCES = \ 427test_namestore_api_tx_rollback_sqlite_SOURCES = \
573 test_namestore_api_zone_iteration.c 428 test_namestore_api_tx_rollback.c
574test_namestore_api_zone_iteration_flat_LDADD = \ 429test_namestore_api_tx_rollback_sqlite_LDADD = \
575 $(top_builddir)/src/testing/libgnunettesting.la \ 430 $(top_builddir)/src/testing/libgnunettesting.la \
576 $(top_builddir)/src/identity/libgnunetidentity.la \ 431 $(top_builddir)/src/identity/libgnunetidentity.la \
577 $(top_builddir)/src/util/libgnunetutil.la \ 432 libgnunetnamestore.la \
578 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 433 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
579 libgnunetnamestore.la 434 $(top_builddir)/src/util/libgnunetutil.la
435
436test_namestore_api_tx_rollback_postgres_SOURCES = \
437 test_namestore_api_tx_rollback.c
438test_namestore_api_tx_rollback_postgres_LDADD = \
439 $(top_builddir)/src/testing/libgnunettesting.la \
440 $(top_builddir)/src/identity/libgnunetidentity.la \
441 libgnunetnamestore.la \
442 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
443 $(top_builddir)/src/util/libgnunetutil.la
444
445
580 446
581test_namestore_api_zone_iteration_sqlite_SOURCES = \ 447test_namestore_api_zone_iteration_sqlite_SOURCES = \
582 test_namestore_api_zone_iteration.c 448 test_namestore_api_zone_iteration.c
@@ -614,24 +480,6 @@ perf_namestore_api_zone_iteration_sqlite_LDADD = \
614 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 480 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
615 libgnunetnamestore.la 481 libgnunetnamestore.la
616 482
617perf_namestore_api_zone_iteration_flat_SOURCES = \
618 perf_namestore_api_zone_iteration.c
619perf_namestore_api_zone_iteration_flat_LDADD = \
620 $(top_builddir)/src/testing/libgnunettesting.la \
621 $(top_builddir)/src/identity/libgnunetidentity.la \
622 $(top_builddir)/src/util/libgnunetutil.la \
623 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
624 libgnunetnamestore.la
625
626test_namestore_api_zone_iteration_nick_flat_SOURCES = \
627 test_namestore_api_zone_iteration_nick.c
628test_namestore_api_zone_iteration_nick_flat_LDADD = \
629 $(top_builddir)/src/testing/libgnunettesting.la \
630 $(top_builddir)/src/util/libgnunetutil.la \
631 $(top_builddir)/src/identity/libgnunetidentity.la \
632 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
633 libgnunetnamestore.la
634
635test_namestore_api_zone_iteration_nick_sqlite_SOURCES = \ 483test_namestore_api_zone_iteration_nick_sqlite_SOURCES = \
636 test_namestore_api_zone_iteration_nick.c 484 test_namestore_api_zone_iteration_nick.c
637test_namestore_api_zone_iteration_nick_sqlite_LDADD = \ 485test_namestore_api_zone_iteration_nick_sqlite_LDADD = \
@@ -650,15 +498,6 @@ test_namestore_api_zone_iteration_nick_postgres_LDADD = \
650 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 498 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
651 libgnunetnamestore.la 499 libgnunetnamestore.la
652 500
653test_namestore_api_zone_iteration_specific_zone_flat_SOURCES = \
654 test_namestore_api_zone_iteration_specific_zone.c
655test_namestore_api_zone_iteration_specific_zone_flat_LDADD = \
656 $(top_builddir)/src/testing/libgnunettesting.la \
657 $(top_builddir)/src/identity/libgnunetidentity.la \
658 $(top_builddir)/src/util/libgnunetutil.la \
659 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
660 libgnunetnamestore.la
661
662test_namestore_api_zone_iteration_specific_zone_sqlite_SOURCES = \ 501test_namestore_api_zone_iteration_specific_zone_sqlite_SOURCES = \
663 test_namestore_api_zone_iteration_specific_zone.c 502 test_namestore_api_zone_iteration_specific_zone.c
664test_namestore_api_zone_iteration_specific_zone_sqlite_LDADD = \ 503test_namestore_api_zone_iteration_specific_zone_sqlite_LDADD = \
@@ -677,15 +516,6 @@ test_namestore_api_zone_iteration_specific_zone_postgres_LDADD = \
677 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 516 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
678 libgnunetnamestore.la 517 libgnunetnamestore.la
679 518
680test_namestore_api_zone_iteration_stop_flat_SOURCES = \
681 test_namestore_api_zone_iteration_stop.c
682test_namestore_api_zone_iteration_stop_flat_LDADD = \
683 $(top_builddir)/src/testing/libgnunettesting.la \
684 $(top_builddir)/src/identity/libgnunetidentity.la \
685 $(top_builddir)/src/util/libgnunetutil.la \
686 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
687 libgnunetnamestore.la
688
689test_namestore_api_zone_iteration_stop_sqlite_SOURCES = \ 519test_namestore_api_zone_iteration_stop_sqlite_SOURCES = \
690 test_namestore_api_zone_iteration_stop.c 520 test_namestore_api_zone_iteration_stop.c
691test_namestore_api_zone_iteration_stop_sqlite_LDADD = \ 521test_namestore_api_zone_iteration_stop_sqlite_LDADD = \
@@ -704,13 +534,6 @@ test_namestore_api_zone_iteration_stop_postgres_LDADD = \
704 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 534 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
705 libgnunetnamestore.la 535 libgnunetnamestore.la
706 536
707test_plugin_namestore_flat_SOURCES = \
708 test_plugin_namestore.c
709test_plugin_namestore_flat_LDADD = \
710 $(top_builddir)/src/testing/libgnunettesting.la \
711 $(top_builddir)/src/identity/libgnunetidentity.la \
712 $(top_builddir)/src/util/libgnunetutil.la
713
714test_plugin_namestore_sqlite_SOURCES = \ 537test_plugin_namestore_sqlite_SOURCES = \
715 test_plugin_namestore.c 538 test_plugin_namestore.c
716test_plugin_namestore_sqlite_LDADD = \ 539test_plugin_namestore_sqlite_LDADD = \
@@ -738,12 +561,9 @@ EXTRA_DIST = \
738 test_namestore_api.conf \ 561 test_namestore_api.conf \
739 test_namestore_api_postgres.conf \ 562 test_namestore_api_postgres.conf \
740 test_namestore_api_sqlite.conf \ 563 test_namestore_api_sqlite.conf \
741 test_namestore_api_flat.conf \
742 perf_namestore_api_postgres.conf \ 564 perf_namestore_api_postgres.conf \
743 perf_namestore_api_sqlite.conf \ 565 perf_namestore_api_sqlite.conf \
744 perf_namestore_api_flat.conf \
745 test_plugin_namestore_sqlite.conf \ 566 test_plugin_namestore_sqlite.conf \
746 test_plugin_namestore_postgres.conf \ 567 test_plugin_namestore_postgres.conf \
747 test_plugin_namestore_flat.conf \
748 test_hostkey \ 568 test_hostkey \
749 $(check_SCRIPTS) 569 $(check_SCRIPTS)
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index 6d3cc45ec..1f621c5f0 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -132,6 +132,11 @@ struct NamestoreClient
132 struct GNUNET_SERVICE_Client *client; 132 struct GNUNET_SERVICE_Client *client;
133 133
134 /** 134 /**
135 * Database handle
136 */
137 struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
138
139 /**
135 * Message queue for transmission to @e client 140 * Message queue for transmission to @e client
136 */ 141 */
137 struct GNUNET_MQ_Handle *mq; 142 struct GNUNET_MQ_Handle *mq;
@@ -353,11 +358,6 @@ static struct GNUNET_STATISTICS_Handle *statistics;
353static struct GNUNET_NAMECACHE_Handle *namecache; 358static struct GNUNET_NAMECACHE_Handle *namecache;
354 359
355/** 360/**
356 * Database handle
357 */
358static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
359
360/**
361 * Name of the database plugin 361 * Name of the database plugin
362 */ 362 */
363static char *db_lib_name; 363static char *db_lib_name;
@@ -436,7 +436,6 @@ cleanup_task (void *cls)
436 GNUNET_NAMECACHE_disconnect (namecache); 436 GNUNET_NAMECACHE_disconnect (namecache);
437 namecache = NULL; 437 namecache = NULL;
438 } 438 }
439 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
440 GNUNET_free (db_lib_name); 439 GNUNET_free (db_lib_name);
441 db_lib_name = NULL; 440 db_lib_name = NULL;
442 if (NULL != monitor_nc) 441 if (NULL != monitor_nc)
@@ -560,11 +559,13 @@ cache_nick (const struct GNUNET_IDENTITY_PrivateKey *zone,
560/** 559/**
561 * Return the NICK record for the zone (if it exists). 560 * Return the NICK record for the zone (if it exists).
562 * 561 *
562 * @param nc the namestore client
563 * @param zone private key for the zone to look for nick 563 * @param zone private key for the zone to look for nick
564 * @return NULL if no NICK record was found 564 * @return NULL if no NICK record was found
565 */ 565 */
566static struct GNUNET_GNSRECORD_Data * 566static struct GNUNET_GNSRECORD_Data *
567get_nick_record (const struct GNUNET_IDENTITY_PrivateKey *zone) 567get_nick_record (const struct NamestoreClient *nc,
568 const struct GNUNET_IDENTITY_PrivateKey *zone)
568{ 569{
569 struct GNUNET_IDENTITY_PublicKey pub; 570 struct GNUNET_IDENTITY_PublicKey pub;
570 struct GNUNET_GNSRECORD_Data *nick; 571 struct GNUNET_GNSRECORD_Data *nick;
@@ -588,11 +589,11 @@ get_nick_record (const struct GNUNET_IDENTITY_PrivateKey *zone)
588 } 589 }
589 590
590 nick = NULL; 591 nick = NULL;
591 res = GSN_database->lookup_records (GSN_database->cls, 592 res = nc->GSN_database->lookup_records (nc->GSN_database->cls,
592 zone, 593 zone,
593 GNUNET_GNS_EMPTY_LABEL_AT, 594 GNUNET_GNS_EMPTY_LABEL_AT,
594 &lookup_nick_it, 595 &lookup_nick_it,
595 &nick); 596 &nick);
596 if ((GNUNET_OK != res) || (NULL == nick)) 597 if ((GNUNET_OK != res) || (NULL == nick))
597 { 598 {
598#if ! defined(GNUNET_CULL_LOGGING) 599#if ! defined(GNUNET_CULL_LOGGING)
@@ -735,7 +736,7 @@ send_lookup_response (struct NamestoreClient *nc,
735 char *name_tmp; 736 char *name_tmp;
736 char *rd_ser; 737 char *rd_ser;
737 738
738 nick = get_nick_record (zone_key); 739 nick = get_nick_record (nc, zone_key);
739 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd)); 740 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd));
740 741
741 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) 742 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
@@ -936,7 +937,7 @@ refresh_block (struct NamestoreClient *nc,
936 rd_clean[rd_count_clean++] = rd[i]; 937 rd_clean[rd_count_clean++] = rd[i];
937 } 938 }
938 939
939 nick = get_nick_record (zone_key); 940 nick = get_nick_record (nc, zone_key);
940 res_count = rd_count_clean; 941 res_count = rd_count_clean;
941 res = (struct GNUNET_GNSRECORD_Data *) rd_clean; /* fixme: a bit unclean... */ 942 res = (struct GNUNET_GNSRECORD_Data *) rd_clean; /* fixme: a bit unclean... */
942 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) 943 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
@@ -1168,6 +1169,7 @@ client_disconnect_cb (void *cls,
1168 for (cop = cop_head; NULL != cop; cop = cop->next) 1169 for (cop = cop_head; NULL != cop; cop = cop->next)
1169 if (nc == cop->nc) 1170 if (nc == cop->nc)
1170 cop->nc = NULL; 1171 cop->nc = NULL;
1172 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, nc->GSN_database));
1171 GNUNET_free (nc); 1173 GNUNET_free (nc);
1172} 1174}
1173 1175
@@ -1186,12 +1188,35 @@ client_connect_cb (void *cls,
1186 struct GNUNET_MQ_Handle *mq) 1188 struct GNUNET_MQ_Handle *mq)
1187{ 1189{
1188 struct NamestoreClient *nc; 1190 struct NamestoreClient *nc;
1191 char *database;
1192 char *db_lib_name;
1189 1193
1190 (void) cls; 1194 (void) cls;
1191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); 1195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1192 nc = GNUNET_new (struct NamestoreClient); 1196 nc = GNUNET_new (struct NamestoreClient);
1193 nc->client = client; 1197 nc->client = client;
1194 nc->mq = mq; 1198 nc->mq = mq;
1199 /* Loading database plugin */
1200 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (GSN_cfg,
1201 "namestore",
1202 "database",
1203 &database))
1204 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1205 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
1206 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading %s\n", db_lib_name);
1207 nc->GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1208 GNUNET_free (database);
1209 if (NULL == nc->GSN_database)
1210 {
1211 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1212 "Could not load database backend `%s'\n",
1213 db_lib_name);
1214 GNUNET_free (db_lib_name);
1215 GNUNET_free (nc);
1216 return NULL;
1217 }
1218 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loaded %s\n", db_lib_name);
1219 GNUNET_free (db_lib_name);
1195 return nc; 1220 return nc;
1196} 1221}
1197 1222
@@ -1402,12 +1427,12 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1402 rlc.res_rd_count = 0; 1427 rlc.res_rd_count = 0;
1403 rlc.res_rd = NULL; 1428 rlc.res_rd = NULL;
1404 rlc.rd_ser_len = 0; 1429 rlc.rd_ser_len = 0;
1405 rlc.nick = get_nick_record (&ll_msg->zone); 1430 rlc.nick = get_nick_record (nc, &ll_msg->zone);
1406 res = GSN_database->lookup_records (GSN_database->cls, 1431 res = nc->GSN_database->lookup_records (nc->GSN_database->cls,
1407 &ll_msg->zone, 1432 &ll_msg->zone,
1408 conv_name, 1433 conv_name,
1409 &lookup_it, 1434 &lookup_it,
1410 &rlc); 1435 &rlc);
1411 env = 1436 env =
1412 GNUNET_MQ_msg_extra (llr_msg, 1437 GNUNET_MQ_msg_extra (llr_msg,
1413 name_len + rlc.rd_ser_len, 1438 name_len + rlc.rd_ser_len,
@@ -1591,11 +1616,11 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1591 "Creating %u records for name `%s'\n", 1616 "Creating %u records for name `%s'\n",
1592 (unsigned int) rd_count, 1617 (unsigned int) rd_count,
1593 conv_name); 1618 conv_name);
1594 if ((GNUNET_NO == GSN_database->lookup_records (GSN_database->cls, 1619 if ((GNUNET_NO == nc->GSN_database->lookup_records (nc->GSN_database->cls,
1595 &rp_msg->private_key, 1620 &rp_msg->private_key,
1596 conv_name, 1621 conv_name,
1597 &get_block_exp_existing, 1622 &get_block_exp_existing,
1598 &existing_block_exp)) && 1623 &existing_block_exp)) &&
1599 (rd_count == 0)) 1624 (rd_count == 0))
1600 { 1625 {
1601 /* This name does not exist, so cannot be removed */ 1626 /* This name does not exist, so cannot be removed */
@@ -1676,11 +1701,11 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1676 /* remove nick record from cache, in case we have one there */ 1701 /* remove nick record from cache, in case we have one there */
1677 cache_nick (&rp_msg->private_key, NULL); 1702 cache_nick (&rp_msg->private_key, NULL);
1678 } 1703 }
1679 res = GSN_database->store_records (GSN_database->cls, 1704 res = nc->GSN_database->store_records (nc->GSN_database->cls,
1680 &rp_msg->private_key, 1705 &rp_msg->private_key,
1681 conv_name, 1706 conv_name,
1682 rd_nf_count, 1707 rd_nf_count,
1683 rd_nf); 1708 rd_nf);
1684 } 1709 }
1685 1710
1686 if (GNUNET_OK != res) 1711 if (GNUNET_OK != res)
@@ -1703,6 +1728,57 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1703 } 1728 }
1704} 1729}
1705 1730
1731/**
1732 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL message
1733 *
1734 * @param cls client sending the message
1735 * @param tx_msg message of type `struct TxControlMessage`
1736 */
1737static void
1738handle_tx_control (void *cls, const struct TxControlMessage *tx_msg)
1739{
1740 struct NamestoreClient *nc = cls;
1741 struct TxControlResultMessage *txr_msg;
1742 struct GNUNET_MQ_Envelope *env;
1743 enum GNUNET_GenericReturnValue ret;
1744 char *emsg;
1745 char *err_tmp;
1746 size_t err_len;
1747
1748 switch (ntohs (tx_msg->control))
1749 {
1750 case GNUNET_NAMESTORE_TX_BEGIN:
1751 ret = nc->GSN_database->transaction_begin (nc->GSN_database->cls,
1752 &emsg);
1753 break;
1754 case GNUNET_NAMESTORE_TX_COMMIT:
1755 ret = nc->GSN_database->transaction_commit (nc->GSN_database->cls,
1756 &emsg);
1757 break;
1758 case GNUNET_NAMESTORE_TX_ROLLBACK:
1759 ret = nc->GSN_database->transaction_rollback (nc->GSN_database->cls,
1760 &emsg);
1761 break;
1762 default:
1763 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1764 "Unknown control type %u\n", ntohs (tx_msg->control));
1765 GNUNET_break (0);
1766 }
1767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1768 "TX status is %u\n", ret);
1769 err_len = (GNUNET_YES == ret) ? 0 : strlen (emsg) + 1;
1770 env =
1771 GNUNET_MQ_msg_extra (txr_msg,
1772 err_len,
1773 GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT);
1774 txr_msg->gns_header.header.size = htons (sizeof (struct TxControlResultMessage) + err_len);
1775 txr_msg->gns_header.r_id = tx_msg->gns_header.r_id;
1776 txr_msg->success = htons (ret);
1777 err_tmp = (char *) &txr_msg[1];
1778 GNUNET_memcpy (err_tmp, emsg, err_len);
1779 GNUNET_MQ_send (nc->mq, env);
1780 GNUNET_SERVICE_client_continue (nc->client);
1781}
1706 1782
1707/** 1783/**
1708 * Context for record remove operations passed from #handle_zone_to_name to 1784 * Context for record remove operations passed from #handle_zone_to_name to
@@ -1817,11 +1893,11 @@ handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg)
1817 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id); 1893 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1818 ztn_ctx.nc = nc; 1894 ztn_ctx.nc = nc;
1819 ztn_ctx.success = GNUNET_NO; 1895 ztn_ctx.success = GNUNET_NO;
1820 if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls, 1896 if (GNUNET_SYSERR == nc->GSN_database->zone_to_name (nc->GSN_database->cls,
1821 &ztn_msg->zone, 1897 &ztn_msg->zone,
1822 &ztn_msg->value_zone, 1898 &ztn_msg->value_zone,
1823 &handle_zone_to_name_it, 1899 &handle_zone_to_name_it,
1824 &ztn_ctx)) 1900 &ztn_ctx))
1825 { 1901 {
1826 /* internal error, hang up instead of signalling something 1902 /* internal error, hang up instead of signalling something
1827 that might be wrong */ 1903 that might be wrong */
@@ -1935,6 +2011,7 @@ run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
1935 struct ZoneIterationProcResult proc; 2011 struct ZoneIterationProcResult proc;
1936 struct GNUNET_TIME_Absolute start; 2012 struct GNUNET_TIME_Absolute start;
1937 struct GNUNET_TIME_Relative duration; 2013 struct GNUNET_TIME_Relative duration;
2014 struct NamestoreClient *nc = zi->nc;
1938 2015
1939 memset (&proc, 0, sizeof(proc)); 2016 memset (&proc, 0, sizeof(proc));
1940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2017 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1945,15 +2022,16 @@ run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
1945 proc.limit = limit; 2022 proc.limit = limit;
1946 start = GNUNET_TIME_absolute_get (); 2023 start = GNUNET_TIME_absolute_get ();
1947 GNUNET_break (GNUNET_SYSERR != 2024 GNUNET_break (GNUNET_SYSERR !=
1948 GSN_database->iterate_records (GSN_database->cls, 2025 nc->GSN_database->iterate_records (nc->GSN_database->cls,
1949 (GNUNET_YES == GNUNET_is_zero ( 2026 (GNUNET_YES ==
1950 &zi->zone)) 2027 GNUNET_is_zero (
2028 &zi->zone))
1951 ? NULL 2029 ? NULL
1952 : &zi->zone, 2030 : &zi->zone,
1953 zi->seq, 2031 zi->seq,
1954 limit, 2032 limit,
1955 &zone_iterate_proc, 2033 &zone_iterate_proc,
1956 &proc)); 2034 &proc));
1957 duration = GNUNET_TIME_absolute_get_duration (start); 2035 duration = GNUNET_TIME_absolute_get_duration (start);
1958 duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit); 2036 duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit);
1959 GNUNET_STATISTICS_set (statistics, 2037 GNUNET_STATISTICS_set (statistics,
@@ -2212,6 +2290,7 @@ static void
2212monitor_iteration_next (void *cls) 2290monitor_iteration_next (void *cls)
2213{ 2291{
2214 struct ZoneMonitor *zm = cls; 2292 struct ZoneMonitor *zm = cls;
2293 struct NamestoreClient *nc = zm->nc;
2215 int ret; 2294 int ret;
2216 2295
2217 zm->task = NULL; 2296 zm->task = NULL;
@@ -2220,15 +2299,13 @@ monitor_iteration_next (void *cls)
2220 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */ 2299 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2221 else 2300 else
2222 zm->iteration_cnt = zm->limit; /* use it all */ 2301 zm->iteration_cnt = zm->limit; /* use it all */
2223 ret = GSN_database->iterate_records (GSN_database->cls, 2302 ret = nc->GSN_database->iterate_records (nc->GSN_database->cls,
2224 (GNUNET_YES == GNUNET_is_zero ( 2303 (GNUNET_YES == GNUNET_is_zero (
2225 &zm->zone)) 2304 &zm->zone)) ? NULL : &zm->zone,
2226 ? NULL 2305 zm->seq,
2227 : &zm->zone, 2306 zm->iteration_cnt,
2228 zm->seq, 2307 &monitor_iterate_cb,
2229 zm->iteration_cnt, 2308 zm);
2230 &monitor_iterate_cb,
2231 zm);
2232 if (GNUNET_SYSERR == ret) 2309 if (GNUNET_SYSERR == ret)
2233 { 2310 {
2234 GNUNET_SERVICE_client_drop (zm->nc->client); 2311 GNUNET_SERVICE_client_drop (zm->nc->client);
@@ -2330,26 +2407,8 @@ run (void *cls,
2330 namecache = GNUNET_NAMECACHE_connect (cfg); 2407 namecache = GNUNET_NAMECACHE_connect (cfg);
2331 GNUNET_assert (NULL != namecache); 2408 GNUNET_assert (NULL != namecache);
2332 } 2409 }
2333 /* Loading database plugin */
2334 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2335 "namestore",
2336 "database",
2337 &database))
2338 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2339
2340 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2341 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2342 GNUNET_free (database);
2343 statistics = GNUNET_STATISTICS_create ("namestore", cfg); 2410 statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2344 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); 2411 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
2345 if (NULL == GSN_database)
2346 {
2347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2348 "Could not load database backend `%s'\n",
2349 db_lib_name);
2350 GNUNET_SCHEDULER_shutdown ();
2351 return;
2352 }
2353} 2412}
2354 2413
2355 2414
@@ -2363,6 +2422,10 @@ GNUNET_SERVICE_MAIN (
2363 &client_connect_cb, 2422 &client_connect_cb,
2364 &client_disconnect_cb, 2423 &client_disconnect_cb,
2365 NULL, 2424 NULL,
2425 GNUNET_MQ_hd_fixed_size (tx_control,
2426 GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL,
2427 struct TxControlMessage,
2428 NULL),
2366 GNUNET_MQ_hd_var_size (record_store, 2429 GNUNET_MQ_hd_var_size (record_store,
2367 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, 2430 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2368 struct RecordStoreMessage, 2431 struct RecordStoreMessage,
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
index 583ec1e68..06feee13a 100644
--- a/src/namestore/namestore.h
+++ b/src/namestore/namestore.h
@@ -305,6 +305,54 @@ struct RecordResultMessage
305 */ 305 */
306}; 306};
307 307
308/**
309 * Send a transaction control message.
310 */
311struct TxControlMessage
312{
313 /**
314 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL
315 */
316 struct GNUNET_NAMESTORE_Header gns_header;
317
318 /**
319 * The type of control message to send
320 */
321 uint16_t control GNUNET_PACKED;
322
323 /**
324 * always zero (for alignment)
325 */
326 uint16_t reserved GNUNET_PACKED;
327
328};
329
330/**
331 * Result of a transaction control message.
332 */
333struct TxControlResultMessage
334{
335 /**
336 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT
337 */
338 struct GNUNET_NAMESTORE_Header gns_header;
339
340 /**
341 * The type of control message to send
342 */
343 uint16_t control GNUNET_PACKED;
344
345 /**
346 * Of type GNUNET_GenericReturnValue
347 */
348 uint16_t success GNUNET_PACKED;
349
350 /* followed by:
351 * an error message if status != ntohs(GNUNET_OK)
352 */
353};
354
355
308 356
309/** 357/**
310 * Start monitoring a zone. 358 * Start monitoring a zone.
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index 73f985803..26e1477f4 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -674,6 +674,60 @@ handle_record_result_end (void *cls, const struct GNUNET_NAMESTORE_Header *msg)
674 free_ze (ze); 674 free_ze (ze);
675} 675}
676 676
677/**
678 * Handle an incoming message of type
679 * #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT.
680 *
681 * @param qe the respective entry in the message queue
682 * @param msg the message we received
683 * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed
684 */
685static int
686check_tx_control_result (void *cls,
687 const struct TxControlResultMessage *msg)
688{
689 const char *err_tmp;
690 size_t err_len;
691
692 (void) cls;
693 err_len = ntohs (msg->gns_header.header.size)
694 - sizeof (struct TxControlResultMessage);
695 if ((GNUNET_YES == ntohs (msg->success)) && (err_len > 0))
696 {
697 GNUNET_break (0);
698 return GNUNET_SYSERR;
699 }
700 err_tmp = (const char *) &msg[1];
701 if ((err_len > 0) && ('\0' != err_tmp[err_len - 1]))
702 {
703 GNUNET_break (0);
704 return GNUNET_SYSERR;
705 }
706 return GNUNET_OK;
707}
708
709static void
710handle_tx_control_result (void *cls,
711 const struct TxControlResultMessage *msg)
712{
713 struct GNUNET_NAMESTORE_Handle *h = cls;
714 struct GNUNET_NAMESTORE_QueueEntry *qe;
715 int res;
716 const char *emsg;
717
718 qe = find_qe (h, ntohl (msg->gns_header.r_id));
719 emsg = (const char *) &msg[1];
720 res = ntohs (msg->success);
721 LOG (GNUNET_ERROR_TYPE_DEBUG,
722 "Received TX_CONTROL_RESULT with result %d\n",
723 res);
724 if (NULL == qe)
725 return;
726 if (NULL != qe->cont)
727 qe->cont (qe->cont_cls, res,
728 (GNUNET_YES == res) ? NULL : emsg);
729 free_qe (qe);
730}
677 731
678/** 732/**
679 * Handle an incoming message of type 733 * Handle an incoming message of type
@@ -839,6 +893,10 @@ reconnect (struct GNUNET_NAMESTORE_Handle *h)
839 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE, 893 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE,
840 struct LabelLookupResponseMessage, 894 struct LabelLookupResponseMessage,
841 h), 895 h),
896 GNUNET_MQ_hd_var_size (tx_control_result,
897 GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT,
898 struct TxControlResultMessage,
899 h),
842 GNUNET_MQ_handler_end () }; 900 GNUNET_MQ_handler_end () };
843 struct GNUNET_NAMESTORE_ZoneIterator *it; 901 struct GNUNET_NAMESTORE_ZoneIterator *it;
844 struct GNUNET_NAMESTORE_QueueEntry *qe; 902 struct GNUNET_NAMESTORE_QueueEntry *qe;
@@ -1344,43 +1402,65 @@ GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1344 * New API draft. Experimental 1402 * New API draft. Experimental
1345 */ 1403 */
1346 1404
1347struct GNUNET_NAMESTORE_QueueEntry * 1405static struct GNUNET_NAMESTORE_QueueEntry *
1348GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h, 1406send_transaction_control_msg (struct GNUNET_NAMESTORE_Handle *h,
1349 GNUNET_SCHEDULER_TaskCallback error_cb, 1407 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1350 void *error_cb_cls) 1408 void *cont_cls,
1409 enum GNUNET_NAMESTORE_TxControl ctrl)
1351{ 1410{
1411 struct GNUNET_NAMESTORE_QueueEntry *qe;
1412 struct GNUNET_MQ_Envelope *env;
1413 struct TxControlMessage *msg;
1414 uint32_t rid;
1415
1416 rid = get_op_id (h);
1417 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1418 qe->h = h;
1419 qe->cont = cont;
1420 qe->cont_cls = cont_cls;
1421 qe->op_id = rid;
1422 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1423
1424 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL);
1425 msg->gns_header.r_id = htonl (rid);
1426 msg->control = htons (ctrl);
1427 if (NULL == h->mq)
1428 qe->env = env;
1429 else
1430 GNUNET_MQ_send (h->mq, env);
1431 return qe;
1352 GNUNET_break (0); 1432 GNUNET_break (0);
1353 return NULL; 1433 return NULL;
1354} 1434}
1355 1435
1436struct GNUNET_NAMESTORE_QueueEntry *
1437GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
1438 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1439 void *cont_cls)
1440{
1441 return send_transaction_control_msg (h, cont, cont_cls,
1442 GNUNET_NAMESTORE_TX_BEGIN);
1443}
1356 1444
1357struct GNUNET_NAMESTORE_QueueEntry * 1445struct GNUNET_NAMESTORE_QueueEntry *
1358GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h, 1446GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
1359 GNUNET_SCHEDULER_TaskCallback error_cb, 1447 GNUNET_NAMESTORE_ContinuationWithStatus
1360 void *error_cb_cls) 1448 cont,
1449 void *cont_cls)
1361{ 1450{
1362 GNUNET_break (0); 1451 return send_transaction_control_msg (h, cont, cont_cls,
1363 return NULL; 1452 GNUNET_NAMESTORE_TX_COMMIT);
1364} 1453}
1365 1454
1366 1455
1367/**
1368 * Commit a namestore transaction.
1369 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
1370 *
1371 * @param h handle to the namestore
1372 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
1373 * the handle is afterwards invalid
1374 * @param error_cb_cls closure for @a error_cb
1375 * @return handle to abort the request
1376 */
1377struct GNUNET_NAMESTORE_QueueEntry * 1456struct GNUNET_NAMESTORE_QueueEntry *
1378GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h, 1457GNUNET_NAMESTORE_transaction_rollback (struct GNUNET_NAMESTORE_Handle *h,
1379 GNUNET_SCHEDULER_TaskCallback error_cb, 1458 GNUNET_NAMESTORE_ContinuationWithStatus
1380 void *error_cb_cls) 1459 cont,
1460 void *cont_cls)
1381{ 1461{
1382 GNUNET_break (0); 1462 return send_transaction_control_msg (h, cont, cont_cls,
1383 return NULL; 1463 GNUNET_NAMESTORE_TX_ROLLBACK);
1384} 1464}
1385 1465
1386 1466
diff --git a/src/namestore/perf_namestore_api_flat.conf b/src/namestore/perf_namestore_api_flat.conf
deleted file mode 100644
index 30759ce7a..000000000
--- a/src/namestore/perf_namestore_api_flat.conf
+++ /dev/null
@@ -1,10 +0,0 @@
1@INLINE@ test_namestore_api.conf
2
3[namestore]
4DATABASE = flat
5
6[namecache]
7DISABLE = YES
8
9[namestore-heap]
10FILENAME = $GNUNET_TEST_HOME/namestore/heap.db
diff --git a/src/namestore/plugin_namestore_flat.c b/src/namestore/plugin_namestore_flat.c
deleted file mode 100644
index 3576b14e0..000000000
--- a/src/namestore/plugin_namestore_flat.c
+++ /dev/null
@@ -1,818 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2015, 2018, 2019 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 namestore/plugin_namestore_flat.c
22 * @brief file-based namestore backend
23 * @author Martin Schanzenbach
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_namestore_plugin.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "namestore.h"
32
33/**
34 * Context for all functions in this plugin.
35 */
36struct Plugin
37{
38 const struct GNUNET_CONFIGURATION_Handle *cfg;
39
40 /**
41 * Database filename.
42 */
43 char *fn;
44
45 /**
46 * HashMap
47 */
48 struct GNUNET_CONTAINER_MultiHashMap *hm;
49};
50
51
52struct FlatFileEntry
53{
54 /**
55 * Entry zone
56 */
57 struct GNUNET_IDENTITY_PrivateKey private_key;
58
59 /**
60 * Record count.
61 */
62 uint32_t record_count;
63
64 /**
65 * Rvalue
66 */
67 uint64_t rvalue;
68
69 /**
70 * Record data
71 */
72 struct GNUNET_GNSRECORD_Data *record_data;
73
74 /**
75 * Label
76 */
77 char *label;
78};
79
80
81/**
82 * Hash contactenation of @a pkey and @a label into @a h
83 *
84 * @param pkey a key
85 * @param label a label
86 * @param h[out] initialized hash
87 */
88static void
89hash_pkey_and_label (const struct GNUNET_IDENTITY_PrivateKey *pkey,
90 const char *label,
91 struct GNUNET_HashCode *h)
92{
93 char *key;
94 size_t label_len;
95 size_t key_len;
96
97 label_len = strlen (label);
98 key_len = label_len + sizeof(struct GNUNET_IDENTITY_PrivateKey);
99 key = GNUNET_malloc (key_len);
100 GNUNET_memcpy (key,
101 label,
102 label_len);
103 GNUNET_memcpy (key + label_len,
104 pkey,
105 sizeof(struct GNUNET_IDENTITY_PrivateKey));
106 GNUNET_CRYPTO_hash (key,
107 key_len,
108 h);
109 GNUNET_free (key);
110}
111
112
113/**
114 * Initialize the database connections and associated
115 * data structures (create tables and indices
116 * as needed as well).
117 *
118 * @param plugin the plugin context (state for this module)
119 * @return #GNUNET_OK on success
120 */
121static int
122database_setup (struct Plugin *plugin)
123{
124 char *flatdbfile;
125 char *record_data;
126 char *zone_private_key;
127 char *record_data_b64;
128 char *buffer;
129 char *line;
130 char *label;
131 char *rvalue;
132 char *record_count;
133 size_t record_data_size;
134 uint64_t size;
135 struct GNUNET_HashCode hkey;
136 struct GNUNET_DISK_FileHandle *fh;
137 struct FlatFileEntry *entry;
138 struct GNUNET_DISK_MapHandle *mh;
139
140 if (GNUNET_OK !=
141 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
142 "namestore-flat",
143 "FILENAME",
144 &flatdbfile))
145 {
146 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
147 "namestore-flat",
148 "FILENAME");
149 return GNUNET_SYSERR;
150 }
151 if (GNUNET_OK !=
152 GNUNET_DISK_file_test (flatdbfile))
153 {
154 if (GNUNET_OK !=
155 GNUNET_DISK_directory_create_for_file (flatdbfile))
156 {
157 GNUNET_break (0);
158 GNUNET_free (flatdbfile);
159 return GNUNET_SYSERR;
160 }
161 }
162 /* flatdbfile should be UTF-8-encoded. If it isn't, it's a bug */
163 plugin->fn = flatdbfile;
164
165 /* Load data from file into hashmap */
166 plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
167 GNUNET_NO);
168 fh = GNUNET_DISK_file_open (flatdbfile,
169 GNUNET_DISK_OPEN_CREATE
170 | GNUNET_DISK_OPEN_READWRITE,
171 GNUNET_DISK_PERM_USER_WRITE
172 | GNUNET_DISK_PERM_USER_READ);
173 if (NULL == fh)
174 {
175 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
176 _ ("Unable to initialize file: %s.\n"),
177 flatdbfile);
178 return GNUNET_SYSERR;
179 }
180 if (GNUNET_SYSERR ==
181 GNUNET_DISK_file_size (flatdbfile,
182 &size,
183 GNUNET_YES,
184 GNUNET_YES))
185 {
186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
187 _ ("Unable to get filesize: %s.\n"),
188 flatdbfile);
189 GNUNET_DISK_file_close (fh);
190 return GNUNET_SYSERR;
191 }
192 if (size > SIZE_MAX)
193 {
194 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
195 _ ("File too big to map: %llu bytes.\n"),
196 (unsigned long long) size);
197 GNUNET_DISK_file_close (fh);
198 return GNUNET_SYSERR;
199 }
200 if (0 == size)
201 {
202 GNUNET_DISK_file_close (fh);
203 return GNUNET_OK;
204 }
205 buffer = GNUNET_DISK_file_map (fh,
206 &mh,
207 GNUNET_DISK_MAP_TYPE_READ,
208 size);
209 if (NULL == buffer)
210 {
211 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
212 "mmap");
213 GNUNET_DISK_file_close (fh);
214 return GNUNET_SYSERR;
215 }
216 if ('\0' != buffer[size - 1])
217 {
218 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
219 _ ("Namestore database file `%s' malformed\n"),
220 flatdbfile);
221 GNUNET_DISK_file_unmap (mh);
222 GNUNET_DISK_file_close (fh);
223 return GNUNET_SYSERR;
224 }
225
226 line = strtok (buffer, "\n");
227 while (NULL != line)
228 {
229 zone_private_key = strtok (line, ",");
230 if (NULL == zone_private_key)
231 break;
232 rvalue = strtok (NULL, ",");
233 if (NULL == rvalue)
234 break;
235 record_count = strtok (NULL, ",");
236 if (NULL == record_count)
237 break;
238 record_data_b64 = strtok (NULL, ",");
239 if (NULL == record_data_b64)
240 break;
241 label = strtok (NULL, ",");
242 if (NULL == label)
243 break;
244 line = strtok (NULL, "\n");
245 entry = GNUNET_new (struct FlatFileEntry);
246 {
247 unsigned long long ll;
248
249 if (1 != sscanf (rvalue,
250 "%llu",
251 &ll))
252 {
253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
254 "Error parsing entry\n");
255 GNUNET_free (entry);
256 break;
257 }
258 entry->rvalue = (uint64_t) ll;
259 }
260 {
261 unsigned int ui;
262
263 if (1 != sscanf (record_count,
264 "%u",
265 &ui))
266 {
267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
268 "Error parsing entry\n");
269 GNUNET_free (entry);
270 break;
271 }
272 entry->record_count = (uint32_t) ui;
273 }
274 entry->label = GNUNET_strdup (label);
275 record_data_size
276 = GNUNET_STRINGS_base64_decode (record_data_b64,
277 strlen (record_data_b64),
278 (void **) &record_data);
279 entry->record_data =
280 GNUNET_new_array (entry->record_count,
281 struct GNUNET_GNSRECORD_Data);
282 if (GNUNET_OK !=
283 GNUNET_GNSRECORD_records_deserialize (record_data_size,
284 record_data,
285 entry->record_count,
286 entry->record_data))
287 {
288 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
289 "Unable to deserialize record %s\n",
290 label);
291 GNUNET_free (entry->label);
292 GNUNET_free (entry);
293 GNUNET_free (record_data);
294 break;
295 }
296 GNUNET_free (record_data);
297
298 {
299 struct GNUNET_IDENTITY_PrivateKey *private_key;
300
301 GNUNET_STRINGS_base64_decode (zone_private_key,
302 strlen (zone_private_key),
303 (void **) &private_key);
304 entry->private_key = *private_key;
305 GNUNET_free (private_key);
306 }
307
308 hash_pkey_and_label (&entry->private_key,
309 label,
310 &hkey);
311 if (GNUNET_OK !=
312 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
313 &hkey,
314 entry,
315 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
316 {
317 GNUNET_free (entry);
318 GNUNET_break (0);
319 }
320 }
321 GNUNET_DISK_file_unmap (mh);
322 GNUNET_DISK_file_close (fh);
323 return GNUNET_OK;
324}
325
326
327/**
328 * Store values in hashmap in file and free data
329 *
330 * @param plugin the plugin context
331 * @param key key in the map
332 * @param value a `struct FlatFileEntry`
333 */
334static int
335store_and_free_entries (void *cls,
336 const struct GNUNET_HashCode *key,
337 void *value)
338{
339 struct GNUNET_DISK_FileHandle *fh = cls;
340 struct FlatFileEntry *entry = value;
341 char *line;
342 char *zone_private_key;
343 char *record_data_b64;
344 ssize_t data_size;
345
346 (void) key;
347 GNUNET_STRINGS_base64_encode (&entry->private_key,
348 sizeof(struct GNUNET_IDENTITY_PrivateKey),
349 &zone_private_key);
350 data_size = GNUNET_GNSRECORD_records_get_size (entry->record_count,
351 entry->record_data);
352 if (data_size < 0)
353 {
354 GNUNET_break (0);
355 GNUNET_free (zone_private_key);
356 return GNUNET_SYSERR;
357 }
358 if (data_size >= UINT16_MAX)
359 {
360 GNUNET_break (0);
361 GNUNET_free (zone_private_key);
362 return GNUNET_SYSERR;
363 }
364 {
365 char data[data_size];
366 ssize_t ret;
367
368 ret = GNUNET_GNSRECORD_records_serialize (entry->record_count,
369 entry->record_data,
370 data_size,
371 data);
372 if ((ret < 0) ||
373 (data_size != ret))
374 {
375 GNUNET_break (0);
376 GNUNET_free (zone_private_key);
377 return GNUNET_SYSERR;
378 }
379 GNUNET_STRINGS_base64_encode (data,
380 data_size,
381 &record_data_b64);
382 }
383 GNUNET_asprintf (&line,
384 "%s,%llu,%u,%s,%s\n",
385 zone_private_key,
386 (unsigned long long) entry->rvalue,
387 (unsigned int) entry->record_count,
388 record_data_b64,
389 entry->label);
390 GNUNET_free (record_data_b64);
391 GNUNET_free (zone_private_key);
392
393 GNUNET_DISK_file_write (fh,
394 line,
395 strlen (line));
396
397 GNUNET_free (line);
398 GNUNET_free (entry->label);
399 GNUNET_free (entry->record_data);
400 GNUNET_free (entry);
401 return GNUNET_YES;
402}
403
404
405/**
406 * Shutdown database connection and associate data
407 * structures.
408 * @param plugin the plugin context (state for this module)
409 */
410static void
411database_shutdown (struct Plugin *plugin)
412{
413 struct GNUNET_DISK_FileHandle *fh;
414
415 fh = GNUNET_DISK_file_open (plugin->fn,
416 GNUNET_DISK_OPEN_CREATE
417 | GNUNET_DISK_OPEN_TRUNCATE
418 | GNUNET_DISK_OPEN_READWRITE,
419 GNUNET_DISK_PERM_USER_WRITE
420 | GNUNET_DISK_PERM_USER_READ);
421 if (NULL == fh)
422 {
423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
424 _ ("Unable to initialize file: %s.\n"),
425 plugin->fn);
426 return;
427 }
428
429 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
430 &store_and_free_entries,
431 fh);
432 GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
433 /* append 0-terminator */
434 GNUNET_DISK_file_write (fh,
435 "",
436 1);
437 GNUNET_DISK_file_close (fh);
438}
439
440
441/**
442 * Store a record in the datastore. Removes any existing record in the
443 * same zone with the same name.
444 *
445 * @param cls closure (internal context for the plugin)
446 * @param zone_key private key of the zone
447 * @param label name that is being mapped (at most 255 characters long)
448 * @param rd_count number of entries in @a rd array
449 * @param rd array of records with data to store
450 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
451 */
452static int
453namestore_flat_store_records (void *cls,
454 const struct
455 GNUNET_IDENTITY_PrivateKey *zone_key,
456 const char *label,
457 unsigned int rd_count,
458 const struct GNUNET_GNSRECORD_Data *rd)
459{
460 struct Plugin *plugin = cls;
461 uint64_t rvalue;
462 struct GNUNET_HashCode hkey;
463 struct FlatFileEntry *entry;
464
465 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
466 UINT64_MAX);
467 hash_pkey_and_label (zone_key,
468 label,
469 &hkey);
470 GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm,
471 &hkey);
472 if (0 == rd_count)
473 {
474 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
475 "sqlite",
476 "Record deleted\n");
477 return GNUNET_OK;
478 }
479 entry = GNUNET_new (struct FlatFileEntry);
480 GNUNET_asprintf (&entry->label,
481 label,
482 strlen (label));
483 GNUNET_memcpy (&entry->private_key,
484 zone_key,
485 sizeof(struct GNUNET_IDENTITY_PrivateKey));
486 entry->rvalue = rvalue;
487 entry->record_count = rd_count;
488 entry->record_data = GNUNET_new_array (rd_count,
489 struct GNUNET_GNSRECORD_Data);
490 for (unsigned int i = 0; i < rd_count; i++)
491 {
492 entry->record_data[i].expiration_time = rd[i].expiration_time;
493 entry->record_data[i].record_type = rd[i].record_type;
494 entry->record_data[i].flags = rd[i].flags;
495 entry->record_data[i].data_size = rd[i].data_size;
496 entry->record_data[i].data = GNUNET_malloc (rd[i].data_size);
497 GNUNET_memcpy ((char *) entry->record_data[i].data,
498 rd[i].data,
499 rd[i].data_size);
500 }
501 return GNUNET_CONTAINER_multihashmap_put (plugin->hm,
502 &hkey,
503 entry,
504 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
505}
506
507
508/**
509 * Lookup records in the datastore for which we are the authority.
510 *
511 * @param cls closure (internal context for the plugin)
512 * @param zone private key of the zone
513 * @param label name of the record in the zone
514 * @param iter function to call with the result
515 * @param iter_cls closure for @a iter
516 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
517 */
518static int
519namestore_flat_lookup_records (void *cls,
520 const struct GNUNET_IDENTITY_PrivateKey *zone,
521 const char *label,
522 GNUNET_NAMESTORE_RecordIterator iter,
523 void *iter_cls)
524{
525 struct Plugin *plugin = cls;
526 struct FlatFileEntry *entry;
527 struct GNUNET_HashCode hkey;
528
529 if (NULL == zone)
530 {
531 GNUNET_break (0);
532 return GNUNET_SYSERR;
533 }
534 hash_pkey_and_label (zone,
535 label,
536 &hkey);
537 entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm,
538 &hkey);
539
540 if (NULL == entry)
541 return GNUNET_NO;
542 if (NULL != iter)
543 iter (iter_cls,
544 1, /* zero is illegal */
545 &entry->private_key,
546 entry->label,
547 entry->record_count,
548 entry->record_data);
549 return GNUNET_YES;
550}
551
552
553/**
554 * Closure for #iterate_zones.
555 */
556struct IterateContext
557{
558 /**
559 * How many more records should we skip before returning results?
560 */
561 uint64_t offset;
562
563 /**
564 * How many more records should we return?
565 */
566 uint64_t limit;
567
568 /**
569 * What is the position of the current entry, counting
570 * starts from 1.
571 */
572 uint64_t pos;
573
574 /**
575 * Target zone.
576 */
577 const struct GNUNET_IDENTITY_PrivateKey *zone;
578
579 /**
580 * Function to call on each record.
581 */
582 GNUNET_NAMESTORE_RecordIterator iter;
583
584 /**
585 * Closure for @e iter.
586 */
587 void *iter_cls;
588};
589
590
591/**
592 * Helper function for #namestore_flat_iterate_records().
593 *
594 * @param cls a `struct IterateContext`
595 * @param key unused
596 * @param value a `struct FlatFileEntry`
597 * @return #GNUNET_YES to continue the iteration
598 */
599static int
600iterate_zones (void *cls,
601 const struct GNUNET_HashCode *key,
602 void *value)
603{
604 struct IterateContext *ic = cls;
605 struct FlatFileEntry *entry = value;
606
607 (void) key;
608 if (0 == ic->limit)
609 return GNUNET_NO;
610 if ((NULL != ic->zone) &&
611 (0 != GNUNET_memcmp (&entry->private_key,
612 ic->zone)))
613 return GNUNET_YES;
614 ic->pos++;
615 if (ic->offset > 0)
616 {
617 ic->offset--;
618 return GNUNET_YES;
619 }
620 ic->iter (ic->iter_cls,
621 ic->pos,
622 (NULL == ic->zone)
623 ? &entry->private_key
624 : ic->zone,
625 entry->label,
626 entry->record_count,
627 entry->record_data);
628 ic->limit--;
629 if (0 == ic->limit)
630 return GNUNET_NO;
631 return GNUNET_YES;
632}
633
634
635/**
636 * Iterate over the results for a particular key and zone in the
637 * datastore. Will return at most one result to the iterator.
638 *
639 * @param cls closure (internal context for the plugin)
640 * @param zone hash of public key of the zone, NULL to iterate over all zones
641 * @param serial serial number to exclude in the list of all matching records
642 * @param limit maximum number of results to return to @a iter
643 * @param iter function to call with the result
644 * @param iter_cls closure for @a iter
645 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
646 */
647static int
648namestore_flat_iterate_records (void *cls,
649 const struct
650 GNUNET_IDENTITY_PrivateKey *zone,
651 uint64_t serial,
652 uint64_t limit,
653 GNUNET_NAMESTORE_RecordIterator iter,
654 void *iter_cls)
655{
656 struct Plugin *plugin = cls;
657 struct IterateContext ic;
658
659 ic.offset = serial;
660 ic.pos = 0;
661 ic.limit = limit;
662 ic.iter = iter;
663 ic.iter_cls = iter_cls;
664 ic.zone = zone;
665 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
666 &iterate_zones,
667 &ic);
668 return (0 == ic.limit) ? GNUNET_OK : GNUNET_NO;
669}
670
671
672/**
673 * Closure for #zone_to_name.
674 */
675struct ZoneToNameContext
676{
677 const struct GNUNET_IDENTITY_PrivateKey *zone;
678 const struct GNUNET_IDENTITY_PublicKey *value_zone;
679 GNUNET_NAMESTORE_RecordIterator iter;
680 void *iter_cls;
681
682 int result_found;
683};
684
685
686static int
687zone_to_name (void *cls,
688 const struct GNUNET_HashCode *key,
689 void *value)
690{
691 struct ZoneToNameContext *ztn = cls;
692 struct FlatFileEntry *entry = value;
693
694 (void) key;
695 if (0 != GNUNET_memcmp (&entry->private_key,
696 ztn->zone))
697 return GNUNET_YES;
698
699 for (unsigned int i = 0; i < entry->record_count; i++)
700 {
701 if (GNUNET_NO ==
702 GNUNET_GNSRECORD_is_zonekey_type (entry->record_data[i].record_type))
703 continue;
704 if (ztn->value_zone->type != entry->record_data[i].record_type)
705 continue;
706 if (0 == memcmp (ztn->value_zone,
707 entry->record_data[i].data,
708 entry->record_data[i].data_size))
709 {
710 ztn->iter (ztn->iter_cls,
711 i + 1, /* zero is illegal! */
712 &entry->private_key,
713 entry->label,
714 entry->record_count,
715 entry->record_data);
716 ztn->result_found = GNUNET_YES;
717 }
718 }
719 return GNUNET_YES;
720}
721
722
723/**
724 * Look for an existing PKEY delegation record for a given public key.
725 * Returns at most one result to the iterator.
726 *
727 * @param cls closure (internal context for the plugin)
728 * @param zone private key of the zone to look up in, never NULL
729 * @param value_zone public key of the target zone (value), never NULL
730 * @param iter function to call with the result
731 * @param iter_cls closure for @a iter
732 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
733 */
734static int
735namestore_flat_zone_to_name (void *cls,
736 const struct GNUNET_IDENTITY_PrivateKey *zone,
737 const struct
738 GNUNET_IDENTITY_PublicKey *value_zone,
739 GNUNET_NAMESTORE_RecordIterator iter,
740 void *iter_cls)
741{
742 struct Plugin *plugin = cls;
743 struct ZoneToNameContext ztn = {
744 .iter = iter,
745 .iter_cls = iter_cls,
746 .zone = zone,
747 .value_zone = value_zone,
748 .result_found = GNUNET_NO
749 };
750
751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
752 "Performing reverse lookup for `%s'\n",
753 GNUNET_GNSRECORD_z2s (value_zone));
754 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
755 &zone_to_name,
756 &ztn);
757 return ztn.result_found;
758}
759
760
761/**
762 * Entry point for the plugin.
763 *
764 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
765 * @return NULL on error, otherwise the plugin context
766 */
767void *
768libgnunet_plugin_namestore_flat_init (void *cls)
769{
770 static struct Plugin plugin;
771 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
772 struct GNUNET_NAMESTORE_PluginFunctions *api;
773
774 if (NULL != plugin.cfg)
775 return NULL; /* can only initialize once! */
776 memset (&plugin,
777 0,
778 sizeof(struct Plugin));
779 plugin.cfg = cfg;
780 if (GNUNET_OK != database_setup (&plugin))
781 {
782 database_shutdown (&plugin);
783 return NULL;
784 }
785 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
786 api->cls = &plugin;
787 api->store_records = &namestore_flat_store_records;
788 api->iterate_records = &namestore_flat_iterate_records;
789 api->zone_to_name = &namestore_flat_zone_to_name;
790 api->lookup_records = &namestore_flat_lookup_records;
791 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
792 _ ("Flat file database running\n"));
793 return api;
794}
795
796
797/**
798 * Exit point from the plugin.
799 *
800 * @param cls the plugin context (as returned by "init")
801 * @return always NULL
802 */
803void *
804libgnunet_plugin_namestore_flat_done (void *cls)
805{
806 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
807 struct Plugin *plugin = api->cls;
808
809 database_shutdown (plugin);
810 plugin->cfg = NULL;
811 GNUNET_free (api);
812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
813 "Flat file plugin is finished\n");
814 return NULL;
815}
816
817
818/* end of plugin_namestore_flat.c */
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
index bdbaf96b3..3b1b7ac21 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_postgres.c
@@ -553,6 +553,68 @@ namestore_postgres_zone_to_name (void *cls,
553 return GNUNET_OK; 553 return GNUNET_OK;
554} 554}
555 555
556/**
557 * Begin a transaction for a client.
558 *
559 * @param cls closure (internal context for the plugin)
560 * @param emsg error message set of return code is #GNUNET_SYSERR
561 * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started.
562 */
563static enum GNUNET_GenericReturnValue
564namestore_postgres_transaction_begin (void *cls,
565 char **emsg)
566{
567 struct Plugin *plugin = cls;
568 struct GNUNET_PQ_ExecuteStatement es[] = {
569 GNUNET_PQ_make_execute ("BEGIN;"),
570 GNUNET_PQ_EXECUTE_STATEMENT_END
571 };
572
573 return GNUNET_PQ_exec_statements (plugin->dbh, es);
574}
575
576/**
577 * Commit a transaction for a client.
578 * This releases the lock on the database.
579 *
580 * @param cls closure (internal context for the plugin)
581 * @param emsg error message set of return code is #GNUNET_SYSERR
582 * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started.
583 */
584static enum GNUNET_GenericReturnValue
585namestore_postgres_transaction_rollback (void *cls,
586 char **emsg)
587{
588 struct Plugin *plugin = cls;
589 struct GNUNET_PQ_ExecuteStatement es[] = {
590 GNUNET_PQ_make_execute ("ROLLBACK;"),
591 GNUNET_PQ_EXECUTE_STATEMENT_END
592 };
593
594 return GNUNET_PQ_exec_statements (plugin->dbh, es);
595}
596
597/**
598 * Roll back a transaction for a client.
599 * This releases the lock on the database.
600 *
601 * @param cls closure (internal context for the plugin)
602 * @param emsg error message set of return code is #GNUNET_SYSERR
603 * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started.
604 */
605static enum GNUNET_GenericReturnValue
606namestore_postgres_transaction_commit (void *cls,
607 char **emsg)
608{
609 struct Plugin *plugin = cls;
610 struct GNUNET_PQ_ExecuteStatement es[] = {
611 GNUNET_PQ_make_execute ("COMMIT;"),
612 GNUNET_PQ_EXECUTE_STATEMENT_END
613 };
614
615 return GNUNET_PQ_exec_statements (plugin->dbh, es);
616}
617
556 618
557/** 619/**
558 * Shutdown database connection and associate data 620 * Shutdown database connection and associate data
@@ -577,25 +639,27 @@ database_shutdown (struct Plugin *plugin)
577void * 639void *
578libgnunet_plugin_namestore_postgres_init (void *cls) 640libgnunet_plugin_namestore_postgres_init (void *cls)
579{ 641{
580 static struct Plugin plugin; 642 struct Plugin *plugin;
581 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 643 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
582 struct GNUNET_NAMESTORE_PluginFunctions *api; 644 struct GNUNET_NAMESTORE_PluginFunctions *api;
583 645
584 if (NULL != plugin.cfg) 646 plugin = GNUNET_new (struct Plugin);
585 return NULL; /* can only initialize once! */ 647 plugin->cfg = cfg;
586 memset (&plugin, 0, sizeof(struct Plugin)); 648 if (GNUNET_OK != database_setup (plugin))
587 plugin.cfg = cfg;
588 if (GNUNET_OK != database_setup (&plugin))
589 { 649 {
590 database_shutdown (&plugin); 650 database_shutdown (plugin);
651 GNUNET_free (plugin);
591 return NULL; 652 return NULL;
592 } 653 }
593 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); 654 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
594 api->cls = &plugin; 655 api->cls = plugin;
595 api->store_records = &namestore_postgres_store_records; 656 api->store_records = &namestore_postgres_store_records;
596 api->iterate_records = &namestore_postgres_iterate_records; 657 api->iterate_records = &namestore_postgres_iterate_records;
597 api->zone_to_name = &namestore_postgres_zone_to_name; 658 api->zone_to_name = &namestore_postgres_zone_to_name;
598 api->lookup_records = &namestore_postgres_lookup_records; 659 api->lookup_records = &namestore_postgres_lookup_records;
660 api->transaction_begin = &namestore_postgres_transaction_begin;
661 api->transaction_commit = &namestore_postgres_transaction_commit;
662 api->transaction_rollback = &namestore_postgres_transaction_rollback;
599 LOG (GNUNET_ERROR_TYPE_INFO, 663 LOG (GNUNET_ERROR_TYPE_INFO,
600 "Postgres namestore plugin running\n"); 664 "Postgres namestore plugin running\n");
601 return api; 665 return api;
@@ -616,6 +680,7 @@ libgnunet_plugin_namestore_postgres_done (void *cls)
616 680
617 database_shutdown (plugin); 681 database_shutdown (plugin);
618 plugin->cfg = NULL; 682 plugin->cfg = NULL;
683 GNUNET_free (plugin);
619 GNUNET_free (api); 684 GNUNET_free (api);
620 LOG (GNUNET_ERROR_TYPE_DEBUG, 685 LOG (GNUNET_ERROR_TYPE_DEBUG,
621 "Postgres namestore plugin is finished\n"); 686 "Postgres namestore plugin is finished\n");
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c
index 0b3aac84f..d434abd94 100644
--- a/src/namestore/plugin_namestore_sqlite.c
+++ b/src/namestore/plugin_namestore_sqlite.c
@@ -129,7 +129,7 @@ database_setup (struct Plugin *plugin)
129 GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"), 129 GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
130 GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"), 130 GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
131 GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""), 131 GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
132 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=EXCLUSIVE"), 132 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"),
133 GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"), 133 GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
134 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"), 134 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
135 GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records (" 135 GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
@@ -201,17 +201,16 @@ database_setup (struct Plugin *plugin)
201 return GNUNET_SYSERR; 201 return GNUNET_SYSERR;
202 } 202 }
203 } 203 }
204 /* sqlite_filename should be UTF-8-encoded. If it isn't, it's a bug */
205 plugin->fn = sqlite_filename;
206 204
207 /* Open database and precompile statements */ 205 /* Open database and precompile statements */
208 if (SQLITE_OK != 206 if (SQLITE_OK !=
209 sqlite3_open (plugin->fn, 207 sqlite3_open (sqlite_filename,
210 &plugin->dbh)) 208 &plugin->dbh))
211 { 209 {
212 LOG (GNUNET_ERROR_TYPE_ERROR, 210 LOG (GNUNET_ERROR_TYPE_ERROR,
213 _ ("Unable to initialize SQLite: %s.\n"), 211 _ ("Unable to initialize SQLite: %s.\n"),
214 sqlite3_errmsg (plugin->dbh)); 212 sqlite3_errmsg (plugin->dbh));
213 GNUNET_free (sqlite_filename);
215 return GNUNET_SYSERR; 214 return GNUNET_SYSERR;
216 } 215 }
217 GNUNET_break (SQLITE_OK == 216 GNUNET_break (SQLITE_OK ==
@@ -224,7 +223,8 @@ database_setup (struct Plugin *plugin)
224 GNUNET_break (0); 223 GNUNET_break (0);
225 LOG (GNUNET_ERROR_TYPE_ERROR, 224 LOG (GNUNET_ERROR_TYPE_ERROR,
226 _ ("Failed to setup database at `%s'\n"), 225 _ ("Failed to setup database at `%s'\n"),
227 plugin->fn); 226 sqlite_filename);
227 GNUNET_free (sqlite_filename);
228 return GNUNET_SYSERR; 228 return GNUNET_SYSERR;
229 } 229 }
230 230
@@ -235,7 +235,8 @@ database_setup (struct Plugin *plugin)
235 GNUNET_break (0); 235 GNUNET_break (0);
236 LOG (GNUNET_ERROR_TYPE_ERROR, 236 LOG (GNUNET_ERROR_TYPE_ERROR,
237 _ ("Failed to setup database at `%s'\n"), 237 _ ("Failed to setup database at `%s'\n"),
238 plugin->fn); 238 sqlite_filename);
239 GNUNET_free (sqlite_filename);
239 return GNUNET_SYSERR; 240 return GNUNET_SYSERR;
240 } 241 }
241 return GNUNET_OK; 242 return GNUNET_OK;
@@ -296,7 +297,6 @@ database_shutdown (struct Plugin *plugin)
296 GNUNET_ERROR_TYPE_ERROR, 297 GNUNET_ERROR_TYPE_ERROR,
297 "sqlite3_close"); 298 "sqlite3_close");
298 299
299 GNUNET_free (plugin->fn);
300} 300}
301 301
302 302
@@ -331,8 +331,8 @@ namestore_sqlite_store_records (void *cls,
331 for (unsigned int i = 0; i < rd_count; i++) 331 for (unsigned int i = 0; i < rd_count; i++)
332 { 332 {
333 LOG (GNUNET_ERROR_TYPE_DEBUG, 333 LOG (GNUNET_ERROR_TYPE_DEBUG,
334 "Checking if `%d' is zonekey type\n", 334 "Checking if `%d' is zonekey type\n",
335 rd[i].record_type); 335 rd[i].record_type);
336 336
337 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) 337 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
338 { 338 {
@@ -342,8 +342,8 @@ namestore_sqlite_store_records (void *cls,
342 rd[i].record_type, 342 rd[i].record_type,
343 &pkey)); 343 &pkey));
344 LOG (GNUNET_ERROR_TYPE_DEBUG, 344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "Storing delegation zone record value `%s'\n", 345 "Storing delegation zone record value `%s'\n",
346 GNUNET_GNSRECORD_z2s (&pkey)); 346 GNUNET_GNSRECORD_z2s (&pkey));
347 347
348 break; 348 break;
349 } 349 }
@@ -740,6 +740,58 @@ namestore_sqlite_zone_to_name (void *cls,
740 iter_cls); 740 iter_cls);
741} 741}
742 742
743/**
744 * Begin a transaction for a client.
745 * This locks the database. SQLite is unable to discern between different
746 * rows with a specific zone key but the API looks like this anyway.
747 * https://www.sqlite.org/lang_transaction.html
748 *
749 * @param cls closure (internal context for the plugin)
750 * @param emsg error message set of return code is #GNUNET_SYSERR
751 * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started.
752 */
753static enum GNUNET_GenericReturnValue
754namestore_sqlite_transaction_begin (void *cls,
755 char **emsg)
756{
757 struct Plugin *plugin = cls;
758 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "BEGIN TRANSACTION;", NULL,
759 NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES;
760}
761
762/**
763 * Commit a transaction for a client.
764 * This releases the lock on the database.
765 *
766 * @param cls closure (internal context for the plugin)
767 * @param emsg error message set of return code is #GNUNET_SYSERR
768 * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started.
769 */
770static enum GNUNET_GenericReturnValue
771namestore_sqlite_transaction_rollback (void *cls,
772 char **emsg)
773{
774 struct Plugin *plugin = cls;
775 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "ROLLBACK;", NULL,
776 NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES;
777}
778
779/**
780 * Roll back a transaction for a client.
781 * This releases the lock on the database.
782 *
783 * @param cls closure (internal context for the plugin)
784 * @param emsg error message set of return code is #GNUNET_SYSERR
785 * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started.
786 */
787static enum GNUNET_GenericReturnValue
788namestore_sqlite_transaction_commit (void *cls,
789 char **emsg)
790{
791 struct Plugin *plugin = cls;
792 return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "END TRANSACTION;", NULL,
793 NULL, emsg)) ? GNUNET_SYSERR : GNUNET_YES;
794}
743 795
744/** 796/**
745 * Entry point for the plugin. 797 * Entry point for the plugin.
@@ -750,27 +802,27 @@ namestore_sqlite_zone_to_name (void *cls,
750void * 802void *
751libgnunet_plugin_namestore_sqlite_init (void *cls) 803libgnunet_plugin_namestore_sqlite_init (void *cls)
752{ 804{
753 static struct Plugin plugin; 805 struct Plugin *plugin;
754 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 806 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
755 struct GNUNET_NAMESTORE_PluginFunctions *api; 807 struct GNUNET_NAMESTORE_PluginFunctions *api;
756 808
757 if (NULL != plugin.cfg) 809 plugin = GNUNET_new (struct Plugin);
758 return NULL; /* can only initialize once! */ 810 plugin->cfg = cfg;
759 memset (&plugin, 811 if (GNUNET_OK != database_setup (plugin))
760 0,
761 sizeof(struct Plugin));
762 plugin.cfg = cfg;
763 if (GNUNET_OK != database_setup (&plugin))
764 { 812 {
765 database_shutdown (&plugin); 813 database_shutdown (plugin);
814 GNUNET_free (plugin);
766 return NULL; 815 return NULL;
767 } 816 }
768 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); 817 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
769 api->cls = &plugin; 818 api->cls = plugin;
770 api->store_records = &namestore_sqlite_store_records; 819 api->store_records = &namestore_sqlite_store_records;
771 api->iterate_records = &namestore_sqlite_iterate_records; 820 api->iterate_records = &namestore_sqlite_iterate_records;
772 api->zone_to_name = &namestore_sqlite_zone_to_name; 821 api->zone_to_name = &namestore_sqlite_zone_to_name;
773 api->lookup_records = &namestore_sqlite_lookup_records; 822 api->lookup_records = &namestore_sqlite_lookup_records;
823 api->transaction_begin = &namestore_sqlite_transaction_begin;
824 api->transaction_commit = &namestore_sqlite_transaction_commit;
825 api->transaction_rollback = &namestore_sqlite_transaction_rollback;
774 LOG (GNUNET_ERROR_TYPE_INFO, 826 LOG (GNUNET_ERROR_TYPE_INFO,
775 _ ("Sqlite database running\n")); 827 _ ("Sqlite database running\n"));
776 return api; 828 return api;
@@ -791,6 +843,7 @@ libgnunet_plugin_namestore_sqlite_done (void *cls)
791 843
792 database_shutdown (plugin); 844 database_shutdown (plugin);
793 plugin->cfg = NULL; 845 plugin->cfg = NULL;
846 GNUNET_free (plugin);
794 GNUNET_free (api); 847 GNUNET_free (api);
795 LOG (GNUNET_ERROR_TYPE_DEBUG, 848 LOG (GNUNET_ERROR_TYPE_DEBUG,
796 "sqlite plugin is finished\n"); 849 "sqlite plugin is finished\n");
diff --git a/src/namestore/test_namestore_api_flat.conf b/src/namestore/test_namestore_api_flat.conf
deleted file mode 100644
index 8460d143c..000000000
--- a/src/namestore/test_namestore_api_flat.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1@INLINE@ test_namestore_api.conf
2
3[namestore]
4DATABASE = flat
5
6[namestore-heap]
7FILENAME = $GNUNET_TEST_HOME/namestore/flat.db
diff --git a/src/namestore/test_namestore_api_monitoring_existing.c b/src/namestore/test_namestore_api_monitoring_existing.c
index 366f5739f..95907f34a 100644
--- a/src/namestore/test_namestore_api_monitoring_existing.c
+++ b/src/namestore/test_namestore_api_monitoring_existing.c
@@ -250,25 +250,6 @@ put_cont (void *cls,
250 250
251 if (3 == c) 251 if (3 == c)
252 { 252 {
253 /* Start monitoring */
254 zm = GNUNET_NAMESTORE_zone_monitor_start (cfg,
255 &privkey,
256 GNUNET_YES,
257 &fail_cb,
258 NULL,
259 &zone_proc,
260 NULL,
261 &sync_cb,
262 NULL);
263 if (NULL == zm)
264 {
265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
266 "Failed to create zone monitor\n");
267 GNUNET_break (0);
268 res = 1;
269 GNUNET_SCHEDULER_shutdown ();
270 return;
271 }
272 } 253 }
273} 254}
274 255
@@ -324,6 +305,25 @@ run (void *cls,
324 NULL); 305 NULL);
325 return; 306 return;
326 } 307 }
308 /* Start monitoring */
309 zm = GNUNET_NAMESTORE_zone_monitor_start (cfg,
310 &privkey,
311 GNUNET_YES,
312 &fail_cb,
313 NULL,
314 &zone_proc,
315 NULL,
316 &sync_cb,
317 NULL);
318 if (NULL == zm)
319 {
320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
321 "Failed to create zone monitor\n");
322 GNUNET_break (0);
323 res = 1;
324 GNUNET_SCHEDULER_shutdown ();
325 return;
326 }
327 327
328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
329 "Created record 3\n"); 329 "Created record 3\n");
diff --git a/src/namestore/test_plugin_namestore_flat.conf b/src/namestore/test_plugin_namestore_flat.conf
deleted file mode 100644
index 5c632f0d1..000000000
--- a/src/namestore/test_plugin_namestore_flat.conf
+++ /dev/null
@@ -1,2 +0,0 @@
1[namestore-flat]
2FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-flat/flatdb