diff options
Diffstat (limited to 'src/namestore')
27 files changed, 2610 insertions, 1629 deletions
diff --git a/src/namestore/.gitignore b/src/namestore/.gitignore index f159cdaff..907361276 100644 --- a/src/namestore/.gitignore +++ b/src/namestore/.gitignore | |||
@@ -1,5 +1,6 @@ | |||
1 | gnunet-service-namestore | 1 | gnunet-service-namestore |
2 | gnunet-namestore | 2 | gnunet-namestore |
3 | gnunet-namestore-dbtool | ||
3 | gnunet-namestore-fcfsd | 4 | gnunet-namestore-fcfsd |
4 | test_namestore_api_lookup_nick.nc | 5 | test_namestore_api_lookup_nick.nc |
5 | test_namestore_api_lookup_private.nc | 6 | test_namestore_api_lookup_private.nc |
@@ -18,71 +19,39 @@ test_namestore_api_zone_iteration_specific_zone.nc | |||
18 | test_namestore_api_zone_iteration_stop.nc | 19 | test_namestore_api_zone_iteration_stop.nc |
19 | test_plugin_namestore_postgres | 20 | test_plugin_namestore_postgres |
20 | test_plugin_namestore_sqlite | 21 | test_plugin_namestore_sqlite |
21 | test_plugin_namestore_flat | ||
22 | gnunet-zoneimport | 22 | gnunet-zoneimport |
23 | test_namestore_api_lookup_nick_flat | ||
24 | test_namestore_api_lookup_nick_postgres | 23 | test_namestore_api_lookup_nick_postgres |
25 | test_namestore_api_lookup_nick_sqlite | 24 | test_namestore_api_lookup_nick_sqlite |
26 | test_namestore_api_lookup_private_flat | ||
27 | test_namestore_api_lookup_private_postgres | 25 | test_namestore_api_lookup_private_postgres |
28 | test_namestore_api_lookup_private_sqlite | 26 | test_namestore_api_lookup_private_sqlite |
29 | test_namestore_api_lookup_public_flat | ||
30 | test_namestore_api_lookup_public_postgres | 27 | test_namestore_api_lookup_public_postgres |
31 | test_namestore_api_lookup_public_sqlite | 28 | test_namestore_api_lookup_public_sqlite |
32 | test_namestore_api_lookup_shadow_filter_flat | ||
33 | test_namestore_api_lookup_shadow_filter_postgres | 29 | test_namestore_api_lookup_shadow_filter_postgres |
34 | test_namestore_api_lookup_shadow_filter_sqlite | 30 | test_namestore_api_lookup_shadow_filter_sqlite |
35 | test_namestore_api_lookup_shadow_flat | ||
36 | test_namestore_api_lookup_shadow_postgres | 31 | test_namestore_api_lookup_shadow_postgres |
37 | test_namestore_api_lookup_shadow_sqlite | 32 | test_namestore_api_lookup_shadow_sqlite |
38 | test_namestore_api_monitoring_existing_flat | ||
39 | test_namestore_api_monitoring_existing_postgres | 33 | test_namestore_api_monitoring_existing_postgres |
40 | test_namestore_api_monitoring_existing_sqlite | 34 | test_namestore_api_monitoring_existing_sqlite |
41 | test_namestore_api_monitoring_flat | ||
42 | test_namestore_api_monitoring_postgres | 35 | test_namestore_api_monitoring_postgres |
43 | test_namestore_api_monitoring_sqlite | 36 | test_namestore_api_monitoring_sqlite |
44 | test_namestore_api_remove_flat | ||
45 | test_namestore_api_remove_not_existing_record_flat | ||
46 | test_namestore_api_remove_not_existing_record_postgres | 37 | test_namestore_api_remove_not_existing_record_postgres |
47 | test_namestore_api_remove_not_existing_record_sqlite | 38 | test_namestore_api_remove_not_existing_record_sqlite |
48 | test_namestore_api_remove_postgres | 39 | test_namestore_api_remove_postgres |
49 | test_namestore_api_remove_sqlite | 40 | test_namestore_api_remove_sqlite |
50 | test_namestore_api_store_flat | ||
51 | test_namestore_api_store_postgres | 41 | test_namestore_api_store_postgres |
52 | test_namestore_api_store_sqlite | 42 | test_namestore_api_store_sqlite |
53 | test_namestore_api_store_update_flat | ||
54 | test_namestore_api_store_update_postgres | 43 | test_namestore_api_store_update_postgres |
55 | test_namestore_api_store_update_sqlite | 44 | test_namestore_api_store_update_sqlite |
56 | test_namestore_api_zone_iteration_flat | ||
57 | test_namestore_api_zone_iteration_nick_flat | ||
58 | test_namestore_api_zone_iteration_nick_postgres | 45 | test_namestore_api_zone_iteration_nick_postgres |
59 | test_namestore_api_zone_iteration_nick_sqlite | 46 | test_namestore_api_zone_iteration_nick_sqlite |
60 | test_namestore_api_zone_iteration_postgres | 47 | test_namestore_api_zone_iteration_postgres |
61 | test_namestore_api_zone_iteration_specific_zone_flat | ||
62 | test_namestore_api_zone_iteration_specific_zone_postgres | 48 | test_namestore_api_zone_iteration_specific_zone_postgres |
63 | test_namestore_api_zone_iteration_specific_zone_sqlite | 49 | test_namestore_api_zone_iteration_specific_zone_sqlite |
64 | test_namestore_api_zone_iteration_sqlite | 50 | test_namestore_api_zone_iteration_sqlite |
65 | test_namestore_api_zone_iteration_stop_flat | ||
66 | test_namestore_api_zone_iteration_stop_postgres | 51 | test_namestore_api_zone_iteration_stop_postgres |
67 | test_namestore_api_zone_iteration_stop_sqlite | 52 | test_namestore_api_zone_iteration_stop_sqlite |
68 | test_namestore_api_zone_to_name_flat | ||
69 | test_namestore_api_zone_to_name_postgres | 53 | test_namestore_api_zone_to_name_postgres |
70 | test_namestore_api_zone_to_name_sqlite | 54 | test_namestore_api_zone_to_name_sqlite |
71 | test_namestore_api_lookup_nick_flat | 55 | test_namestore_api_tx_rollback_postgres |
72 | test_namestore_api_lookup_private_flat | 56 | test_namestore_api_tx_rollback_sqlite |
73 | test_namestore_api_lookup_public_flat | 57 | test_namestore_api_edit_records_postgres |
74 | test_namestore_api_lookup_shadow_filter_flat | ||
75 | test_namestore_api_lookup_shadow_flat | ||
76 | test_namestore_api_monitoring_existing_flat | ||
77 | test_namestore_api_monitoring_flat | ||
78 | test_namestore_api_remove_flat | ||
79 | test_namestore_api_remove_not_existing_record_flat | ||
80 | test_namestore_api_store_flat | ||
81 | test_namestore_api_store_update_flat | ||
82 | test_namestore_api_zone_iteration_flat | ||
83 | test_namestore_api_zone_iteration_nick_flat | ||
84 | test_namestore_api_zone_iteration_specific_zone_flat | ||
85 | test_namestore_api_zone_iteration_stop_flat | ||
86 | test_namestore_api_zone_to_name_flat | ||
87 | test_plugin_namestore_flat | ||
88 | perf_namestore_api_zone_iteration_flat | ||
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 51708dd67..d5e110206 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am | |||
@@ -15,25 +15,6 @@ if USE_COVERAGE | |||
15 | XLIBS = -lgcov | 15 | XLIBS = -lgcov |
16 | endif | 16 | endif |
17 | 17 | ||
18 | HEAP_PLUGIN = libgnunet_plugin_namestore_flat.la | ||
19 | HEAP_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 | 18 | ||
38 | if HAVE_SQLITE | 19 | if HAVE_SQLITE |
39 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la | 20 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la |
@@ -54,9 +35,11 @@ SQLITE_TESTS = test_plugin_namestore_sqlite \ | |||
54 | test_namestore_api_zone_iteration_stop_sqlite \ | 35 | test_namestore_api_zone_iteration_stop_sqlite \ |
55 | test_namestore_api_monitoring_existing_sqlite \ | 36 | test_namestore_api_monitoring_existing_sqlite \ |
56 | test_namestore_api_zone_to_name_sqlite \ | 37 | test_namestore_api_zone_to_name_sqlite \ |
57 | perf_namestore_api_zone_iteration_sqlite | 38 | perf_namestore_api_zone_iteration_sqlite \ |
39 | test_namestore_api_tx_rollback_sqlite | ||
58 | endif | 40 | endif |
59 | 41 | ||
42 | |||
60 | if HAVE_POSTGRESQL | 43 | if HAVE_POSTGRESQL |
61 | POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la | 44 | POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la |
62 | POSTGRES_TESTS = test_plugin_namestore_postgres \ | 45 | POSTGRES_TESTS = test_plugin_namestore_postgres \ |
@@ -76,14 +59,17 @@ POSTGRES_TESTS = test_plugin_namestore_postgres \ | |||
76 | test_namestore_api_zone_iteration_stop_postgres \ | 59 | test_namestore_api_zone_iteration_stop_postgres \ |
77 | test_namestore_api_monitoring_existing_postgres \ | 60 | test_namestore_api_monitoring_existing_postgres \ |
78 | test_namestore_api_zone_to_name_postgres \ | 61 | test_namestore_api_zone_to_name_postgres \ |
79 | perf_namestore_api_zone_iteration_postgres | 62 | perf_namestore_api_zone_iteration_postgres \ |
63 | test_namestore_api_tx_rollback_postgres | ||
64 | if HAVE_EXPERIMENTAL | ||
65 | POSTGRES_TESTS += test_namestore_api_edit_records_postgres | ||
66 | endif | ||
80 | endif | 67 | endif |
81 | 68 | ||
82 | if HAVE_SQLITE | 69 | if HAVE_SQLITE |
83 | check_PROGRAMS = \ | 70 | check_PROGRAMS = \ |
84 | $(SQLITE_TESTS) \ | 71 | $(SQLITE_TESTS) \ |
85 | $(POSTGRES_TESTS) \ | 72 | $(POSTGRES_TESTS) |
86 | $(HEAP_TESTS) | ||
87 | endif | 73 | endif |
88 | 74 | ||
89 | if ENABLE_TEST_RUN | 75 | if ENABLE_TEST_RUN |
@@ -104,6 +90,7 @@ libexec_PROGRAMS = \ | |||
104 | 90 | ||
105 | bin_PROGRAMS = \ | 91 | bin_PROGRAMS = \ |
106 | gnunet-namestore \ | 92 | gnunet-namestore \ |
93 | gnunet-namestore-dbtool \ | ||
107 | gnunet-zoneimport | 94 | gnunet-zoneimport |
108 | 95 | ||
109 | libexec_PROGRAMS += \ | 96 | libexec_PROGRAMS += \ |
@@ -113,7 +100,6 @@ libexec_PROGRAMS += \ | |||
113 | plugin_LTLIBRARIES = \ | 100 | plugin_LTLIBRARIES = \ |
114 | $(SQLITE_PLUGIN) \ | 101 | $(SQLITE_PLUGIN) \ |
115 | $(POSTGRES_PLUGIN) \ | 102 | $(POSTGRES_PLUGIN) \ |
116 | $(HEAP_PLUGIN) \ | ||
117 | $(REST_PLUGIN) | 103 | $(REST_PLUGIN) |
118 | 104 | ||
119 | 105 | ||
@@ -168,6 +154,14 @@ gnunet_namestore_LDADD = \ | |||
168 | libgnunetnamestore.la \ | 154 | libgnunetnamestore.la \ |
169 | $(GN_LIBINTL) | 155 | $(GN_LIBINTL) |
170 | 156 | ||
157 | gnunet_namestore_dbtool_SOURCES = \ | ||
158 | gnunet-namestore-dbtool.c | ||
159 | gnunet_namestore_dbtool_LDADD = \ | ||
160 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
161 | libgnunetnamestore.la \ | ||
162 | $(GN_LIBINTL) | ||
163 | |||
164 | |||
171 | 165 | ||
172 | gnunet_namestore_fcfsd_SOURCES = \ | 166 | gnunet_namestore_fcfsd_SOURCES = \ |
173 | gnunet-namestore-fcfsd.c | 167 | gnunet-namestore-fcfsd.c |
@@ -195,18 +189,6 @@ gnunet_service_namestore_LDADD = \ | |||
195 | 189 | ||
196 | 190 | ||
197 | 191 | ||
198 | libgnunet_plugin_namestore_flat_la_SOURCES = \ | ||
199 | plugin_namestore_flat.c | ||
200 | libgnunet_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) | ||
206 | libgnunet_plugin_namestore_flat_la_LDFLAGS = \ | ||
207 | $(GN_PLUGIN_LDFLAGS) | ||
208 | |||
209 | |||
210 | libgnunet_plugin_namestore_sqlite_la_SOURCES = \ | 192 | libgnunet_plugin_namestore_sqlite_la_SOURCES = \ |
211 | plugin_namestore_sqlite.c | 193 | plugin_namestore_sqlite.c |
212 | libgnunet_plugin_namestore_sqlite_la_LIBADD = \ | 194 | libgnunet_plugin_namestore_sqlite_la_LIBADD = \ |
@@ -231,15 +213,6 @@ libgnunet_plugin_namestore_postgres_la_LIBADD = \ | |||
231 | libgnunet_plugin_namestore_postgres_la_LDFLAGS = \ | 213 | libgnunet_plugin_namestore_postgres_la_LDFLAGS = \ |
232 | $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS) | 214 | $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS) |
233 | 215 | ||
234 | test_namestore_api_store_flat_SOURCES = \ | ||
235 | test_namestore_api_store.c | ||
236 | test_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 | |||
243 | test_namestore_api_store_sqlite_SOURCES = \ | 216 | test_namestore_api_store_sqlite_SOURCES = \ |
244 | test_namestore_api_store.c | 217 | test_namestore_api_store.c |
245 | test_namestore_api_store_sqlite_LDADD = \ | 218 | test_namestore_api_store_sqlite_LDADD = \ |
@@ -258,16 +231,6 @@ test_namestore_api_store_postgres_LDADD = \ | |||
258 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 231 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
259 | libgnunetnamestore.la | 232 | libgnunetnamestore.la |
260 | 233 | ||
261 | test_namestore_api_store_update_flat_SOURCES = \ | ||
262 | test_namestore_api_store_update.c | ||
263 | test_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 | |||
271 | test_namestore_api_store_update_sqlite_SOURCES = \ | 234 | test_namestore_api_store_update_sqlite_SOURCES = \ |
272 | test_namestore_api_store_update.c | 235 | test_namestore_api_store_update.c |
273 | test_namestore_api_store_update_sqlite_LDADD = \ | 236 | test_namestore_api_store_update_sqlite_LDADD = \ |
@@ -288,16 +251,6 @@ test_namestore_api_store_update_postgres_LDADD = \ | |||
288 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | 251 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ |
289 | libgnunetnamestore.la | 252 | libgnunetnamestore.la |
290 | 253 | ||
291 | test_namestore_api_lookup_public_flat_SOURCES = \ | ||
292 | test_namestore_api_lookup_public.c | ||
293 | test_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 | |||
301 | test_namestore_api_lookup_public_sqlite_SOURCES = \ | 254 | test_namestore_api_lookup_public_sqlite_SOURCES = \ |
302 | test_namestore_api_lookup_public.c | 255 | test_namestore_api_lookup_public.c |
303 | test_namestore_api_lookup_public_sqlite_LDADD = \ | 256 | test_namestore_api_lookup_public_sqlite_LDADD = \ |
@@ -338,26 +291,6 @@ test_namestore_api_lookup_nick_postgres_LDADD = \ | |||
338 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | 291 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ |
339 | libgnunetnamestore.la | 292 | libgnunetnamestore.la |
340 | 293 | ||
341 | test_namestore_api_lookup_nick_flat_SOURCES = \ | ||
342 | test_namestore_api_lookup_nick.c | ||
343 | test_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 | |||
351 | test_namestore_api_lookup_private_flat_SOURCES = \ | ||
352 | test_namestore_api_lookup_private.c | ||
353 | test_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 | |||
361 | test_namestore_api_lookup_private_sqlite_SOURCES = \ | 294 | test_namestore_api_lookup_private_sqlite_SOURCES = \ |
362 | test_namestore_api_lookup_private.c | 295 | test_namestore_api_lookup_private.c |
363 | test_namestore_api_lookup_private_sqlite_LDADD = \ | 296 | test_namestore_api_lookup_private_sqlite_LDADD = \ |
@@ -378,16 +311,6 @@ test_namestore_api_lookup_private_postgres_LDADD = \ | |||
378 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | 311 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ |
379 | libgnunetnamestore.la | 312 | libgnunetnamestore.la |
380 | 313 | ||
381 | test_namestore_api_lookup_shadow_flat_SOURCES = \ | ||
382 | test_namestore_api_lookup_shadow.c | ||
383 | test_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 | |||
391 | test_namestore_api_lookup_shadow_sqlite_SOURCES = \ | 314 | test_namestore_api_lookup_shadow_sqlite_SOURCES = \ |
392 | test_namestore_api_lookup_shadow.c | 315 | test_namestore_api_lookup_shadow.c |
393 | test_namestore_api_lookup_shadow_sqlite_LDADD = \ | 316 | test_namestore_api_lookup_shadow_sqlite_LDADD = \ |
@@ -408,16 +331,6 @@ test_namestore_api_lookup_shadow_postgres_LDADD = \ | |||
408 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | 331 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ |
409 | libgnunetnamestore.la | 332 | libgnunetnamestore.la |
410 | 333 | ||
411 | test_namestore_api_lookup_shadow_filter_flat_SOURCES = \ | ||
412 | test_namestore_api_lookup_shadow_filter.c | ||
413 | test_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 | |||
421 | test_namestore_api_lookup_shadow_filter_sqlite_SOURCES = \ | 334 | test_namestore_api_lookup_shadow_filter_sqlite_SOURCES = \ |
422 | test_namestore_api_lookup_shadow_filter.c | 335 | test_namestore_api_lookup_shadow_filter.c |
423 | test_namestore_api_lookup_shadow_filter_sqlite_LDADD = \ | 336 | test_namestore_api_lookup_shadow_filter_sqlite_LDADD = \ |
@@ -455,24 +368,6 @@ test_namestore_api_remove_postgres_LDADD = \ | |||
455 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 368 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
456 | libgnunetnamestore.la | 369 | libgnunetnamestore.la |
457 | 370 | ||
458 | test_namestore_api_remove_flat_SOURCES = \ | ||
459 | test_namestore_api_remove.c | ||
460 | test_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 | |||
467 | test_namestore_api_remove_not_existing_record_flat_SOURCES = \ | ||
468 | test_namestore_api_remove_not_existing_record.c | ||
469 | test_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 | |||
476 | test_namestore_api_remove_not_existing_record_sqlite_SOURCES = \ | 371 | test_namestore_api_remove_not_existing_record_sqlite_SOURCES = \ |
477 | test_namestore_api_remove_not_existing_record.c | 372 | test_namestore_api_remove_not_existing_record.c |
478 | test_namestore_api_remove_not_existing_record_sqlite_LDADD = \ | 373 | test_namestore_api_remove_not_existing_record_sqlite_LDADD = \ |
@@ -491,14 +386,6 @@ test_namestore_api_remove_not_existing_record_postgres_LDADD = \ | |||
491 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 386 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
492 | libgnunetnamestore.la | 387 | libgnunetnamestore.la |
493 | 388 | ||
494 | test_namestore_api_zone_to_name_flat_SOURCES = \ | ||
495 | test_namestore_api_zone_to_name.c | ||
496 | test_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 | |||
502 | test_namestore_api_zone_to_name_sqlite_SOURCES = \ | 389 | test_namestore_api_zone_to_name_sqlite_SOURCES = \ |
503 | test_namestore_api_zone_to_name.c | 390 | test_namestore_api_zone_to_name.c |
504 | test_namestore_api_zone_to_name_sqlite_LDADD = \ | 391 | test_namestore_api_zone_to_name_sqlite_LDADD = \ |
@@ -515,15 +402,6 @@ test_namestore_api_zone_to_name_postgres_LDADD = \ | |||
515 | $(top_builddir)/src/util/libgnunetutil.la \ | 402 | $(top_builddir)/src/util/libgnunetutil.la \ |
516 | libgnunetnamestore.la | 403 | libgnunetnamestore.la |
517 | 404 | ||
518 | test_namestore_api_monitoring_flat_SOURCES = \ | ||
519 | test_namestore_api_monitoring.c | ||
520 | test_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 | |||
527 | test_namestore_api_monitoring_sqlite_SOURCES = \ | 405 | test_namestore_api_monitoring_sqlite_SOURCES = \ |
528 | test_namestore_api_monitoring.c | 406 | test_namestore_api_monitoring.c |
529 | test_namestore_api_monitoring_sqlite_LDADD = \ | 407 | test_namestore_api_monitoring_sqlite_LDADD = \ |
@@ -542,41 +420,52 @@ test_namestore_api_monitoring_postgres_LDADD = \ | |||
542 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 420 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
543 | $(top_builddir)/src/util/libgnunetutil.la | 421 | $(top_builddir)/src/util/libgnunetutil.la |
544 | 422 | ||
545 | test_namestore_api_monitoring_existing_flat_SOURCES = \ | 423 | test_namestore_api_monitoring_existing_sqlite_SOURCES = \ |
546 | test_namestore_api_monitoring_existing.c | 424 | test_namestore_api_monitoring_existing.c |
547 | test_namestore_api_monitoring_existing_flat_LDADD = \ | 425 | test_namestore_api_monitoring_existing_sqlite_LDADD = \ |
548 | $(top_builddir)/src/testing/libgnunettesting.la \ | 426 | $(top_builddir)/src/testing/libgnunettesting.la \ |
549 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 427 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
550 | libgnunetnamestore.la \ | 428 | libgnunetnamestore.la \ |
551 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 429 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
552 | $(top_builddir)/src/util/libgnunetutil.la | 430 | $(top_builddir)/src/util/libgnunetutil.la |
553 | 431 | ||
554 | test_namestore_api_monitoring_existing_sqlite_SOURCES = \ | 432 | test_namestore_api_monitoring_existing_postgres_SOURCES = \ |
555 | test_namestore_api_monitoring_existing.c | 433 | test_namestore_api_monitoring_existing.c |
556 | test_namestore_api_monitoring_existing_sqlite_LDADD = \ | 434 | test_namestore_api_monitoring_existing_postgres_LDADD = \ |
557 | $(top_builddir)/src/testing/libgnunettesting.la \ | 435 | $(top_builddir)/src/testing/libgnunettesting.la \ |
558 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
559 | libgnunetnamestore.la \ | 436 | libgnunetnamestore.la \ |
560 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 437 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
438 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
561 | $(top_builddir)/src/util/libgnunetutil.la | 439 | $(top_builddir)/src/util/libgnunetutil.la |
562 | 440 | ||
563 | test_namestore_api_monitoring_existing_postgres_SOURCES = \ | 441 | test_namestore_api_tx_rollback_sqlite_SOURCES = \ |
564 | test_namestore_api_monitoring_existing.c | 442 | test_namestore_api_tx_rollback.c |
565 | test_namestore_api_monitoring_existing_postgres_LDADD = \ | 443 | test_namestore_api_tx_rollback_sqlite_LDADD = \ |
566 | $(top_builddir)/src/testing/libgnunettesting.la \ | 444 | $(top_builddir)/src/testing/libgnunettesting.la \ |
445 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
567 | libgnunetnamestore.la \ | 446 | libgnunetnamestore.la \ |
568 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 447 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
448 | $(top_builddir)/src/util/libgnunetutil.la | ||
449 | |||
450 | test_namestore_api_tx_rollback_postgres_SOURCES = \ | ||
451 | test_namestore_api_tx_rollback.c | ||
452 | test_namestore_api_tx_rollback_postgres_LDADD = \ | ||
453 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
569 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 454 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
455 | libgnunetnamestore.la \ | ||
456 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
570 | $(top_builddir)/src/util/libgnunetutil.la | 457 | $(top_builddir)/src/util/libgnunetutil.la |
571 | 458 | ||
572 | test_namestore_api_zone_iteration_flat_SOURCES = \ | 459 | if HAVE_EXPERIMENTAL |
573 | test_namestore_api_zone_iteration.c | 460 | test_namestore_api_edit_records_postgres_SOURCES = \ |
574 | test_namestore_api_zone_iteration_flat_LDADD = \ | 461 | test_namestore_api_edit_records.c |
462 | test_namestore_api_edit_records_postgres_LDADD = \ | ||
575 | $(top_builddir)/src/testing/libgnunettesting.la \ | 463 | $(top_builddir)/src/testing/libgnunettesting.la \ |
576 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 464 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
577 | $(top_builddir)/src/util/libgnunetutil.la \ | 465 | libgnunetnamestore.la \ |
578 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 466 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
579 | libgnunetnamestore.la | 467 | $(top_builddir)/src/util/libgnunetutil.la |
468 | endif | ||
580 | 469 | ||
581 | test_namestore_api_zone_iteration_sqlite_SOURCES = \ | 470 | test_namestore_api_zone_iteration_sqlite_SOURCES = \ |
582 | test_namestore_api_zone_iteration.c | 471 | test_namestore_api_zone_iteration.c |
@@ -614,24 +503,6 @@ perf_namestore_api_zone_iteration_sqlite_LDADD = \ | |||
614 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 503 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
615 | libgnunetnamestore.la | 504 | libgnunetnamestore.la |
616 | 505 | ||
617 | perf_namestore_api_zone_iteration_flat_SOURCES = \ | ||
618 | perf_namestore_api_zone_iteration.c | ||
619 | perf_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 | |||
626 | test_namestore_api_zone_iteration_nick_flat_SOURCES = \ | ||
627 | test_namestore_api_zone_iteration_nick.c | ||
628 | test_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 | |||
635 | test_namestore_api_zone_iteration_nick_sqlite_SOURCES = \ | 506 | test_namestore_api_zone_iteration_nick_sqlite_SOURCES = \ |
636 | test_namestore_api_zone_iteration_nick.c | 507 | test_namestore_api_zone_iteration_nick.c |
637 | test_namestore_api_zone_iteration_nick_sqlite_LDADD = \ | 508 | test_namestore_api_zone_iteration_nick_sqlite_LDADD = \ |
@@ -650,15 +521,6 @@ test_namestore_api_zone_iteration_nick_postgres_LDADD = \ | |||
650 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 521 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
651 | libgnunetnamestore.la | 522 | libgnunetnamestore.la |
652 | 523 | ||
653 | test_namestore_api_zone_iteration_specific_zone_flat_SOURCES = \ | ||
654 | test_namestore_api_zone_iteration_specific_zone.c | ||
655 | test_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 | |||
662 | test_namestore_api_zone_iteration_specific_zone_sqlite_SOURCES = \ | 524 | test_namestore_api_zone_iteration_specific_zone_sqlite_SOURCES = \ |
663 | test_namestore_api_zone_iteration_specific_zone.c | 525 | test_namestore_api_zone_iteration_specific_zone.c |
664 | test_namestore_api_zone_iteration_specific_zone_sqlite_LDADD = \ | 526 | test_namestore_api_zone_iteration_specific_zone_sqlite_LDADD = \ |
@@ -677,15 +539,6 @@ test_namestore_api_zone_iteration_specific_zone_postgres_LDADD = \ | |||
677 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 539 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
678 | libgnunetnamestore.la | 540 | libgnunetnamestore.la |
679 | 541 | ||
680 | test_namestore_api_zone_iteration_stop_flat_SOURCES = \ | ||
681 | test_namestore_api_zone_iteration_stop.c | ||
682 | test_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 | |||
689 | test_namestore_api_zone_iteration_stop_sqlite_SOURCES = \ | 542 | test_namestore_api_zone_iteration_stop_sqlite_SOURCES = \ |
690 | test_namestore_api_zone_iteration_stop.c | 543 | test_namestore_api_zone_iteration_stop.c |
691 | test_namestore_api_zone_iteration_stop_sqlite_LDADD = \ | 544 | test_namestore_api_zone_iteration_stop_sqlite_LDADD = \ |
@@ -704,13 +557,6 @@ test_namestore_api_zone_iteration_stop_postgres_LDADD = \ | |||
704 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 557 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
705 | libgnunetnamestore.la | 558 | libgnunetnamestore.la |
706 | 559 | ||
707 | test_plugin_namestore_flat_SOURCES = \ | ||
708 | test_plugin_namestore.c | ||
709 | test_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 | |||
714 | test_plugin_namestore_sqlite_SOURCES = \ | 560 | test_plugin_namestore_sqlite_SOURCES = \ |
715 | test_plugin_namestore.c | 561 | test_plugin_namestore.c |
716 | test_plugin_namestore_sqlite_LDADD = \ | 562 | test_plugin_namestore_sqlite_LDADD = \ |
@@ -730,20 +576,18 @@ check_SCRIPTS = \ | |||
730 | test_namestore_lookup.sh \ | 576 | test_namestore_lookup.sh \ |
731 | test_namestore_delete.sh | 577 | test_namestore_delete.sh |
732 | 578 | ||
733 | check_SCRIPTS += \ | 579 | # FIXME |
734 | test_plugin_rest_namestore.sh | 580 | #check_SCRIPTS += \ |
581 | # test_plugin_rest_namestore.sh | ||
735 | 582 | ||
736 | EXTRA_DIST = \ | 583 | EXTRA_DIST = \ |
737 | test_common.c \ | 584 | test_common.c \ |
738 | test_namestore_api.conf \ | 585 | test_namestore_api.conf \ |
739 | test_namestore_api_postgres.conf \ | 586 | test_namestore_api_postgres.conf \ |
740 | test_namestore_api_sqlite.conf \ | 587 | test_namestore_api_sqlite.conf \ |
741 | test_namestore_api_flat.conf \ | ||
742 | perf_namestore_api_postgres.conf \ | 588 | perf_namestore_api_postgres.conf \ |
743 | perf_namestore_api_sqlite.conf \ | 589 | perf_namestore_api_sqlite.conf \ |
744 | perf_namestore_api_flat.conf \ | ||
745 | test_plugin_namestore_sqlite.conf \ | 590 | test_plugin_namestore_sqlite.conf \ |
746 | test_plugin_namestore_postgres.conf \ | 591 | test_plugin_namestore_postgres.conf \ |
747 | test_plugin_namestore_flat.conf \ | ||
748 | test_hostkey \ | 592 | test_hostkey \ |
749 | $(check_SCRIPTS) | 593 | $(check_SCRIPTS) |
diff --git a/src/namestore/gnunet-namestore-dbtool.c b/src/namestore/gnunet-namestore-dbtool.c new file mode 100644 index 000000000..b0f7e2ab9 --- /dev/null +++ b/src/namestore/gnunet-namestore-dbtool.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2013, 2014, 2019, 2022 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file gnunet-namestore-dbtool.c | ||
22 | * @brief command line tool to manipulate the database backends for the namestore | ||
23 | * @author Martin Schanzenbach | ||
24 | * | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include <gnunet_util_lib.h> | ||
28 | #include <gnunet_namestore_plugin.h> | ||
29 | |||
30 | /** | ||
31 | * Name of the plugin argument | ||
32 | */ | ||
33 | static char *pluginname; | ||
34 | |||
35 | /** | ||
36 | * Reset argument | ||
37 | */ | ||
38 | static int reset; | ||
39 | |||
40 | /** | ||
41 | * Initialize argument | ||
42 | */ | ||
43 | static int init; | ||
44 | |||
45 | /** | ||
46 | * Return code | ||
47 | */ | ||
48 | static int ret = 0; | ||
49 | |||
50 | /** | ||
51 | * Task run on shutdown. Cleans up everything. | ||
52 | * | ||
53 | * @param cls unused | ||
54 | */ | ||
55 | static void | ||
56 | do_shutdown (void *cls) | ||
57 | { | ||
58 | (void) cls; | ||
59 | if (NULL != pluginname) | ||
60 | GNUNET_free (pluginname); | ||
61 | } | ||
62 | /** | ||
63 | * Main function that will be run. | ||
64 | * | ||
65 | * @param cls closure | ||
66 | * @param args remaining command-line arguments | ||
67 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
68 | * @param cfg configuration | ||
69 | */ | ||
70 | static void | ||
71 | run (void *cls, | ||
72 | char *const *args, | ||
73 | const char *cfgfile, | ||
74 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
75 | { | ||
76 | const char *pkey_str; | ||
77 | char *db_lib_name; | ||
78 | char *emsg; | ||
79 | struct GNUNET_NAMESTORE_PluginFunctions *plugin; | ||
80 | |||
81 | (void) cls; | ||
82 | (void) args; | ||
83 | (void) cfgfile; | ||
84 | if (NULL != args[0]) | ||
85 | GNUNET_log ( | ||
86 | GNUNET_ERROR_TYPE_WARNING, | ||
87 | _ ("Superfluous command line arguments (starting with `%s') ignored\n"), | ||
88 | args[0]); | ||
89 | |||
90 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg); | ||
91 | if (NULL == pluginname) | ||
92 | { | ||
93 | fprintf (stderr, "No plugin given!\n"); | ||
94 | ret = 1; | ||
95 | GNUNET_SCHEDULER_shutdown (); | ||
96 | return; | ||
97 | } | ||
98 | GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", pluginname); | ||
99 | plugin = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); | ||
100 | if (NULL == plugin) | ||
101 | { | ||
102 | fprintf (stderr, "Failed to load %s!\n", db_lib_name); | ||
103 | ret = 1; | ||
104 | GNUNET_SCHEDULER_shutdown (); | ||
105 | GNUNET_free (db_lib_name); | ||
106 | return; | ||
107 | } | ||
108 | if (reset) | ||
109 | { | ||
110 | if (GNUNET_OK != plugin->reset_database (plugin->cls, &emsg)) | ||
111 | { | ||
112 | // FIXME do we want to return a reason? | ||
113 | fprintf (stderr, "Failed to reset database: %s\n", | ||
114 | emsg); | ||
115 | ret = 1; | ||
116 | GNUNET_free (emsg); | ||
117 | GNUNET_free (db_lib_name); | ||
118 | GNUNET_SCHEDULER_shutdown (); | ||
119 | return; | ||
120 | } | ||
121 | } | ||
122 | else if (init) | ||
123 | { | ||
124 | if (GNUNET_OK != plugin->initialize_database (plugin->cls, &emsg)) | ||
125 | { | ||
126 | // FIXME do we want to return a reason? | ||
127 | fprintf (stderr, "Failed to initialize database: %s\n", | ||
128 | emsg); | ||
129 | ret = 1; | ||
130 | GNUNET_free (emsg); | ||
131 | GNUNET_free (db_lib_name); | ||
132 | GNUNET_SCHEDULER_shutdown (); | ||
133 | return; | ||
134 | } | ||
135 | } | ||
136 | GNUNET_SCHEDULER_shutdown (); | ||
137 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, plugin)); | ||
138 | GNUNET_free (db_lib_name); | ||
139 | } | ||
140 | |||
141 | |||
142 | /** | ||
143 | * The main function for gnunet-namestore-dbtool. | ||
144 | * | ||
145 | * @param argc number of arguments from the command line | ||
146 | * @param argv command line arguments | ||
147 | * @return 0 ok, 1 on error | ||
148 | */ | ||
149 | int | ||
150 | main (int argc, char *const *argv) | ||
151 | { | ||
152 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
153 | { GNUNET_GETOPT_option_flag ('i', "init", gettext_noop ( | ||
154 | "initialize database"), &init), | ||
155 | GNUNET_GETOPT_option_flag ('r', | ||
156 | "reset", | ||
157 | gettext_noop ( | ||
158 | "reset database (DANGEROUS: All existing data is lost!"), | ||
159 | &reset), | ||
160 | GNUNET_GETOPT_option_string ( | ||
161 | 'p', | ||
162 | "plugin", | ||
163 | "PLUGIN", | ||
164 | gettext_noop ( | ||
165 | "the namestore plugin to work with, e.g. 'sqlite'"), | ||
166 | &pluginname), | ||
167 | GNUNET_GETOPT_OPTION_END }; | ||
168 | int lret; | ||
169 | |||
170 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
171 | return 2; | ||
172 | |||
173 | GNUNET_log_setup ("gnunet-namestore-dbtool", "WARNING", NULL); | ||
174 | if (GNUNET_OK != | ||
175 | (lret = GNUNET_PROGRAM_run (argc, | ||
176 | argv, | ||
177 | "gnunet-namestore-dbtool", | ||
178 | _ ( | ||
179 | "GNUnet namestore database manipulation tool"), | ||
180 | options, | ||
181 | &run, | ||
182 | NULL))) | ||
183 | { | ||
184 | GNUNET_free_nz ((void *) argv); | ||
185 | return lret; | ||
186 | } | ||
187 | GNUNET_free_nz ((void *) argv); | ||
188 | return ret; | ||
189 | } | ||
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index 6d3cc45ec..fbe188122 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c | |||
@@ -85,6 +85,11 @@ struct ZoneIteration | |||
85 | struct GNUNET_IDENTITY_PrivateKey zone; | 85 | struct GNUNET_IDENTITY_PrivateKey zone; |
86 | 86 | ||
87 | /** | 87 | /** |
88 | * The record set filter | ||
89 | */ | ||
90 | enum GNUNET_GNSRECORD_Filter filter; | ||
91 | |||
92 | /** | ||
88 | * Last sequence number in the zone iteration used to address next | 93 | * Last sequence number in the zone iteration used to address next |
89 | * result of the zone iteration in the store | 94 | * result of the zone iteration in the store |
90 | * | 95 | * |
@@ -132,6 +137,21 @@ struct NamestoreClient | |||
132 | struct GNUNET_SERVICE_Client *client; | 137 | struct GNUNET_SERVICE_Client *client; |
133 | 138 | ||
134 | /** | 139 | /** |
140 | * Database handle for client | ||
141 | */ | ||
142 | struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; | ||
143 | |||
144 | /** | ||
145 | * Name of loaded plugin (neeed for cleanup) | ||
146 | */ | ||
147 | char *db_lib_name; | ||
148 | |||
149 | /** | ||
150 | * GNUNET_YES if this nc has begun a transaction which is uncommited. | ||
151 | */ | ||
152 | int in_transaction; | ||
153 | |||
154 | /** | ||
135 | * Message queue for transmission to @e client | 155 | * Message queue for transmission to @e client |
136 | */ | 156 | */ |
137 | struct GNUNET_MQ_Handle *mq; | 157 | struct GNUNET_MQ_Handle *mq; |
@@ -176,6 +196,11 @@ struct ZoneMonitor | |||
176 | struct GNUNET_IDENTITY_PrivateKey zone; | 196 | struct GNUNET_IDENTITY_PrivateKey zone; |
177 | 197 | ||
178 | /** | 198 | /** |
199 | * The record set filter | ||
200 | */ | ||
201 | enum GNUNET_GNSRECORD_Filter filter; | ||
202 | |||
203 | /** | ||
179 | * Task active during initial iteration. | 204 | * Task active during initial iteration. |
180 | */ | 205 | */ |
181 | struct GNUNET_SCHEDULER_Task *task; | 206 | struct GNUNET_SCHEDULER_Task *task; |
@@ -288,20 +313,42 @@ struct StoreActivity | |||
288 | struct NamestoreClient *nc; | 313 | struct NamestoreClient *nc; |
289 | 314 | ||
290 | /** | 315 | /** |
291 | * Copy of the original store message (as data fields in @e rd will | 316 | * The request ID |
317 | */ | ||
318 | uint32_t rid; | ||
319 | |||
320 | /** | ||
321 | * The currently processed record | ||
322 | */ | ||
323 | uint16_t rd_set_pos; | ||
324 | |||
325 | /** | ||
326 | * The number of records in this activity | ||
327 | */ | ||
328 | uint16_t rd_set_count; | ||
329 | |||
330 | /** | ||
331 | * Wheather or not this store action is already commited. | ||
332 | * The store activity will not be processed unless this field is GNUNET_YES | ||
333 | */ | ||
334 | int uncommited; | ||
335 | |||
336 | /** | ||
337 | * The zone private key | ||
338 | */ | ||
339 | struct GNUNET_IDENTITY_PrivateKey private_key; | ||
340 | |||
341 | /** | ||
342 | * Copy of the original record set (as data fields in @e rd will | ||
292 | * point into it!). | 343 | * point into it!). |
293 | */ | 344 | */ |
294 | const struct RecordStoreMessage *rsm; | 345 | const struct RecordSet *rs; |
295 | 346 | ||
296 | /** | 347 | /** |
297 | * Next zone monitor that still needs to be notified about this PUT. | 348 | * Next zone monitor that still needs to be notified about this PUT. |
298 | */ | 349 | */ |
299 | struct ZoneMonitor *zm_pos; | 350 | struct ZoneMonitor *zm_pos; |
300 | 351 | ||
301 | /** | ||
302 | * Label nicely canonicalized (lower case). | ||
303 | */ | ||
304 | char *conv_name; | ||
305 | }; | 352 | }; |
306 | 353 | ||
307 | 354 | ||
@@ -353,14 +400,15 @@ static struct GNUNET_STATISTICS_Handle *statistics; | |||
353 | static struct GNUNET_NAMECACHE_Handle *namecache; | 400 | static struct GNUNET_NAMECACHE_Handle *namecache; |
354 | 401 | ||
355 | /** | 402 | /** |
356 | * Database handle | 403 | * Name of the database plugin |
357 | */ | 404 | */ |
358 | static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; | 405 | static char *db_lib_name; |
359 | 406 | ||
360 | /** | 407 | /** |
361 | * Name of the database plugin | 408 | * Database handle for service |
362 | */ | 409 | */ |
363 | static char *db_lib_name; | 410 | struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; |
411 | |||
364 | 412 | ||
365 | /** | 413 | /** |
366 | * Head of cop DLL. | 414 | * Head of cop DLL. |
@@ -436,9 +484,6 @@ cleanup_task (void *cls) | |||
436 | GNUNET_NAMECACHE_disconnect (namecache); | 484 | GNUNET_NAMECACHE_disconnect (namecache); |
437 | namecache = NULL; | 485 | namecache = NULL; |
438 | } | 486 | } |
439 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); | ||
440 | GNUNET_free (db_lib_name); | ||
441 | db_lib_name = NULL; | ||
442 | if (NULL != monitor_nc) | 487 | if (NULL != monitor_nc) |
443 | { | 488 | { |
444 | GNUNET_notification_context_destroy (monitor_nc); | 489 | GNUNET_notification_context_destroy (monitor_nc); |
@@ -449,6 +494,9 @@ cleanup_task (void *cls) | |||
449 | GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); | 494 | GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); |
450 | statistics = NULL; | 495 | statistics = NULL; |
451 | } | 496 | } |
497 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); | ||
498 | GNUNET_free (db_lib_name); | ||
499 | db_lib_name = NULL; | ||
452 | } | 500 | } |
453 | 501 | ||
454 | 502 | ||
@@ -461,7 +509,6 @@ static void | |||
461 | free_store_activity (struct StoreActivity *sa) | 509 | free_store_activity (struct StoreActivity *sa) |
462 | { | 510 | { |
463 | GNUNET_CONTAINER_DLL_remove (sa_head, sa_tail, sa); | 511 | GNUNET_CONTAINER_DLL_remove (sa_head, sa_tail, sa); |
464 | GNUNET_free (sa->conv_name); | ||
465 | GNUNET_free (sa); | 512 | GNUNET_free (sa); |
466 | } | 513 | } |
467 | 514 | ||
@@ -560,6 +607,7 @@ cache_nick (const struct GNUNET_IDENTITY_PrivateKey *zone, | |||
560 | /** | 607 | /** |
561 | * Return the NICK record for the zone (if it exists). | 608 | * Return the NICK record for the zone (if it exists). |
562 | * | 609 | * |
610 | * @param nc the namestore client | ||
563 | * @param zone private key for the zone to look for nick | 611 | * @param zone private key for the zone to look for nick |
564 | * @return NULL if no NICK record was found | 612 | * @return NULL if no NICK record was found |
565 | */ | 613 | */ |
@@ -716,38 +764,63 @@ merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd, | |||
716 | * @param name name | 764 | * @param name name |
717 | * @param rd_count number of records in @a rd | 765 | * @param rd_count number of records in @a rd |
718 | * @param rd array of records | 766 | * @param rd array of records |
767 | * @param filter record set filter | ||
719 | */ | 768 | */ |
720 | static void | 769 | static void |
721 | send_lookup_response (struct NamestoreClient *nc, | 770 | send_lookup_response_with_filter (struct NamestoreClient *nc, |
722 | uint32_t request_id, | 771 | uint32_t request_id, |
723 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | 772 | const struct |
724 | const char *name, | 773 | GNUNET_IDENTITY_PrivateKey *zone_key, |
725 | unsigned int rd_count, | 774 | const char *name, |
726 | const struct GNUNET_GNSRECORD_Data *rd) | 775 | unsigned int rd_count, |
776 | const struct GNUNET_GNSRECORD_Data *rd, | ||
777 | enum GNUNET_GNSRECORD_Filter filter) | ||
727 | { | 778 | { |
728 | struct GNUNET_MQ_Envelope *env; | 779 | struct GNUNET_MQ_Envelope *env; |
729 | struct RecordResultMessage *zir_msg; | 780 | struct RecordResultMessage *zir_msg; |
730 | struct GNUNET_GNSRECORD_Data *nick; | 781 | struct GNUNET_GNSRECORD_Data *nick; |
731 | struct GNUNET_GNSRECORD_Data *res; | 782 | struct GNUNET_GNSRECORD_Data *res; |
783 | struct GNUNET_GNSRECORD_Data rd_nf[rd_count]; | ||
784 | struct GNUNET_TIME_Absolute block_exp = GNUNET_TIME_UNIT_ZERO_ABS;; | ||
732 | unsigned int res_count; | 785 | unsigned int res_count; |
786 | unsigned int rd_nf_count; | ||
733 | size_t name_len; | 787 | size_t name_len; |
734 | ssize_t rd_ser_len; | 788 | ssize_t rd_ser_len; |
735 | char *name_tmp; | 789 | char *name_tmp; |
736 | char *rd_ser; | 790 | char *rd_ser; |
791 | char *emsg; | ||
737 | 792 | ||
738 | nick = get_nick_record (zone_key); | 793 | nick = get_nick_record (zone_key); |
739 | GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd)); | 794 | GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd)); |
740 | 795 | ||
796 | if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (name, | ||
797 | rd, | ||
798 | rd_count, | ||
799 | rd_nf, | ||
800 | &rd_nf_count, | ||
801 | &block_exp, | ||
802 | filter, | ||
803 | &emsg)) | ||
804 | { | ||
805 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); | ||
806 | GNUNET_free (emsg); | ||
807 | GNUNET_assert (0); | ||
808 | } | ||
809 | |||
810 | /** | ||
811 | * FIXME if we ever support GNUNET_NAMESTORE_OMIT_PUBLIC, | ||
812 | * we need to omit adding this public record here | ||
813 | */ | ||
741 | if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) | 814 | if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) |
742 | { | 815 | { |
743 | nick->flags = | 816 | nick->flags = |
744 | (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; | 817 | (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; |
745 | merge_with_nick_records (nick, rd_count, rd, &res_count, &res); | 818 | merge_with_nick_records (nick, rd_nf_count, rd_nf, &res_count, &res); |
746 | } | 819 | } |
747 | else | 820 | else |
748 | { | 821 | { |
749 | res_count = rd_count; | 822 | res_count = rd_nf_count; |
750 | res = (struct GNUNET_GNSRECORD_Data *) rd; | 823 | res = (struct GNUNET_GNSRECORD_Data *) rd_nf; |
751 | } | 824 | } |
752 | if (NULL != nick) | 825 | if (NULL != nick) |
753 | GNUNET_free (nick); | 826 | GNUNET_free (nick); |
@@ -759,7 +832,7 @@ send_lookup_response (struct NamestoreClient *nc, | |||
759 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res); | 832 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res); |
760 | if (rd_ser_len < 0) | 833 | if (rd_ser_len < 0) |
761 | { | 834 | { |
762 | if (rd != res) | 835 | if (rd_nf != res) |
763 | GNUNET_free (res); | 836 | GNUNET_free (res); |
764 | GNUNET_break (0); | 837 | GNUNET_break (0); |
765 | GNUNET_SERVICE_client_drop (nc->client); | 838 | GNUNET_SERVICE_client_drop (nc->client); |
@@ -767,7 +840,7 @@ send_lookup_response (struct NamestoreClient *nc, | |||
767 | } | 840 | } |
768 | if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg)) | 841 | if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg)) |
769 | { | 842 | { |
770 | if (rd != res) | 843 | if (rd_nf != res) |
771 | GNUNET_free (res); | 844 | GNUNET_free (res); |
772 | GNUNET_break (0); | 845 | GNUNET_break (0); |
773 | GNUNET_SERVICE_client_drop (nc->client); | 846 | GNUNET_SERVICE_client_drop (nc->client); |
@@ -781,6 +854,7 @@ send_lookup_response (struct NamestoreClient *nc, | |||
781 | zir_msg->rd_count = htons (res_count); | 854 | zir_msg->rd_count = htons (res_count); |
782 | zir_msg->rd_len = htons ((uint16_t) rd_ser_len); | 855 | zir_msg->rd_len = htons ((uint16_t) rd_ser_len); |
783 | zir_msg->private_key = *zone_key; | 856 | zir_msg->private_key = *zone_key; |
857 | zir_msg->expire = GNUNET_TIME_absolute_hton (block_exp); | ||
784 | name_tmp = (char *) &zir_msg[1]; | 858 | name_tmp = (char *) &zir_msg[1]; |
785 | GNUNET_memcpy (name_tmp, name, name_len); | 859 | GNUNET_memcpy (name_tmp, name, name_len); |
786 | rd_ser = &name_tmp[name_len]; | 860 | rd_ser = &name_tmp[name_len]; |
@@ -795,10 +869,33 @@ send_lookup_response (struct NamestoreClient *nc, | |||
795 | 1, | 869 | 1, |
796 | GNUNET_NO); | 870 | GNUNET_NO); |
797 | GNUNET_MQ_send (nc->mq, env); | 871 | GNUNET_MQ_send (nc->mq, env); |
798 | if (rd != res) | 872 | if (rd_nf != res) |
799 | GNUNET_free (res); | 873 | GNUNET_free (res); |
800 | } | 874 | } |
801 | 875 | ||
876 | /** | ||
877 | * Generate a `struct LookupNameResponseMessage` and send it to the | ||
878 | * given client using the given notification context. | ||
879 | * | ||
880 | * @param nc client to unicast to | ||
881 | * @param request_id request ID to use | ||
882 | * @param zone_key zone key of the zone | ||
883 | * @param name name | ||
884 | * @param rd_count number of records in @a rd | ||
885 | * @param rd array of records | ||
886 | */ | ||
887 | static void | ||
888 | send_lookup_response (struct NamestoreClient *nc, | ||
889 | uint32_t request_id, | ||
890 | const struct | ||
891 | GNUNET_IDENTITY_PrivateKey *zone_key, | ||
892 | const char *name, | ||
893 | unsigned int rd_count, | ||
894 | const struct GNUNET_GNSRECORD_Data *rd) | ||
895 | { | ||
896 | send_lookup_response_with_filter (nc, request_id, zone_key, name, | ||
897 | rd_count, rd, GNUNET_GNSRECORD_FILTER_NONE); | ||
898 | } | ||
802 | 899 | ||
803 | /** | 900 | /** |
804 | * Send response to the store request to the client. | 901 | * Send response to the store request to the client. |
@@ -808,7 +905,7 @@ send_lookup_response (struct NamestoreClient *nc, | |||
808 | * @param rid client's request ID | 905 | * @param rid client's request ID |
809 | */ | 906 | */ |
810 | static void | 907 | static void |
811 | send_store_response (struct NamestoreClient *nc, int res, const char*emsg, | 908 | send_store_response (struct NamestoreClient *nc, int res, const char *emsg, |
812 | uint32_t rid) | 909 | uint32_t rid) |
813 | { | 910 | { |
814 | struct GNUNET_MQ_Envelope *env; | 911 | struct GNUNET_MQ_Envelope *env; |
@@ -994,7 +1091,7 @@ refresh_block (struct NamestoreClient *nc, | |||
994 | cop->nc = nc; | 1091 | cop->nc = nc; |
995 | cop->zi = zi; | 1092 | cop->zi = zi; |
996 | if (NULL != zi) | 1093 | if (NULL != zi) |
997 | zi->cache_ops ++; | 1094 | zi->cache_ops++; |
998 | cop->rid = rid; | 1095 | cop->rid = rid; |
999 | GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop); | 1096 | GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop); |
1000 | cop->qe = GNUNET_NAMECACHE_block_cache (namecache, | 1097 | cop->qe = GNUNET_NAMECACHE_block_cache (namecache, |
@@ -1034,71 +1131,95 @@ warn_monitor_slow (void *cls) | |||
1034 | static void | 1131 | static void |
1035 | continue_store_activity (struct StoreActivity *sa) | 1132 | continue_store_activity (struct StoreActivity *sa) |
1036 | { | 1133 | { |
1037 | const struct RecordStoreMessage *rp_msg = sa->rsm; | 1134 | const struct RecordSet *rd_set = sa->rs; |
1038 | unsigned int rd_count; | 1135 | unsigned int rd_count; |
1039 | size_t name_len; | 1136 | size_t name_len; |
1040 | size_t rd_ser_len; | 1137 | size_t rd_ser_len; |
1041 | uint32_t rid; | 1138 | uint32_t rid; |
1042 | const char *name_tmp; | 1139 | const char *name_tmp; |
1043 | const char *rd_ser; | 1140 | const char *rd_ser; |
1141 | const char *buf; | ||
1142 | char *conv_name; | ||
1044 | 1143 | ||
1045 | rid = ntohl (rp_msg->gns_header.r_id); | 1144 | // If we are in a transaction, do not notify monitors or update |
1046 | name_len = ntohs (rp_msg->name_len); | 1145 | // cached. This will be done when we are commiting. |
1047 | rd_count = ntohs (rp_msg->rd_count); | 1146 | if (GNUNET_YES == sa->uncommited) |
1048 | rd_ser_len = ntohs (rp_msg->rd_len); | ||
1049 | name_tmp = (const char *) &rp_msg[1]; | ||
1050 | rd_ser = &name_tmp[name_len]; | ||
1051 | { | 1147 | { |
1052 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | 1148 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1149 | "Transaction not yet committed, delaying monitor and cache updates\n"); | ||
1150 | send_store_response (sa->nc, GNUNET_YES, NULL, sa->rid); | ||
1151 | GNUNET_SERVICE_client_continue (sa->nc->client); | ||
1152 | return; | ||
1153 | } | ||
1154 | buf = (const char *) &sa[1]; | ||
1155 | for (int i = sa->rd_set_pos; i < sa->rd_set_count; i++) | ||
1156 | { | ||
1157 | rd_set = (struct RecordSet *) buf; | ||
1158 | name_len = ntohs (rd_set->name_len); | ||
1159 | rd_count = ntohs (rd_set->rd_count); | ||
1160 | rd_ser_len = ntohs (rd_set->rd_len); | ||
1161 | name_tmp = (const char *) &rd_set[1]; | ||
1162 | rd_ser = &name_tmp[name_len]; | ||
1163 | conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); | ||
1164 | GNUNET_assert (NULL != conv_name); | ||
1165 | { | ||
1166 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
1053 | 1167 | ||
1054 | /* We did this before, must succeed again */ | 1168 | /* We did this before, must succeed again */ |
1055 | GNUNET_assert ( | 1169 | GNUNET_assert ( |
1056 | GNUNET_OK == | 1170 | GNUNET_OK == |
1057 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)); | 1171 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, |
1172 | rd)); | ||
1058 | 1173 | ||
1059 | for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos) | 1174 | for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos) |
1060 | { | ||
1061 | if ((0 != GNUNET_memcmp (&rp_msg->private_key, &zm->zone)) && | ||
1062 | (0 != GNUNET_memcmp (&zm->zone, &zero))) | ||
1063 | { | ||
1064 | sa->zm_pos = zm->next; /* not interesting to this monitor */ | ||
1065 | continue; | ||
1066 | } | ||
1067 | if (zm->limit == zm->iteration_cnt) | ||
1068 | { | 1175 | { |
1069 | zm->sa_waiting = GNUNET_YES; | 1176 | if ((0 != GNUNET_memcmp (&sa->private_key, &zm->zone)) && |
1070 | zm->sa_waiting_start = GNUNET_TIME_absolute_get (); | 1177 | (0 != GNUNET_memcmp (&zm->zone, &zero))) |
1071 | if (NULL != zm->sa_wait_warning) | 1178 | { |
1072 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | 1179 | sa->zm_pos = zm->next; /* not interesting to this monitor */ |
1073 | zm->sa_wait_warning = | 1180 | continue; |
1074 | GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | 1181 | } |
1075 | &warn_monitor_slow, | 1182 | if (zm->limit == zm->iteration_cnt) |
1076 | zm); | 1183 | { |
1077 | return; /* blocked on zone monitor */ | 1184 | zm->sa_waiting = GNUNET_YES; |
1185 | zm->sa_waiting_start = GNUNET_TIME_absolute_get (); | ||
1186 | if (NULL != zm->sa_wait_warning) | ||
1187 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
1188 | zm->sa_wait_warning = | ||
1189 | GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
1190 | &warn_monitor_slow, | ||
1191 | zm); | ||
1192 | GNUNET_free (conv_name); | ||
1193 | return; /* blocked on zone monitor */ | ||
1194 | } | ||
1195 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1196 | "Notifying monitor about changes under label `%s'\n", | ||
1197 | conv_name); | ||
1198 | zm->limit--; | ||
1199 | send_lookup_response_with_filter (zm->nc, | ||
1200 | 0, | ||
1201 | &sa->private_key, | ||
1202 | conv_name, | ||
1203 | rd_count, | ||
1204 | rd, | ||
1205 | zm->filter); | ||
1206 | sa->zm_pos = zm->next; | ||
1078 | } | 1207 | } |
1079 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1208 | /* great, done with the monitors, unpack (again) for refresh_block operation */ |
1080 | "Notifying monitor about changes under label `%s'\n", | 1209 | sa->rd_set_pos++; |
1081 | sa->conv_name); | 1210 | refresh_block ((sa->rd_set_pos == sa->rd_set_count) ? sa->nc : NULL, |
1082 | zm->limit--; | 1211 | NULL, |
1083 | send_lookup_response (zm->nc, | 1212 | sa->rid, |
1084 | 0, | 1213 | &sa->private_key, |
1085 | &rp_msg->private_key, | 1214 | conv_name, |
1086 | sa->conv_name, | 1215 | rd_count, |
1087 | rd_count, | 1216 | rd); |
1088 | rd); | 1217 | GNUNET_free (conv_name); |
1089 | sa->zm_pos = zm->next; | ||
1090 | } | 1218 | } |
1091 | /* great, done with the monitors, unpack (again) for refresh_block operation */ | ||
1092 | refresh_block (sa->nc, | ||
1093 | NULL, | ||
1094 | rid, | ||
1095 | &rp_msg->private_key, | ||
1096 | sa->conv_name, | ||
1097 | rd_count, | ||
1098 | rd); | ||
1099 | } | 1219 | } |
1100 | GNUNET_SERVICE_client_continue (sa->nc->client); | 1220 | GNUNET_SERVICE_client_continue (sa->nc->client); |
1101 | free_store_activity (sa); | 1221 | free_store_activity (sa); |
1222 | return; | ||
1102 | } | 1223 | } |
1103 | 1224 | ||
1104 | 1225 | ||
@@ -1118,13 +1239,43 @@ client_disconnect_cb (void *cls, | |||
1118 | struct NamestoreClient *nc = app_ctx; | 1239 | struct NamestoreClient *nc = app_ctx; |
1119 | struct ZoneIteration *no; | 1240 | struct ZoneIteration *no; |
1120 | struct CacheOperation *cop; | 1241 | struct CacheOperation *cop; |
1242 | struct StoreActivity *sa; | ||
1243 | struct StoreActivity *sn; | ||
1244 | char *emsg; | ||
1121 | 1245 | ||
1122 | (void) cls; | 1246 | (void) cls; |
1123 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); | 1247 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); |
1248 | if (GNUNET_YES == nc->in_transaction) | ||
1249 | { | ||
1250 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1251 | "Client in transaction, rolling back...\n"); | ||
1252 | if (GNUNET_SYSERR == nc->GSN_database->transaction_rollback ( | ||
1253 | nc->GSN_database->cls, | ||
1254 | &emsg)) | ||
1255 | { | ||
1256 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1257 | "Unable to roll back: %s\n", emsg); | ||
1258 | GNUNET_free (emsg); | ||
1259 | } | ||
1260 | else | ||
1261 | { | ||
1262 | nc->in_transaction = GNUNET_NO; | ||
1263 | while (NULL != sa) | ||
1264 | { | ||
1265 | if ((nc != sa->nc) || | ||
1266 | (GNUNET_NO == sa->uncommited)) | ||
1267 | { | ||
1268 | sa = sa->next; | ||
1269 | continue; | ||
1270 | } | ||
1271 | sn = sa->next; | ||
1272 | free_store_activity (sa); | ||
1273 | sa = sn; | ||
1274 | } | ||
1275 | } | ||
1276 | } | ||
1124 | for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next) | 1277 | for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next) |
1125 | { | 1278 | { |
1126 | struct StoreActivity *san; | ||
1127 | |||
1128 | if (nc != zm->nc) | 1279 | if (nc != zm->nc) |
1129 | continue; | 1280 | continue; |
1130 | GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm); | 1281 | GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm); |
@@ -1138,9 +1289,9 @@ client_disconnect_cb (void *cls, | |||
1138 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | 1289 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); |
1139 | zm->sa_wait_warning = NULL; | 1290 | zm->sa_wait_warning = NULL; |
1140 | } | 1291 | } |
1141 | for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san) | 1292 | for (sa = sa_head; NULL != sa; sa = sn) |
1142 | { | 1293 | { |
1143 | san = sa->next; | 1294 | sn = sa->next; |
1144 | if (zm == sa->zm_pos) | 1295 | if (zm == sa->zm_pos) |
1145 | { | 1296 | { |
1146 | sa->zm_pos = zm->next; | 1297 | sa->zm_pos = zm->next; |
@@ -1168,6 +1319,9 @@ client_disconnect_cb (void *cls, | |||
1168 | for (cop = cop_head; NULL != cop; cop = cop->next) | 1319 | for (cop = cop_head; NULL != cop; cop = cop->next) |
1169 | if (nc == cop->nc) | 1320 | if (nc == cop->nc) |
1170 | cop->nc = NULL; | 1321 | cop->nc = NULL; |
1322 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (nc->db_lib_name, | ||
1323 | nc->GSN_database)); | ||
1324 | GNUNET_free (nc->db_lib_name); | ||
1171 | GNUNET_free (nc); | 1325 | GNUNET_free (nc); |
1172 | } | 1326 | } |
1173 | 1327 | ||
@@ -1186,12 +1340,36 @@ client_connect_cb (void *cls, | |||
1186 | struct GNUNET_MQ_Handle *mq) | 1340 | struct GNUNET_MQ_Handle *mq) |
1187 | { | 1341 | { |
1188 | struct NamestoreClient *nc; | 1342 | struct NamestoreClient *nc; |
1343 | char *database; | ||
1189 | 1344 | ||
1190 | (void) cls; | 1345 | (void) cls; |
1191 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); | 1346 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); |
1192 | nc = GNUNET_new (struct NamestoreClient); | 1347 | nc = GNUNET_new (struct NamestoreClient); |
1193 | nc->client = client; | 1348 | nc->client = client; |
1194 | nc->mq = mq; | 1349 | nc->mq = mq; |
1350 | /* Loading database plugin */ | ||
1351 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (GSN_cfg, | ||
1352 | "namestore", | ||
1353 | "database", | ||
1354 | &database)) | ||
1355 | { | ||
1356 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); | ||
1357 | GNUNET_free (nc); | ||
1358 | return NULL; | ||
1359 | } | ||
1360 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name); | ||
1361 | nc->GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); | ||
1362 | GNUNET_free (database); | ||
1363 | if (NULL == nc->GSN_database) | ||
1364 | { | ||
1365 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1366 | "Could not load database backend `%s'\n", | ||
1367 | db_lib_name); | ||
1368 | GNUNET_free (nc); | ||
1369 | return NULL; | ||
1370 | } | ||
1371 | nc->db_lib_name = GNUNET_strdup (db_lib_name); | ||
1372 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded %s\n", db_lib_name); | ||
1195 | return nc; | 1373 | return nc; |
1196 | } | 1374 | } |
1197 | 1375 | ||
@@ -1403,11 +1581,19 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1403 | rlc.res_rd = NULL; | 1581 | rlc.res_rd = NULL; |
1404 | rlc.rd_ser_len = 0; | 1582 | rlc.rd_ser_len = 0; |
1405 | rlc.nick = get_nick_record (&ll_msg->zone); | 1583 | rlc.nick = get_nick_record (&ll_msg->zone); |
1406 | res = GSN_database->lookup_records (GSN_database->cls, | 1584 | if (GNUNET_YES != ntohl (ll_msg->is_edit_request)) |
1407 | &ll_msg->zone, | 1585 | res = nc->GSN_database->lookup_records (nc->GSN_database->cls, |
1408 | conv_name, | 1586 | &ll_msg->zone, |
1409 | &lookup_it, | 1587 | conv_name, |
1410 | &rlc); | 1588 | &lookup_it, |
1589 | &rlc); | ||
1590 | else | ||
1591 | res = nc->GSN_database->edit_records (nc->GSN_database->cls, | ||
1592 | &ll_msg->zone, | ||
1593 | conv_name, | ||
1594 | &lookup_it, | ||
1595 | &rlc); | ||
1596 | |||
1411 | env = | 1597 | env = |
1412 | GNUNET_MQ_msg_extra (llr_msg, | 1598 | GNUNET_MQ_msg_extra (llr_msg, |
1413 | name_len + rlc.rd_ser_len, | 1599 | name_len + rlc.rd_ser_len, |
@@ -1418,8 +1604,10 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1418 | llr_msg->rd_count = htons (rlc.res_rd_count); | 1604 | llr_msg->rd_count = htons (rlc.res_rd_count); |
1419 | llr_msg->rd_len = htons (rlc.rd_ser_len); | 1605 | llr_msg->rd_len = htons (rlc.rd_ser_len); |
1420 | res_name = (char *) &llr_msg[1]; | 1606 | res_name = (char *) &llr_msg[1]; |
1421 | if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) | 1607 | if (GNUNET_YES == rlc.found) |
1422 | llr_msg->found = htons (GNUNET_YES); | 1608 | llr_msg->found = htons (GNUNET_YES); |
1609 | else if (GNUNET_SYSERR == res) | ||
1610 | llr_msg->found = htons (GNUNET_SYSERR); | ||
1423 | else | 1611 | else |
1424 | llr_msg->found = htons (GNUNET_NO); | 1612 | llr_msg->found = htons (GNUNET_NO); |
1425 | GNUNET_memcpy (&llr_msg[1], conv_name, name_len); | 1613 | GNUNET_memcpy (&llr_msg[1], conv_name, name_len); |
@@ -1441,29 +1629,16 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1441 | static int | 1629 | static int |
1442 | check_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | 1630 | check_record_store (void *cls, const struct RecordStoreMessage *rp_msg) |
1443 | { | 1631 | { |
1444 | size_t name_len; | ||
1445 | size_t msg_size; | 1632 | size_t msg_size; |
1446 | size_t msg_size_exp; | 1633 | size_t min_size_exp; |
1447 | size_t rd_ser_len; | 1634 | size_t rd_set_count; |
1448 | const char *name_tmp; | ||
1449 | 1635 | ||
1450 | (void) cls; | 1636 | (void) cls; |
1451 | name_len = ntohs (rp_msg->name_len); | ||
1452 | msg_size = ntohs (rp_msg->gns_header.header.size); | 1637 | msg_size = ntohs (rp_msg->gns_header.header.size); |
1453 | rd_ser_len = ntohs (rp_msg->rd_len); | 1638 | rd_set_count = ntohs (rp_msg->rd_set_count); |
1454 | msg_size_exp = sizeof(struct RecordStoreMessage) + name_len + rd_ser_len; | 1639 | min_size_exp = sizeof(struct RecordStoreMessage) + sizeof (struct RecordSet) |
1455 | if (msg_size != msg_size_exp) | 1640 | * rd_set_count; |
1456 | { | 1641 | if (msg_size < min_size_exp) |
1457 | GNUNET_break (0); | ||
1458 | return GNUNET_SYSERR; | ||
1459 | } | ||
1460 | if ((0 == name_len) || (name_len > MAX_NAME_LEN)) | ||
1461 | { | ||
1462 | GNUNET_break (0); | ||
1463 | return GNUNET_SYSERR; | ||
1464 | } | ||
1465 | name_tmp = (const char *) &rp_msg[1]; | ||
1466 | if ('\0' != name_tmp[name_len - 1]) | ||
1467 | { | 1642 | { |
1468 | GNUNET_break (0); | 1643 | GNUNET_break (0); |
1469 | return GNUNET_SYSERR; | 1644 | return GNUNET_SYSERR; |
@@ -1496,13 +1671,15 @@ get_block_exp_existing (void *cls, | |||
1496 | unsigned int rd_pub_count; | 1671 | unsigned int rd_pub_count; |
1497 | char *emsg; | 1672 | char *emsg; |
1498 | 1673 | ||
1499 | if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label, | 1674 | if (GNUNET_OK != |
1500 | rd, | 1675 | GNUNET_GNSRECORD_normalize_record_set (label, |
1501 | rd_count, | 1676 | rd, |
1502 | rd_pub, | 1677 | rd_count, |
1503 | &rd_pub_count, | 1678 | rd_pub, |
1504 | exp, | 1679 | &rd_pub_count, |
1505 | &emsg)) | 1680 | exp, |
1681 | GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE, | ||
1682 | &emsg)) | ||
1506 | { | 1683 | { |
1507 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1684 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1508 | "%s\n", emsg); | 1685 | "%s\n", emsg); |
@@ -1510,42 +1687,33 @@ get_block_exp_existing (void *cls, | |||
1510 | } | 1687 | } |
1511 | } | 1688 | } |
1512 | 1689 | ||
1513 | 1690 | static enum GNUNET_GenericReturnValue | |
1514 | /** | 1691 | store_record_set (struct NamestoreClient *nc, |
1515 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | 1692 | const struct GNUNET_IDENTITY_PrivateKey *private_key, |
1516 | * | 1693 | const struct RecordSet *rd_set, |
1517 | * @param cls client sending the message | 1694 | ssize_t *len, |
1518 | * @param rp_msg message of type `struct RecordStoreMessage` | 1695 | char **emsg) |
1519 | */ | ||
1520 | static void | ||
1521 | handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | ||
1522 | { | 1696 | { |
1523 | struct NamestoreClient *nc = cls; | ||
1524 | size_t name_len; | 1697 | size_t name_len; |
1525 | size_t rd_ser_len; | 1698 | size_t rd_ser_len; |
1526 | uint32_t rid; | ||
1527 | const char *name_tmp; | 1699 | const char *name_tmp; |
1528 | char *conv_name; | ||
1529 | const char *rd_ser; | 1700 | const char *rd_ser; |
1701 | char *conv_name; | ||
1530 | unsigned int rd_count; | 1702 | unsigned int rd_count; |
1531 | int res; | 1703 | int res; |
1532 | struct StoreActivity *sa; | ||
1533 | struct GNUNET_TIME_Absolute existing_block_exp; | 1704 | struct GNUNET_TIME_Absolute existing_block_exp; |
1534 | struct GNUNET_TIME_Absolute new_block_exp; | 1705 | struct GNUNET_TIME_Absolute new_block_exp; |
1535 | 1706 | *len = sizeof (struct RecordSet); | |
1536 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1707 | |
1537 | "Received NAMESTORE_RECORD_STORE message\n"); | 1708 | name_len = ntohs (rd_set->name_len); |
1538 | existing_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | 1709 | *len += name_len; |
1539 | new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | 1710 | rd_count = ntohs (rd_set->rd_count); |
1540 | rid = ntohl (rp_msg->gns_header.r_id); | 1711 | rd_ser_len = ntohs (rd_set->rd_len); |
1541 | name_len = ntohs (rp_msg->name_len); | 1712 | *len += rd_ser_len; |
1542 | rd_count = ntohs (rp_msg->rd_count); | 1713 | name_tmp = (const char *) &rd_set[1]; |
1543 | rd_ser_len = ntohs (rp_msg->rd_len); | ||
1544 | name_tmp = (const char *) &rp_msg[1]; | ||
1545 | rd_ser = &name_tmp[name_len]; | 1714 | rd_ser = &name_tmp[name_len]; |
1546 | { | 1715 | { |
1547 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | 1716 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; |
1548 | char *emsg; | ||
1549 | 1717 | ||
1550 | /* Extracting and converting private key */ | 1718 | /* Extracting and converting private key */ |
1551 | conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); | 1719 | conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); |
@@ -1554,33 +1722,27 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1554 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1722 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1555 | "Error normalizing name `%s'\n", | 1723 | "Error normalizing name `%s'\n", |
1556 | name_tmp); | 1724 | name_tmp); |
1557 | send_store_response (nc, GNUNET_SYSERR, _ ("Error normalizing name."), | 1725 | *emsg = GNUNET_strdup (_ ("Error normalizing name.")); |
1558 | rid); | 1726 | return GNUNET_SYSERR; |
1559 | GNUNET_SERVICE_client_continue (nc->client); | ||
1560 | return; | ||
1561 | } | 1727 | } |
1562 | 1728 | ||
1563 | /* Check name for validity */ | 1729 | /* Check name for validity */ |
1564 | if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, &emsg)) | 1730 | if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, emsg)) |
1565 | { | 1731 | { |
1566 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1732 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1567 | "Label invalid: `%s'\n", | 1733 | "Label invalid: `%s'\n", |
1568 | emsg); | 1734 | *emsg); |
1569 | send_store_response (nc, GNUNET_SYSERR, emsg, rid); | ||
1570 | GNUNET_free (emsg); | ||
1571 | GNUNET_free (conv_name); | 1735 | GNUNET_free (conv_name); |
1572 | GNUNET_SERVICE_client_continue (nc->client); | 1736 | return -1; |
1573 | return; | ||
1574 | } | 1737 | } |
1575 | 1738 | ||
1576 | if (GNUNET_OK != | 1739 | if (GNUNET_OK != |
1577 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)) | 1740 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, |
1741 | rd)) | ||
1578 | { | 1742 | { |
1579 | send_store_response (nc, GNUNET_SYSERR, | 1743 | *emsg = GNUNET_strdup (_ ("Error deserializing records.")); |
1580 | _ ("Error deserializing records."), rid); | ||
1581 | GNUNET_free (conv_name); | 1744 | GNUNET_free (conv_name); |
1582 | GNUNET_SERVICE_client_continue (nc->client); | 1745 | return GNUNET_SYSERR; |
1583 | return; | ||
1584 | } | 1746 | } |
1585 | 1747 | ||
1586 | GNUNET_STATISTICS_update (statistics, | 1748 | GNUNET_STATISTICS_update (statistics, |
@@ -1591,11 +1753,13 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1591 | "Creating %u records for name `%s'\n", | 1753 | "Creating %u records for name `%s'\n", |
1592 | (unsigned int) rd_count, | 1754 | (unsigned int) rd_count, |
1593 | conv_name); | 1755 | conv_name); |
1594 | if ((GNUNET_NO == GSN_database->lookup_records (GSN_database->cls, | 1756 | if ((GNUNET_NO == nc->GSN_database->lookup_records (nc->GSN_database->cls, |
1595 | &rp_msg->private_key, | 1757 | private_key, |
1596 | conv_name, | 1758 | conv_name, |
1597 | &get_block_exp_existing, | 1759 | & |
1598 | &existing_block_exp)) && | 1760 | get_block_exp_existing, |
1761 | &existing_block_exp)) | ||
1762 | && | ||
1599 | (rd_count == 0)) | 1763 | (rd_count == 0)) |
1600 | { | 1764 | { |
1601 | /* This name does not exist, so cannot be removed */ | 1765 | /* This name does not exist, so cannot be removed */ |
@@ -1618,7 +1782,6 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1618 | struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1]; | 1782 | struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1]; |
1619 | unsigned int rd_clean_off; | 1783 | unsigned int rd_clean_off; |
1620 | unsigned int rd_nf_count; | 1784 | unsigned int rd_nf_count; |
1621 | char *emsg; | ||
1622 | int have_nick; | 1785 | int have_nick; |
1623 | 1786 | ||
1624 | rd_clean_off = 0; | 1787 | rd_clean_off = 0; |
@@ -1634,27 +1797,27 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1634 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && | 1797 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && |
1635 | (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type)) | 1798 | (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type)) |
1636 | { | 1799 | { |
1637 | cache_nick (&rp_msg->private_key, &rd[i]); | 1800 | // FIXME: In case this is an uncommited transaction, |
1801 | // we should not do this here. Can we do this in the store activity? | ||
1802 | cache_nick (private_key, &rd[i]); | ||
1638 | have_nick = GNUNET_YES; | 1803 | have_nick = GNUNET_YES; |
1639 | } | 1804 | } |
1640 | } | 1805 | } |
1641 | if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (conv_name, | 1806 | if (GNUNET_OK != |
1642 | rd_clean, | 1807 | GNUNET_GNSRECORD_normalize_record_set (conv_name, |
1643 | rd_clean_off, | 1808 | rd_clean, |
1644 | rd_nf, | 1809 | rd_clean_off, |
1645 | &rd_nf_count, | 1810 | rd_nf, |
1646 | &new_block_exp, | 1811 | &rd_nf_count, |
1647 | GNUNET_YES, | 1812 | &new_block_exp, |
1648 | &emsg)) | 1813 | GNUNET_GNSRECORD_FILTER_NONE, |
1814 | emsg)) | ||
1649 | { | 1815 | { |
1650 | send_store_response (nc, GNUNET_SYSERR, emsg, rid); | ||
1651 | GNUNET_free (emsg); | ||
1652 | GNUNET_SERVICE_client_continue (nc->client); | ||
1653 | GNUNET_free (conv_name); | 1816 | GNUNET_free (conv_name); |
1654 | return; | 1817 | return GNUNET_SYSERR; |
1655 | } | 1818 | } |
1656 | /* | 1819 | /* |
1657 | * If existing_block_exp is 0, then there was not record set | 1820 | * If existing_block_exp is 0, then there was no record set |
1658 | * and no tombstone. | 1821 | * and no tombstone. |
1659 | * Otherwise, if the existing block expiration is after the | 1822 | * Otherwise, if the existing block expiration is after the |
1660 | * new block expiration would be, we need to add a tombstone | 1823 | * new block expiration would be, we need to add a tombstone |
@@ -1674,35 +1837,187 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1674 | (GNUNET_NO == have_nick)) | 1837 | (GNUNET_NO == have_nick)) |
1675 | { | 1838 | { |
1676 | /* remove nick record from cache, in case we have one there */ | 1839 | /* remove nick record from cache, in case we have one there */ |
1677 | cache_nick (&rp_msg->private_key, NULL); | 1840 | // FIXME: In case this is an uncommited transaction, |
1841 | // we should not do this here. Can we do this in the store activity? | ||
1842 | cache_nick (private_key, NULL); | ||
1678 | } | 1843 | } |
1679 | res = GSN_database->store_records (GSN_database->cls, | 1844 | res = nc->GSN_database->store_records (nc->GSN_database->cls, |
1680 | &rp_msg->private_key, | 1845 | private_key, |
1681 | conv_name, | 1846 | conv_name, |
1682 | rd_nf_count, | 1847 | rd_nf_count, |
1683 | rd_nf); | 1848 | rd_nf); |
1684 | } | 1849 | } |
1685 | 1850 | ||
1686 | if (GNUNET_OK != res) | 1851 | if (GNUNET_SYSERR == res) |
1687 | { | 1852 | { |
1688 | /* store not successful, no need to tell monitors */ | 1853 | /* store not successful, no need to tell monitors */ |
1689 | send_store_response (nc, res, _ ("Store failed"), rid); | 1854 | *emsg = GNUNET_strdup (_ ("Store failed")); |
1690 | GNUNET_SERVICE_client_continue (nc->client); | ||
1691 | GNUNET_free (conv_name); | 1855 | GNUNET_free (conv_name); |
1856 | return GNUNET_SYSERR; | ||
1857 | } | ||
1858 | } | ||
1859 | GNUNET_free (conv_name); | ||
1860 | return res; | ||
1861 | } | ||
1862 | |||
1863 | /** | ||
1864 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | ||
1865 | * | ||
1866 | * @param cls client sending the message | ||
1867 | * @param rp_msg message of type `struct RecordStoreMessage` | ||
1868 | */ | ||
1869 | static void | ||
1870 | handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | ||
1871 | { | ||
1872 | struct NamestoreClient *nc = cls; | ||
1873 | size_t name_len; | ||
1874 | size_t rd_ser_len; | ||
1875 | uint32_t rid; | ||
1876 | uint16_t rd_set_count; | ||
1877 | const char *name_tmp; | ||
1878 | char *emsg = NULL; | ||
1879 | const char *buf; | ||
1880 | const char *rd_ser; | ||
1881 | unsigned int rd_count; | ||
1882 | ssize_t read; | ||
1883 | struct StoreActivity *sa; | ||
1884 | struct RecordSet *rs; | ||
1885 | struct GNUNET_TIME_Absolute existing_block_exp; | ||
1886 | struct GNUNET_TIME_Absolute new_block_exp; | ||
1887 | enum GNUNET_GenericReturnValue res; | ||
1888 | int blocked = GNUNET_NO; | ||
1889 | |||
1890 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1891 | "Received NAMESTORE_RECORD_STORE message\n"); | ||
1892 | existing_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1893 | new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1894 | rid = ntohl (rp_msg->gns_header.r_id); | ||
1895 | rd_set_count = ntohs (rp_msg->rd_set_count); | ||
1896 | buf = (const char *) &rp_msg[1]; | ||
1897 | for (int i = 0; i < rd_set_count; i++) | ||
1898 | { | ||
1899 | rs = (struct RecordSet *) buf; | ||
1900 | res = store_record_set (nc, &rp_msg->private_key, | ||
1901 | rs, &read, &emsg); | ||
1902 | if (GNUNET_OK != res) | ||
1903 | { | ||
1904 | send_store_response (nc, res, emsg, | ||
1905 | rid); | ||
1906 | GNUNET_free (emsg); | ||
1907 | GNUNET_SERVICE_client_continue (nc->client); | ||
1692 | return; | 1908 | return; |
1693 | } | 1909 | } |
1694 | sa = GNUNET_malloc (sizeof(struct StoreActivity) | 1910 | buf += read; |
1695 | + ntohs (rp_msg->gns_header.header.size)); | ||
1696 | GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa); | ||
1697 | sa->nc = nc; | ||
1698 | sa->rsm = (const struct RecordStoreMessage *) &sa[1]; | ||
1699 | GNUNET_memcpy (&sa[1], rp_msg, ntohs (rp_msg->gns_header.header.size)); | ||
1700 | sa->zm_pos = monitor_head; | ||
1701 | sa->conv_name = conv_name; | ||
1702 | continue_store_activity (sa); | ||
1703 | } | 1911 | } |
1912 | sa = GNUNET_malloc (sizeof(struct StoreActivity) | ||
1913 | + ntohs (rp_msg->gns_header.header.size) | ||
1914 | - sizeof (*rp_msg)); | ||
1915 | GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa); | ||
1916 | sa->nc = nc; | ||
1917 | sa->rs = (struct RecordSet *) &sa[1]; | ||
1918 | sa->rd_set_count = rd_set_count; | ||
1919 | GNUNET_memcpy (&sa[1], (char *) &rp_msg[1], | ||
1920 | ntohs (rp_msg->gns_header.header.size) - sizeof (*rp_msg)); | ||
1921 | sa->rid = rid; | ||
1922 | sa->rd_set_pos = 0; | ||
1923 | sa->private_key = rp_msg->private_key; | ||
1924 | sa->zm_pos = monitor_head; | ||
1925 | sa->uncommited = nc->in_transaction; | ||
1926 | continue_store_activity (sa); | ||
1704 | } | 1927 | } |
1705 | 1928 | ||
1929 | /** | ||
1930 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL message | ||
1931 | * | ||
1932 | * @param cls client sending the message | ||
1933 | * @param tx_msg message of type `struct TxControlMessage` | ||
1934 | */ | ||
1935 | static void | ||
1936 | handle_tx_control (void *cls, const struct TxControlMessage *tx_msg) | ||
1937 | { | ||
1938 | struct NamestoreClient *nc = cls; | ||
1939 | struct TxControlResultMessage *txr_msg; | ||
1940 | struct GNUNET_MQ_Envelope *env; | ||
1941 | struct StoreActivity *sa = sa_head; | ||
1942 | struct StoreActivity *sn; | ||
1943 | enum GNUNET_GenericReturnValue ret; | ||
1944 | char *emsg = NULL; | ||
1945 | char *err_tmp; | ||
1946 | size_t err_len; | ||
1947 | |||
1948 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received TX_CONTROL message\n"); | ||
1949 | |||
1950 | switch (ntohs (tx_msg->control)) | ||
1951 | { | ||
1952 | case GNUNET_NAMESTORE_TX_BEGIN: | ||
1953 | ret = nc->GSN_database->transaction_begin (nc->GSN_database->cls, | ||
1954 | &emsg); | ||
1955 | nc->in_transaction = GNUNET_YES; | ||
1956 | break; | ||
1957 | case GNUNET_NAMESTORE_TX_COMMIT: | ||
1958 | ret = nc->GSN_database->transaction_commit (nc->GSN_database->cls, | ||
1959 | &emsg); | ||
1960 | if (GNUNET_SYSERR != ret) | ||
1961 | { | ||
1962 | nc->in_transaction = GNUNET_NO; | ||
1963 | while (NULL != sa) | ||
1964 | { | ||
1965 | if ((nc != sa->nc) || | ||
1966 | (GNUNET_NO == sa->uncommited)) | ||
1967 | { | ||
1968 | sa = sa->next; | ||
1969 | continue; | ||
1970 | } | ||
1971 | sa->uncommited = GNUNET_NO; | ||
1972 | continue_store_activity (sa); | ||
1973 | sa = sa->next; | ||
1974 | } | ||
1975 | } | ||
1976 | break; | ||
1977 | case GNUNET_NAMESTORE_TX_ROLLBACK: | ||
1978 | ret = nc->GSN_database->transaction_rollback (nc->GSN_database->cls, | ||
1979 | &emsg); | ||
1980 | if (GNUNET_SYSERR != ret) | ||
1981 | { | ||
1982 | nc->in_transaction = GNUNET_NO; | ||
1983 | while (NULL != sa) | ||
1984 | { | ||
1985 | if ((nc != sa->nc) || | ||
1986 | (GNUNET_NO == sa->uncommited)) | ||
1987 | { | ||
1988 | sa = sa->next; | ||
1989 | continue; | ||
1990 | } | ||
1991 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Discarding uncommited StoreActivity\n"); | ||
1992 | sn = sa->next; | ||
1993 | free_store_activity (sa); | ||
1994 | sa = sn; | ||
1995 | } | ||
1996 | } | ||
1997 | break; | ||
1998 | default: | ||
1999 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2000 | "Unknown control type %u\n", ntohs (tx_msg->control)); | ||
2001 | GNUNET_break (0); | ||
2002 | } | ||
2003 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2004 | "TX status is %u\n", ret); | ||
2005 | err_len = (NULL == emsg) ? 0 : strlen (emsg) + 1; | ||
2006 | env = | ||
2007 | GNUNET_MQ_msg_extra (txr_msg, | ||
2008 | err_len, | ||
2009 | GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT); | ||
2010 | txr_msg->gns_header.header.size = htons (sizeof (struct | ||
2011 | TxControlResultMessage) | ||
2012 | + err_len); | ||
2013 | txr_msg->gns_header.r_id = tx_msg->gns_header.r_id; | ||
2014 | txr_msg->success = htons (ret); | ||
2015 | err_tmp = (char *) &txr_msg[1]; | ||
2016 | GNUNET_memcpy (err_tmp, emsg, err_len); | ||
2017 | GNUNET_free (emsg); | ||
2018 | GNUNET_MQ_send (nc->mq, env); | ||
2019 | GNUNET_SERVICE_client_continue (nc->client); | ||
2020 | } | ||
1706 | 2021 | ||
1707 | /** | 2022 | /** |
1708 | * Context for record remove operations passed from #handle_zone_to_name to | 2023 | * Context for record remove operations passed from #handle_zone_to_name to |
@@ -1817,11 +2132,11 @@ handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg) | |||
1817 | ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id); | 2132 | ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id); |
1818 | ztn_ctx.nc = nc; | 2133 | ztn_ctx.nc = nc; |
1819 | ztn_ctx.success = GNUNET_NO; | 2134 | ztn_ctx.success = GNUNET_NO; |
1820 | if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls, | 2135 | if (GNUNET_SYSERR == nc->GSN_database->zone_to_name (nc->GSN_database->cls, |
1821 | &ztn_msg->zone, | 2136 | &ztn_msg->zone, |
1822 | &ztn_msg->value_zone, | 2137 | &ztn_msg->value_zone, |
1823 | &handle_zone_to_name_it, | 2138 | &handle_zone_to_name_it, |
1824 | &ztn_ctx)) | 2139 | &ztn_ctx)) |
1825 | { | 2140 | { |
1826 | /* internal error, hang up instead of signalling something | 2141 | /* internal error, hang up instead of signalling something |
1827 | that might be wrong */ | 2142 | that might be wrong */ |
@@ -1903,12 +2218,13 @@ zone_iterate_proc (void *cls, | |||
1903 | } | 2218 | } |
1904 | proc->limit--; | 2219 | proc->limit--; |
1905 | proc->zi->seq = seq; | 2220 | proc->zi->seq = seq; |
1906 | send_lookup_response (proc->zi->nc, | 2221 | send_lookup_response_with_filter (proc->zi->nc, |
1907 | proc->zi->request_id, | 2222 | proc->zi->request_id, |
1908 | zone_key, | 2223 | zone_key, |
1909 | name, | 2224 | name, |
1910 | rd_count, | 2225 | rd_count, |
1911 | rd); | 2226 | rd, |
2227 | proc->zi->filter); | ||
1912 | 2228 | ||
1913 | 2229 | ||
1914 | do_refresh_block = GNUNET_NO; | 2230 | do_refresh_block = GNUNET_NO; |
@@ -1935,6 +2251,7 @@ run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit) | |||
1935 | struct ZoneIterationProcResult proc; | 2251 | struct ZoneIterationProcResult proc; |
1936 | struct GNUNET_TIME_Absolute start; | 2252 | struct GNUNET_TIME_Absolute start; |
1937 | struct GNUNET_TIME_Relative duration; | 2253 | struct GNUNET_TIME_Relative duration; |
2254 | struct NamestoreClient *nc = zi->nc; | ||
1938 | 2255 | ||
1939 | memset (&proc, 0, sizeof(proc)); | 2256 | memset (&proc, 0, sizeof(proc)); |
1940 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2257 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1945,15 +2262,16 @@ run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit) | |||
1945 | proc.limit = limit; | 2262 | proc.limit = limit; |
1946 | start = GNUNET_TIME_absolute_get (); | 2263 | start = GNUNET_TIME_absolute_get (); |
1947 | GNUNET_break (GNUNET_SYSERR != | 2264 | GNUNET_break (GNUNET_SYSERR != |
1948 | GSN_database->iterate_records (GSN_database->cls, | 2265 | nc->GSN_database->iterate_records (nc->GSN_database->cls, |
1949 | (GNUNET_YES == GNUNET_is_zero ( | 2266 | (GNUNET_YES == |
1950 | &zi->zone)) | 2267 | GNUNET_is_zero ( |
2268 | &zi->zone)) | ||
1951 | ? NULL | 2269 | ? NULL |
1952 | : &zi->zone, | 2270 | : &zi->zone, |
1953 | zi->seq, | 2271 | zi->seq, |
1954 | limit, | 2272 | limit, |
1955 | &zone_iterate_proc, | 2273 | &zone_iterate_proc, |
1956 | &proc)); | 2274 | &proc)); |
1957 | duration = GNUNET_TIME_absolute_get_duration (start); | 2275 | duration = GNUNET_TIME_absolute_get_duration (start); |
1958 | duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit); | 2276 | duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit); |
1959 | GNUNET_STATISTICS_set (statistics, | 2277 | GNUNET_STATISTICS_set (statistics, |
@@ -1987,6 +2305,7 @@ handle_iteration_start (void *cls, | |||
1987 | "Received ZONE_ITERATION_START message\n"); | 2305 | "Received ZONE_ITERATION_START message\n"); |
1988 | zi = GNUNET_new (struct ZoneIteration); | 2306 | zi = GNUNET_new (struct ZoneIteration); |
1989 | zi->request_id = ntohl (zis_msg->gns_header.r_id); | 2307 | zi->request_id = ntohl (zis_msg->gns_header.r_id); |
2308 | zi->filter = ntohs (zis_msg->filter); | ||
1990 | zi->offset = 0; | 2309 | zi->offset = 0; |
1991 | zi->nc = nc; | 2310 | zi->nc = nc; |
1992 | zi->zone = zis_msg->zone; | 2311 | zi->zone = zis_msg->zone; |
@@ -2073,6 +2392,7 @@ static void | |||
2073 | monitor_unblock (struct ZoneMonitor *zm) | 2392 | monitor_unblock (struct ZoneMonitor *zm) |
2074 | { | 2393 | { |
2075 | struct StoreActivity *sa = sa_head; | 2394 | struct StoreActivity *sa = sa_head; |
2395 | int blocked = GNUNET_NO; | ||
2076 | 2396 | ||
2077 | while ((NULL != sa) && (zm->limit > zm->iteration_cnt)) | 2397 | while ((NULL != sa) && (zm->limit > zm->iteration_cnt)) |
2078 | { | 2398 | { |
@@ -2181,16 +2501,19 @@ monitor_iterate_cb (void *cls, | |||
2181 | * @param zis_msg message from the client | 2501 | * @param zis_msg message from the client |
2182 | */ | 2502 | */ |
2183 | static void | 2503 | static void |
2184 | handle_monitor_start (void *cls, const struct ZoneMonitorStartMessage *zis_msg) | 2504 | handle_monitor_start (void *cls, const struct |
2505 | ZoneMonitorStartMessage *zis_msg) | ||
2185 | { | 2506 | { |
2186 | struct NamestoreClient *nc = cls; | 2507 | struct NamestoreClient *nc = cls; |
2187 | struct ZoneMonitor *zm; | 2508 | struct ZoneMonitor *zm; |
2188 | 2509 | ||
2189 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_MONITOR_START message\n"); | 2510 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2511 | "Received ZONE_MONITOR_START message\n"); | ||
2190 | zm = GNUNET_new (struct ZoneMonitor); | 2512 | zm = GNUNET_new (struct ZoneMonitor); |
2191 | zm->nc = nc; | 2513 | zm->nc = nc; |
2192 | zm->zone = zis_msg->zone; | 2514 | zm->zone = zis_msg->zone; |
2193 | zm->limit = 1; | 2515 | zm->limit = 1; |
2516 | zm->filter = ntohs (zis_msg->filter); | ||
2194 | zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first)); | 2517 | zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first)); |
2195 | GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm); | 2518 | GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm); |
2196 | GNUNET_SERVICE_client_mark_monitor (nc->client); | 2519 | GNUNET_SERVICE_client_mark_monitor (nc->client); |
@@ -2212,23 +2535,22 @@ static void | |||
2212 | monitor_iteration_next (void *cls) | 2535 | monitor_iteration_next (void *cls) |
2213 | { | 2536 | { |
2214 | struct ZoneMonitor *zm = cls; | 2537 | struct ZoneMonitor *zm = cls; |
2538 | struct NamestoreClient *nc = zm->nc; | ||
2215 | int ret; | 2539 | int ret; |
2216 | 2540 | ||
2217 | zm->task = NULL; | 2541 | zm->task = NULL; |
2218 | GNUNET_assert (0 == zm->iteration_cnt); | 2542 | GNUNET_assert (0 == zm->iteration_cnt); |
2219 | if (zm->limit > 16) | 2543 | if (zm->limit > 16) |
2220 | zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */ | 2544 | zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */ |
2221 | else | 2545 | else |
2222 | zm->iteration_cnt = zm->limit; /* use it all */ | 2546 | zm->iteration_cnt = zm->limit; /* use it all */ |
2223 | ret = GSN_database->iterate_records (GSN_database->cls, | 2547 | ret = nc->GSN_database->iterate_records (nc->GSN_database->cls, |
2224 | (GNUNET_YES == GNUNET_is_zero ( | 2548 | (GNUNET_YES == GNUNET_is_zero ( |
2225 | &zm->zone)) | 2549 | &zm->zone)) ? NULL : &zm->zone, |
2226 | ? NULL | 2550 | zm->seq, |
2227 | : &zm->zone, | 2551 | zm->iteration_cnt, |
2228 | zm->seq, | 2552 | &monitor_iterate_cb, |
2229 | zm->iteration_cnt, | 2553 | zm); |
2230 | &monitor_iterate_cb, | ||
2231 | zm); | ||
2232 | if (GNUNET_SYSERR == ret) | 2554 | if (GNUNET_SYSERR == ret) |
2233 | { | 2555 | { |
2234 | GNUNET_SERVICE_client_drop (zm->nc->client); | 2556 | GNUNET_SERVICE_client_drop (zm->nc->client); |
@@ -2315,7 +2637,6 @@ run (void *cls, | |||
2315 | struct GNUNET_SERVICE_Handle *service) | 2637 | struct GNUNET_SERVICE_Handle *service) |
2316 | { | 2638 | { |
2317 | char *database; | 2639 | char *database; |
2318 | |||
2319 | (void) cls; | 2640 | (void) cls; |
2320 | (void) service; | 2641 | (void) service; |
2321 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); | 2642 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); |
@@ -2330,26 +2651,31 @@ run (void *cls, | |||
2330 | namecache = GNUNET_NAMECACHE_connect (cfg); | 2651 | namecache = GNUNET_NAMECACHE_connect (cfg); |
2331 | GNUNET_assert (NULL != namecache); | 2652 | GNUNET_assert (NULL != namecache); |
2332 | } | 2653 | } |
2654 | statistics = GNUNET_STATISTICS_create ("namestore", cfg); | ||
2333 | /* Loading database plugin */ | 2655 | /* Loading database plugin */ |
2334 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, | 2656 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, |
2335 | "namestore", | 2657 | "namestore", |
2336 | "database", | 2658 | "database", |
2337 | &database)) | 2659 | &database)) |
2660 | { | ||
2338 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); | 2661 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); |
2339 | 2662 | GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); | |
2663 | return; | ||
2664 | } | ||
2340 | GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); | 2665 | GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); |
2341 | GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); | 2666 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name); |
2667 | GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); | ||
2342 | GNUNET_free (database); | 2668 | GNUNET_free (database); |
2343 | statistics = GNUNET_STATISTICS_create ("namestore", cfg); | ||
2344 | GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); | ||
2345 | if (NULL == GSN_database) | 2669 | if (NULL == GSN_database) |
2346 | { | 2670 | { |
2347 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2671 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2348 | "Could not load database backend `%s'\n", | 2672 | "Could not load database backend `%s'\n", |
2349 | db_lib_name); | 2673 | db_lib_name); |
2350 | GNUNET_SCHEDULER_shutdown (); | 2674 | GNUNET_free (db_lib_name); |
2675 | GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); | ||
2351 | return; | 2676 | return; |
2352 | } | 2677 | } |
2678 | GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); | ||
2353 | } | 2679 | } |
2354 | 2680 | ||
2355 | 2681 | ||
@@ -2363,6 +2689,10 @@ GNUNET_SERVICE_MAIN ( | |||
2363 | &client_connect_cb, | 2689 | &client_connect_cb, |
2364 | &client_disconnect_cb, | 2690 | &client_disconnect_cb, |
2365 | NULL, | 2691 | NULL, |
2692 | GNUNET_MQ_hd_fixed_size (tx_control, | ||
2693 | GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL, | ||
2694 | struct TxControlMessage, | ||
2695 | NULL), | ||
2366 | GNUNET_MQ_hd_var_size (record_store, | 2696 | GNUNET_MQ_hd_var_size (record_store, |
2367 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, | 2697 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, |
2368 | struct RecordStoreMessage, | 2698 | struct RecordStoreMessage, |
diff --git a/src/namestore/namestore.conf.in b/src/namestore/namestore.conf.in index a9c928c66..fe7d4002c 100644 --- a/src/namestore/namestore.conf.in +++ b/src/namestore/namestore.conf.in | |||
@@ -21,12 +21,9 @@ CACHE_KEYS = YES | |||
21 | 21 | ||
22 | 22 | ||
23 | [namestore-sqlite] | 23 | [namestore-sqlite] |
24 | INIT_ON_CONNECT = YES | ||
24 | FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db | 25 | FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db |
25 | 26 | ||
26 | [namestore-heap] | ||
27 | FILENAME = $GNUNET_DATA_HOME/namestore/heap.db | ||
28 | |||
29 | |||
30 | [namestore-postgres] | 27 | [namestore-postgres] |
31 | # How to connect to the database | 28 | # How to connect to the database |
32 | CONFIG = postgres:///gnunet | 29 | CONFIG = postgres:///gnunet |
@@ -34,6 +31,7 @@ CONFIG = postgres:///gnunet | |||
34 | TEMPORARY_TABLE = NO | 31 | TEMPORARY_TABLE = NO |
35 | # Use asynchronous commit (SET synchronous_commit TO OFF). | 32 | # Use asynchronous commit (SET synchronous_commit TO OFF). |
36 | ASYNC_COMMIT = NO | 33 | ASYNC_COMMIT = NO |
34 | INIT_ON_CONNECT = YES | ||
37 | 35 | ||
38 | [uri] | 36 | [uri] |
39 | gns = gnunet-namestore -e 1a -u | 37 | gns = gnunet-namestore -e 1a -u |
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h index 583ec1e68..d7b6fd13e 100644 --- a/src/namestore/namestore.h +++ b/src/namestore/namestore.h | |||
@@ -51,23 +51,9 @@ struct GNUNET_NAMESTORE_Header | |||
51 | uint32_t r_id GNUNET_PACKED; | 51 | uint32_t r_id GNUNET_PACKED; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | 54 | struct RecordSet | |
55 | /** | ||
56 | * Store a record to the namestore (as authority). | ||
57 | */ | ||
58 | struct RecordStoreMessage | ||
59 | { | 55 | { |
60 | /** | 56 | /** |
61 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE | ||
62 | */ | ||
63 | struct GNUNET_NAMESTORE_Header gns_header; | ||
64 | |||
65 | /** | ||
66 | * Expiration time | ||
67 | */ | ||
68 | struct GNUNET_TIME_AbsoluteNBO expire; | ||
69 | |||
70 | /** | ||
71 | * Name length | 57 | * Name length |
72 | */ | 58 | */ |
73 | uint16_t name_len GNUNET_PACKED; | 59 | uint16_t name_len GNUNET_PACKED; |
@@ -87,14 +73,35 @@ struct RecordStoreMessage | |||
87 | */ | 73 | */ |
88 | uint16_t reserved GNUNET_PACKED; | 74 | uint16_t reserved GNUNET_PACKED; |
89 | 75 | ||
76 | |||
77 | /* followed by: | ||
78 | * name with length name_len | ||
79 | * serialized record data with rd_count records | ||
80 | */ | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * Store a record to the namestore (as authority). | ||
85 | */ | ||
86 | struct RecordStoreMessage | ||
87 | { | ||
88 | /** | ||
89 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE | ||
90 | */ | ||
91 | struct GNUNET_NAMESTORE_Header gns_header; | ||
92 | |||
90 | /** | 93 | /** |
91 | * The private key of the authority. | 94 | * The private key of the authority. |
92 | */ | 95 | */ |
93 | struct GNUNET_IDENTITY_PrivateKey private_key; | 96 | struct GNUNET_IDENTITY_PrivateKey private_key; |
94 | 97 | ||
95 | /* followed by: | 98 | /** |
96 | * name with length name_len | 99 | * Number of record sets |
97 | * serialized record data with rd_count records | 100 | */ |
101 | uint16_t rd_set_count; | ||
102 | |||
103 | /** | ||
104 | * Followed by rd_set_count RecordSets | ||
98 | */ | 105 | */ |
99 | }; | 106 | }; |
100 | 107 | ||
@@ -146,6 +153,11 @@ struct LabelLookupMessage | |||
146 | uint32_t label_len GNUNET_PACKED; | 153 | uint32_t label_len GNUNET_PACKED; |
147 | 154 | ||
148 | /** | 155 | /** |
156 | * GNUNET_YES if this lookup corresponds to an edit request | ||
157 | */ | ||
158 | uint32_t is_edit_request GNUNET_PACKED; | ||
159 | |||
160 | /** | ||
149 | * The private key of the zone to look up in | 161 | * The private key of the zone to look up in |
150 | */ | 162 | */ |
151 | struct GNUNET_IDENTITY_PrivateKey zone; | 163 | struct GNUNET_IDENTITY_PrivateKey zone; |
@@ -275,6 +287,12 @@ struct RecordResultMessage | |||
275 | struct GNUNET_NAMESTORE_Header gns_header; | 287 | struct GNUNET_NAMESTORE_Header gns_header; |
276 | 288 | ||
277 | /** | 289 | /** |
290 | * Expiration time if the record result (if any). | ||
291 | * Takes TOMBSTONEs into account. | ||
292 | */ | ||
293 | struct GNUNET_TIME_AbsoluteNBO expire; | ||
294 | |||
295 | /** | ||
278 | * Name length | 296 | * Name length |
279 | */ | 297 | */ |
280 | uint16_t name_len GNUNET_PACKED; | 298 | uint16_t name_len GNUNET_PACKED; |
@@ -305,6 +323,54 @@ struct RecordResultMessage | |||
305 | */ | 323 | */ |
306 | }; | 324 | }; |
307 | 325 | ||
326 | /** | ||
327 | * Send a transaction control message. | ||
328 | */ | ||
329 | struct TxControlMessage | ||
330 | { | ||
331 | /** | ||
332 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL | ||
333 | */ | ||
334 | struct GNUNET_NAMESTORE_Header gns_header; | ||
335 | |||
336 | /** | ||
337 | * The type of control message to send | ||
338 | */ | ||
339 | uint16_t control GNUNET_PACKED; | ||
340 | |||
341 | /** | ||
342 | * always zero (for alignment) | ||
343 | */ | ||
344 | uint16_t reserved GNUNET_PACKED; | ||
345 | |||
346 | }; | ||
347 | |||
348 | /** | ||
349 | * Result of a transaction control message. | ||
350 | */ | ||
351 | struct TxControlResultMessage | ||
352 | { | ||
353 | /** | ||
354 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT | ||
355 | */ | ||
356 | struct GNUNET_NAMESTORE_Header gns_header; | ||
357 | |||
358 | /** | ||
359 | * The type of control message to send | ||
360 | */ | ||
361 | uint16_t control GNUNET_PACKED; | ||
362 | |||
363 | /** | ||
364 | * Of type GNUNET_GenericReturnValue | ||
365 | */ | ||
366 | uint16_t success GNUNET_PACKED; | ||
367 | |||
368 | /* followed by: | ||
369 | * an error message if status != ntohs(GNUNET_OK) | ||
370 | */ | ||
371 | }; | ||
372 | |||
373 | |||
308 | 374 | ||
309 | /** | 375 | /** |
310 | * Start monitoring a zone. | 376 | * Start monitoring a zone. |
@@ -323,6 +389,17 @@ struct ZoneMonitorStartMessage | |||
323 | uint32_t iterate_first GNUNET_PACKED; | 389 | uint32_t iterate_first GNUNET_PACKED; |
324 | 390 | ||
325 | /** | 391 | /** |
392 | * Record set filter control flags. | ||
393 | * See GNUNET_NAMESTORE_Filter enum. | ||
394 | */ | ||
395 | uint16_t filter; | ||
396 | |||
397 | /** | ||
398 | * Reserved for alignment | ||
399 | */ | ||
400 | uint16_t reserved; | ||
401 | |||
402 | /** | ||
326 | * Zone key. | 403 | * Zone key. |
327 | */ | 404 | */ |
328 | struct GNUNET_IDENTITY_PrivateKey zone; | 405 | struct GNUNET_IDENTITY_PrivateKey zone; |
@@ -367,6 +444,17 @@ struct ZoneIterationStartMessage | |||
367 | * Zone key. All zeros for "all zones". | 444 | * Zone key. All zeros for "all zones". |
368 | */ | 445 | */ |
369 | struct GNUNET_IDENTITY_PrivateKey zone; | 446 | struct GNUNET_IDENTITY_PrivateKey zone; |
447 | |||
448 | /** | ||
449 | * Record set filter control flags. | ||
450 | * See GNUNET_NAMESTORE_Filter enum. | ||
451 | */ | ||
452 | uint16_t filter; | ||
453 | |||
454 | /** | ||
455 | * Reserved for alignment | ||
456 | */ | ||
457 | uint16_t reserved; | ||
370 | }; | 458 | }; |
371 | 459 | ||
372 | 460 | ||
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index 73f985803..fd348a057 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c | |||
@@ -83,6 +83,11 @@ struct GNUNET_NAMESTORE_QueueEntry | |||
83 | GNUNET_NAMESTORE_RecordMonitor proc; | 83 | GNUNET_NAMESTORE_RecordMonitor proc; |
84 | 84 | ||
85 | /** | 85 | /** |
86 | * Function to call with the records we get back; or NULL. | ||
87 | */ | ||
88 | GNUNET_NAMESTORE_RecordSetMonitor proc2; | ||
89 | |||
90 | /** | ||
86 | * Closure for @e proc. | 91 | * Closure for @e proc. |
87 | */ | 92 | */ |
88 | void *proc_cls; | 93 | void *proc_cls; |
@@ -151,6 +156,11 @@ struct GNUNET_NAMESTORE_ZoneIterator | |||
151 | GNUNET_NAMESTORE_RecordMonitor proc; | 156 | GNUNET_NAMESTORE_RecordMonitor proc; |
152 | 157 | ||
153 | /** | 158 | /** |
159 | * The continuation to call with the results | ||
160 | */ | ||
161 | GNUNET_NAMESTORE_RecordSetMonitor proc2; | ||
162 | |||
163 | /** | ||
154 | * Closure for @e proc. | 164 | * Closure for @e proc. |
155 | */ | 165 | */ |
156 | void *proc_cls; | 166 | void *proc_cls; |
@@ -630,6 +640,9 @@ handle_record_result (void *cls, const struct RecordResultMessage *msg) | |||
630 | { | 640 | { |
631 | if (NULL != ze->proc) | 641 | if (NULL != ze->proc) |
632 | ze->proc (ze->proc_cls, &msg->private_key, name, rd_count, rd); | 642 | ze->proc (ze->proc_cls, &msg->private_key, name, rd_count, rd); |
643 | if (NULL != ze->proc2) | ||
644 | ze->proc2 (ze->proc_cls, &msg->private_key, name, | ||
645 | rd_count, rd, GNUNET_TIME_absolute_ntoh (msg->expire)); | ||
633 | return; | 646 | return; |
634 | } | 647 | } |
635 | } | 648 | } |
@@ -674,6 +687,60 @@ handle_record_result_end (void *cls, const struct GNUNET_NAMESTORE_Header *msg) | |||
674 | free_ze (ze); | 687 | free_ze (ze); |
675 | } | 688 | } |
676 | 689 | ||
690 | /** | ||
691 | * Handle an incoming message of type | ||
692 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT. | ||
693 | * | ||
694 | * @param qe the respective entry in the message queue | ||
695 | * @param msg the message we received | ||
696 | * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed | ||
697 | */ | ||
698 | static int | ||
699 | check_tx_control_result (void *cls, | ||
700 | const struct TxControlResultMessage *msg) | ||
701 | { | ||
702 | const char *err_tmp; | ||
703 | size_t err_len; | ||
704 | |||
705 | (void) cls; | ||
706 | err_len = ntohs (msg->gns_header.header.size) | ||
707 | - sizeof (struct TxControlResultMessage); | ||
708 | if ((GNUNET_YES == ntohs (msg->success)) && (err_len > 0)) | ||
709 | { | ||
710 | GNUNET_break (0); | ||
711 | return GNUNET_SYSERR; | ||
712 | } | ||
713 | err_tmp = (const char *) &msg[1]; | ||
714 | if ((err_len > 0) && ('\0' != err_tmp[err_len - 1])) | ||
715 | { | ||
716 | GNUNET_break (0); | ||
717 | return GNUNET_SYSERR; | ||
718 | } | ||
719 | return GNUNET_OK; | ||
720 | } | ||
721 | |||
722 | static void | ||
723 | handle_tx_control_result (void *cls, | ||
724 | const struct TxControlResultMessage *msg) | ||
725 | { | ||
726 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
727 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
728 | int res; | ||
729 | const char *emsg; | ||
730 | |||
731 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
732 | emsg = (const char *) &msg[1]; | ||
733 | res = ntohs (msg->success); | ||
734 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
735 | "Received TX_CONTROL_RESULT with result %d\n", | ||
736 | res); | ||
737 | if (NULL == qe) | ||
738 | return; | ||
739 | if (NULL != qe->cont) | ||
740 | qe->cont (qe->cont_cls, res, | ||
741 | (GNUNET_YES == res) ? NULL : emsg); | ||
742 | free_qe (qe); | ||
743 | } | ||
677 | 744 | ||
678 | /** | 745 | /** |
679 | * Handle an incoming message of type | 746 | * Handle an incoming message of type |
@@ -839,6 +906,10 @@ reconnect (struct GNUNET_NAMESTORE_Handle *h) | |||
839 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE, | 906 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE, |
840 | struct LabelLookupResponseMessage, | 907 | struct LabelLookupResponseMessage, |
841 | h), | 908 | h), |
909 | GNUNET_MQ_hd_var_size (tx_control_result, | ||
910 | GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT, | ||
911 | struct TxControlResultMessage, | ||
912 | h), | ||
842 | GNUNET_MQ_handler_end () }; | 913 | GNUNET_MQ_handler_end () }; |
843 | struct GNUNET_NAMESTORE_ZoneIterator *it; | 914 | struct GNUNET_NAMESTORE_ZoneIterator *it; |
844 | struct GNUNET_NAMESTORE_QueueEntry *qe; | 915 | struct GNUNET_NAMESTORE_QueueEntry *qe; |
@@ -1024,32 +1095,60 @@ GNUNET_NAMESTORE_records_store ( | |||
1024 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | 1095 | GNUNET_NAMESTORE_ContinuationWithStatus cont, |
1025 | void *cont_cls) | 1096 | void *cont_cls) |
1026 | { | 1097 | { |
1098 | return GNUNET_NAMESTORE_records_store2 (h, pkey, 1, &label, &rd_count, &rd, | ||
1099 | cont, cont_cls); | ||
1100 | } | ||
1101 | |||
1102 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1103 | GNUNET_NAMESTORE_records_store2 ( | ||
1104 | struct GNUNET_NAMESTORE_Handle *h, | ||
1105 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1106 | unsigned int rd_set_count, | ||
1107 | const char **a_label, | ||
1108 | unsigned int *a_rd_count, | ||
1109 | const struct GNUNET_GNSRECORD_Data **a_rd, | ||
1110 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1111 | void *cont_cls) | ||
1112 | { | ||
1027 | struct GNUNET_NAMESTORE_QueueEntry *qe; | 1113 | struct GNUNET_NAMESTORE_QueueEntry *qe; |
1028 | struct GNUNET_MQ_Envelope *env; | 1114 | struct GNUNET_MQ_Envelope *env; |
1115 | const char *label; | ||
1116 | unsigned int rd_count; | ||
1117 | const struct GNUNET_GNSRECORD_Data *rd; | ||
1029 | char *name_tmp; | 1118 | char *name_tmp; |
1030 | char *rd_ser; | 1119 | char *rd_ser; |
1031 | ssize_t rd_ser_len; | 1120 | ssize_t rd_ser_len[rd_set_count]; |
1032 | size_t name_len; | 1121 | size_t name_len; |
1033 | uint32_t rid; | 1122 | uint32_t rid; |
1034 | struct RecordStoreMessage *msg; | 1123 | struct RecordStoreMessage *msg; |
1124 | struct RecordSet *rd_set; | ||
1035 | ssize_t sret; | 1125 | ssize_t sret; |
1126 | int i; | ||
1127 | size_t rd_set_len = 0; | ||
1036 | 1128 | ||
1037 | name_len = strlen (label) + 1; | 1129 | for (i = 0; i < rd_set_count; i++) |
1038 | if (name_len > MAX_NAME_LEN) | ||
1039 | { | ||
1040 | GNUNET_break (0); | ||
1041 | return NULL; | ||
1042 | } | ||
1043 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
1044 | if (rd_ser_len < 0) | ||
1045 | { | ||
1046 | GNUNET_break (0); | ||
1047 | return NULL; | ||
1048 | } | ||
1049 | if (rd_ser_len > UINT16_MAX) | ||
1050 | { | 1130 | { |
1051 | GNUNET_break (0); | 1131 | label = a_label[i]; |
1052 | return NULL; | 1132 | rd_count = a_rd_count[i]; |
1133 | rd = a_rd[i]; | ||
1134 | name_len = strlen (label) + 1; | ||
1135 | if (name_len > MAX_NAME_LEN) | ||
1136 | { | ||
1137 | GNUNET_break (0); | ||
1138 | return NULL; | ||
1139 | } | ||
1140 | rd_ser_len[i] = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
1141 | if (rd_ser_len[i] < 0) | ||
1142 | { | ||
1143 | GNUNET_break (0); | ||
1144 | return NULL; | ||
1145 | } | ||
1146 | if (rd_ser_len[i] > UINT16_MAX) | ||
1147 | { | ||
1148 | GNUNET_break (0); | ||
1149 | return NULL; | ||
1150 | } | ||
1151 | rd_set_len += sizeof (struct RecordSet) + name_len + rd_ser_len[i]; | ||
1053 | } | 1152 | } |
1054 | rid = get_op_id (h); | 1153 | rid = get_op_id (h); |
1055 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | 1154 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); |
@@ -1061,30 +1160,38 @@ GNUNET_NAMESTORE_records_store ( | |||
1061 | 1160 | ||
1062 | /* setup msg */ | 1161 | /* setup msg */ |
1063 | env = GNUNET_MQ_msg_extra (msg, | 1162 | env = GNUNET_MQ_msg_extra (msg, |
1064 | name_len + rd_ser_len, | 1163 | rd_set_len, |
1065 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE); | 1164 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE); |
1066 | msg->gns_header.r_id = htonl (rid); | 1165 | msg->gns_header.r_id = htonl (rid); |
1067 | msg->name_len = htons (name_len); | 1166 | msg->rd_set_count = htons (rd_set_count); |
1068 | msg->rd_count = htons (rd_count); | ||
1069 | msg->rd_len = htons (rd_ser_len); | ||
1070 | msg->reserved = ntohs (0); | ||
1071 | msg->private_key = *pkey; | 1167 | msg->private_key = *pkey; |
1072 | 1168 | rd_set = (struct RecordSet*) &msg[1]; | |
1073 | name_tmp = (char *) &msg[1]; | 1169 | for (int i = 0; i < rd_set_count; i++) |
1074 | GNUNET_memcpy (name_tmp, label, name_len); | ||
1075 | rd_ser = &name_tmp[name_len]; | ||
1076 | sret = GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser); | ||
1077 | if ((0 > sret) || (sret != rd_ser_len)) | ||
1078 | { | 1170 | { |
1079 | GNUNET_break (0); | 1171 | label = a_label[i]; |
1080 | GNUNET_free (env); | 1172 | rd = a_rd[i]; |
1081 | return NULL; | 1173 | name_len = strlen (label) + 1; |
1174 | rd_set->name_len = htons (name_len); | ||
1175 | rd_set->rd_count = htons (a_rd_count[i]); | ||
1176 | rd_set->rd_len = htons (rd_ser_len[i]); | ||
1177 | rd_set->reserved = ntohs (0); | ||
1178 | name_tmp = (char *) &rd_set[1]; | ||
1179 | GNUNET_memcpy (name_tmp, label, name_len); | ||
1180 | rd_ser = &name_tmp[name_len]; | ||
1181 | sret = GNUNET_GNSRECORD_records_serialize (a_rd_count[i], rd, rd_ser_len[i], | ||
1182 | rd_ser); | ||
1183 | if ((0 > sret) || (sret != rd_ser_len[i])) | ||
1184 | { | ||
1185 | GNUNET_break (0); | ||
1186 | GNUNET_free (env); | ||
1187 | return NULL; | ||
1188 | } | ||
1189 | // Point to next RecordSet | ||
1190 | rd_set = (struct RecordSet*) &name_tmp[name_len + rd_ser_len[i]]; | ||
1082 | } | 1191 | } |
1083 | GNUNET_assert (rd_ser_len == sret); | ||
1084 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1192 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1085 | "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n", | 1193 | "Sending NAMESTORE_RECORD_STORE message for name %u record sets\n", |
1086 | label, | 1194 | rd_set_count); |
1087 | rd_count); | ||
1088 | qe->timeout_task = | 1195 | qe->timeout_task = |
1089 | GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe); | 1196 | GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe); |
1090 | if (NULL == h->mq) | 1197 | if (NULL == h->mq) |
@@ -1100,32 +1207,17 @@ GNUNET_NAMESTORE_records_store ( | |||
1100 | return qe; | 1207 | return qe; |
1101 | } | 1208 | } |
1102 | 1209 | ||
1103 | /** | ||
1104 | * TODO: Experimental API will replace API above. | ||
1105 | */ | ||
1106 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1107 | GNUNET_NAMESTORE_records_replace ( | ||
1108 | struct GNUNET_NAMESTORE_Handle *h, | ||
1109 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1110 | const char *label, | ||
1111 | unsigned int rd_count, | ||
1112 | const struct GNUNET_GNSRECORD_Data *rd, | ||
1113 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1114 | void *cont_cls) | ||
1115 | { | ||
1116 | return GNUNET_NAMESTORE_records_store (h, pkey, label, rd_count, rd, | ||
1117 | cont, cont_cls); | ||
1118 | } | ||
1119 | 1210 | ||
1120 | struct GNUNET_NAMESTORE_QueueEntry * | 1211 | static struct GNUNET_NAMESTORE_QueueEntry * |
1121 | GNUNET_NAMESTORE_records_lookup ( | 1212 | records_lookup ( |
1122 | struct GNUNET_NAMESTORE_Handle *h, | 1213 | struct GNUNET_NAMESTORE_Handle *h, |
1123 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | 1214 | const struct GNUNET_IDENTITY_PrivateKey *pkey, |
1124 | const char *label, | 1215 | const char *label, |
1125 | GNUNET_SCHEDULER_TaskCallback error_cb, | 1216 | GNUNET_SCHEDULER_TaskCallback error_cb, |
1126 | void *error_cb_cls, | 1217 | void *error_cb_cls, |
1127 | GNUNET_NAMESTORE_RecordMonitor rm, | 1218 | GNUNET_NAMESTORE_RecordMonitor rm, |
1128 | void *rm_cls) | 1219 | void *rm_cls, |
1220 | int is_edit_request) | ||
1129 | { | 1221 | { |
1130 | struct GNUNET_NAMESTORE_QueueEntry *qe; | 1222 | struct GNUNET_NAMESTORE_QueueEntry *qe; |
1131 | struct GNUNET_MQ_Envelope *env; | 1223 | struct GNUNET_MQ_Envelope *env; |
@@ -1152,6 +1244,7 @@ GNUNET_NAMESTORE_records_lookup ( | |||
1152 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP); | 1244 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP); |
1153 | msg->gns_header.r_id = htonl (qe->op_id); | 1245 | msg->gns_header.r_id = htonl (qe->op_id); |
1154 | msg->zone = *pkey; | 1246 | msg->zone = *pkey; |
1247 | msg->is_edit_request = htonl (is_edit_request); | ||
1155 | msg->label_len = htonl (label_len); | 1248 | msg->label_len = htonl (label_len); |
1156 | GNUNET_memcpy (&msg[1], label, label_len); | 1249 | GNUNET_memcpy (&msg[1], label, label_len); |
1157 | if (NULL == h->mq) | 1250 | if (NULL == h->mq) |
@@ -1161,12 +1254,24 @@ GNUNET_NAMESTORE_records_lookup ( | |||
1161 | return qe; | 1254 | return qe; |
1162 | } | 1255 | } |
1163 | 1256 | ||
1257 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1258 | GNUNET_NAMESTORE_records_lookup ( | ||
1259 | struct GNUNET_NAMESTORE_Handle *h, | ||
1260 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1261 | const char *label, | ||
1262 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1263 | void *error_cb_cls, | ||
1264 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
1265 | void *rm_cls) | ||
1266 | { | ||
1267 | return records_lookup (h, pkey, label, | ||
1268 | error_cb, error_cb_cls, | ||
1269 | rm, rm_cls, GNUNET_NO); | ||
1270 | |||
1271 | } | ||
1164 | 1272 | ||
1165 | /** | ||
1166 | * TODO experimental API. Will replace old API above. | ||
1167 | */ | ||
1168 | struct GNUNET_NAMESTORE_QueueEntry * | 1273 | struct GNUNET_NAMESTORE_QueueEntry * |
1169 | GNUNET_NAMESTORE_records_select ( | 1274 | GNUNET_NAMESTORE_records_edit ( |
1170 | struct GNUNET_NAMESTORE_Handle *h, | 1275 | struct GNUNET_NAMESTORE_Handle *h, |
1171 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | 1276 | const struct GNUNET_IDENTITY_PrivateKey *pkey, |
1172 | const char *label, | 1277 | const char *label, |
@@ -1175,9 +1280,9 @@ GNUNET_NAMESTORE_records_select ( | |||
1175 | GNUNET_NAMESTORE_RecordMonitor rm, | 1280 | GNUNET_NAMESTORE_RecordMonitor rm, |
1176 | void *rm_cls) | 1281 | void *rm_cls) |
1177 | { | 1282 | { |
1178 | return GNUNET_NAMESTORE_records_lookup (h, pkey, label, | 1283 | return records_lookup (h, pkey, label, |
1179 | error_cb, error_cb_cls, | 1284 | error_cb, error_cb_cls, |
1180 | rm, rm_cls); | 1285 | rm, rm_cls, GNUNET_YES); |
1181 | } | 1286 | } |
1182 | 1287 | ||
1183 | struct GNUNET_NAMESTORE_QueueEntry * | 1288 | struct GNUNET_NAMESTORE_QueueEntry * |
@@ -1217,25 +1322,6 @@ GNUNET_NAMESTORE_zone_to_name ( | |||
1217 | } | 1322 | } |
1218 | 1323 | ||
1219 | 1324 | ||
1220 | /** | ||
1221 | * Starts a new zone iteration (used to periodically PUT all of our | ||
1222 | * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle | ||
1223 | * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and | ||
1224 | * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once | ||
1225 | * immediately, and then again after | ||
1226 | * #GNUNET_NAMESTORE_zone_iterator_next is invoked. | ||
1227 | * | ||
1228 | * @param h handle to the namestore | ||
1229 | * @param zone zone to access, NULL for all zones | ||
1230 | * @param error_cb function to call on error (i.e. disconnect) | ||
1231 | * @param error_cb_cls closure for @a error_cb | ||
1232 | * @param proc function to call on each name from the zone; it | ||
1233 | * will be called repeatedly with a value (if available) | ||
1234 | * @param proc_cls closure for @a proc | ||
1235 | * @param finish_cb function to call on completion | ||
1236 | * @param finish_cb_cls closure for @a finish_cb | ||
1237 | * @return an iterator handle to use for iteration | ||
1238 | */ | ||
1239 | struct GNUNET_NAMESTORE_ZoneIterator * | 1325 | struct GNUNET_NAMESTORE_ZoneIterator * |
1240 | GNUNET_NAMESTORE_zone_iteration_start ( | 1326 | GNUNET_NAMESTORE_zone_iteration_start ( |
1241 | struct GNUNET_NAMESTORE_Handle *h, | 1327 | struct GNUNET_NAMESTORE_Handle *h, |
@@ -1277,15 +1363,50 @@ GNUNET_NAMESTORE_zone_iteration_start ( | |||
1277 | return it; | 1363 | return it; |
1278 | } | 1364 | } |
1279 | 1365 | ||
1366 | struct GNUNET_NAMESTORE_ZoneIterator * | ||
1367 | GNUNET_NAMESTORE_zone_iteration_start2 ( | ||
1368 | struct GNUNET_NAMESTORE_Handle *h, | ||
1369 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
1370 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1371 | void *error_cb_cls, | ||
1372 | GNUNET_NAMESTORE_RecordSetMonitor proc, | ||
1373 | void *proc_cls, | ||
1374 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1375 | void *finish_cb_cls, | ||
1376 | enum GNUNET_GNSRECORD_Filter filter) | ||
1377 | { | ||
1378 | struct GNUNET_NAMESTORE_ZoneIterator *it; | ||
1379 | struct GNUNET_MQ_Envelope *env; | ||
1380 | struct ZoneIterationStartMessage *msg; | ||
1381 | uint32_t rid; | ||
1382 | |||
1383 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_START message\n"); | ||
1384 | rid = get_op_id (h); | ||
1385 | it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator); | ||
1386 | it->h = h; | ||
1387 | it->error_cb = error_cb; | ||
1388 | it->error_cb_cls = error_cb_cls; | ||
1389 | it->finish_cb = finish_cb; | ||
1390 | it->finish_cb_cls = finish_cb_cls; | ||
1391 | it->proc2 = proc; | ||
1392 | it->proc_cls = proc_cls; | ||
1393 | it->op_id = rid; | ||
1394 | if (NULL != zone) | ||
1395 | it->zone = *zone; | ||
1396 | GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it); | ||
1397 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); | ||
1398 | msg->gns_header.r_id = htonl (rid); | ||
1399 | msg->filter = htons ((uint16_t) filter); | ||
1400 | if (NULL != zone) | ||
1401 | msg->zone = *zone; | ||
1402 | if (NULL == h->mq) | ||
1403 | it->env = env; | ||
1404 | else | ||
1405 | GNUNET_MQ_send (h->mq, env); | ||
1406 | return it; | ||
1407 | } | ||
1408 | |||
1280 | 1409 | ||
1281 | /** | ||
1282 | * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start | ||
1283 | * for the next record. | ||
1284 | * | ||
1285 | * @param it the iterator | ||
1286 | * @param limit number of records to return to the iterator in one shot | ||
1287 | * (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again) | ||
1288 | */ | ||
1289 | void | 1410 | void |
1290 | GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it, | 1411 | GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it, |
1291 | uint64_t limit) | 1412 | uint64_t limit) |
@@ -1344,43 +1465,65 @@ GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe) | |||
1344 | * New API draft. Experimental | 1465 | * New API draft. Experimental |
1345 | */ | 1466 | */ |
1346 | 1467 | ||
1347 | struct GNUNET_NAMESTORE_QueueEntry * | 1468 | static struct GNUNET_NAMESTORE_QueueEntry * |
1348 | GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h, | 1469 | send_transaction_control_msg (struct GNUNET_NAMESTORE_Handle *h, |
1349 | GNUNET_SCHEDULER_TaskCallback error_cb, | 1470 | GNUNET_NAMESTORE_ContinuationWithStatus cont, |
1350 | void *error_cb_cls) | 1471 | void *cont_cls, |
1472 | enum GNUNET_NAMESTORE_TxControl ctrl) | ||
1351 | { | 1473 | { |
1474 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
1475 | struct GNUNET_MQ_Envelope *env; | ||
1476 | struct TxControlMessage *msg; | ||
1477 | uint32_t rid; | ||
1478 | |||
1479 | rid = get_op_id (h); | ||
1480 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | ||
1481 | qe->h = h; | ||
1482 | qe->cont = cont; | ||
1483 | qe->cont_cls = cont_cls; | ||
1484 | qe->op_id = rid; | ||
1485 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); | ||
1486 | |||
1487 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL); | ||
1488 | msg->gns_header.r_id = htonl (rid); | ||
1489 | msg->control = htons (ctrl); | ||
1490 | if (NULL == h->mq) | ||
1491 | qe->env = env; | ||
1492 | else | ||
1493 | GNUNET_MQ_send (h->mq, env); | ||
1494 | return qe; | ||
1352 | GNUNET_break (0); | 1495 | GNUNET_break (0); |
1353 | return NULL; | 1496 | return NULL; |
1354 | } | 1497 | } |
1355 | 1498 | ||
1499 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1500 | GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h, | ||
1501 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1502 | void *cont_cls) | ||
1503 | { | ||
1504 | return send_transaction_control_msg (h, cont, cont_cls, | ||
1505 | GNUNET_NAMESTORE_TX_BEGIN); | ||
1506 | } | ||
1356 | 1507 | ||
1357 | struct GNUNET_NAMESTORE_QueueEntry * | 1508 | struct GNUNET_NAMESTORE_QueueEntry * |
1358 | GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h, | 1509 | GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h, |
1359 | GNUNET_SCHEDULER_TaskCallback error_cb, | 1510 | GNUNET_NAMESTORE_ContinuationWithStatus |
1360 | void *error_cb_cls) | 1511 | cont, |
1512 | void *cont_cls) | ||
1361 | { | 1513 | { |
1362 | GNUNET_break (0); | 1514 | return send_transaction_control_msg (h, cont, cont_cls, |
1363 | return NULL; | 1515 | GNUNET_NAMESTORE_TX_COMMIT); |
1364 | } | 1516 | } |
1365 | 1517 | ||
1366 | 1518 | ||
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 | */ | ||
1377 | struct GNUNET_NAMESTORE_QueueEntry * | 1519 | struct GNUNET_NAMESTORE_QueueEntry * |
1378 | GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h, | 1520 | GNUNET_NAMESTORE_transaction_rollback (struct GNUNET_NAMESTORE_Handle *h, |
1379 | GNUNET_SCHEDULER_TaskCallback error_cb, | 1521 | GNUNET_NAMESTORE_ContinuationWithStatus |
1380 | void *error_cb_cls) | 1522 | cont, |
1523 | void *cont_cls) | ||
1381 | { | 1524 | { |
1382 | GNUNET_break (0); | 1525 | return send_transaction_control_msg (h, cont, cont_cls, |
1383 | return NULL; | 1526 | GNUNET_NAMESTORE_TX_ROLLBACK); |
1384 | } | 1527 | } |
1385 | 1528 | ||
1386 | 1529 | ||
diff --git a/src/namestore/namestore_api_monitor.c b/src/namestore/namestore_api_monitor.c index 6670e54ce..968d7ed58 100644 --- a/src/namestore/namestore_api_monitor.c +++ b/src/namestore/namestore_api_monitor.c | |||
@@ -65,6 +65,16 @@ struct GNUNET_NAMESTORE_ZoneMonitor | |||
65 | GNUNET_NAMESTORE_RecordMonitor monitor; | 65 | GNUNET_NAMESTORE_RecordMonitor monitor; |
66 | 66 | ||
67 | /** | 67 | /** |
68 | * Function to call on events. | ||
69 | */ | ||
70 | GNUNET_NAMESTORE_RecordSetMonitor monitor2; | ||
71 | |||
72 | /** | ||
73 | * Record set filter for this monitor | ||
74 | */ | ||
75 | enum GNUNET_GNSRECORD_Filter filter; | ||
76 | |||
77 | /** | ||
68 | * Closure for @e monitor. | 78 | * Closure for @e monitor. |
69 | */ | 79 | */ |
70 | void *monitor_cls; | 80 | void *monitor_cls; |
@@ -213,7 +223,11 @@ handle_result (void *cls, const struct RecordResultMessage *lrm) | |||
213 | GNUNET_assert ( | 223 | GNUNET_assert ( |
214 | GNUNET_OK == | 224 | GNUNET_OK == |
215 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)); | 225 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)); |
216 | zm->monitor (zm->monitor_cls, &lrm->private_key, name_tmp, rd_count, rd); | 226 | if (NULL != zm->monitor2) |
227 | zm->monitor2 (zm->monitor_cls, &lrm->private_key, name_tmp, | ||
228 | rd_count, rd, GNUNET_TIME_absolute_ntoh (lrm->expire)); | ||
229 | else | ||
230 | zm->monitor (zm->monitor_cls, &lrm->private_key, name_tmp, rd_count, rd); | ||
217 | } | 231 | } |
218 | } | 232 | } |
219 | 233 | ||
@@ -272,33 +286,11 @@ reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm) | |||
272 | env = GNUNET_MQ_msg (sm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START); | 286 | env = GNUNET_MQ_msg (sm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START); |
273 | sm->iterate_first = htonl (zm->iterate_first); | 287 | sm->iterate_first = htonl (zm->iterate_first); |
274 | sm->zone = zm->zone; | 288 | sm->zone = zm->zone; |
289 | sm->filter = htons ((uint16_t) zm->filter); | ||
275 | GNUNET_MQ_send (zm->mq, env); | 290 | GNUNET_MQ_send (zm->mq, env); |
276 | } | 291 | } |
277 | 292 | ||
278 | 293 | ||
279 | /** | ||
280 | * Begin monitoring a zone for changes. If @a iterate_first is set, | ||
281 | * we Will first call the @a monitor function on all existing records | ||
282 | * in the selected zone(s). In any case, we will call @a sync and | ||
283 | * afterwards call @a monitor whenever a record changes. | ||
284 | * | ||
285 | * @param cfg configuration to use to connect to namestore | ||
286 | * @param zone zone to monitor | ||
287 | * @param iterate_first #GNUNET_YES to first iterate over all existing records, | ||
288 | * #GNUNET_NO to only return changes that happen from now | ||
289 | * on | ||
290 | * @param error_cb function to call on error (i.e. disconnect); note that | ||
291 | * unlike the other error callbacks in this API, a call to this | ||
292 | * function does NOT destroy the monitor handle, it merely signals | ||
293 | * that monitoring is down. You need to still explicitly call | ||
294 | * #GNUNET_NAMESTORE_zone_monitor_stop(). | ||
295 | * @param error_cb_cls closure for @a error_cb | ||
296 | * @param monitor function to call on zone changes | ||
297 | * @param monitor_cls closure for @a monitor | ||
298 | * @param sync_cb function called when we're in sync with the namestore | ||
299 | * @param cls closure for @a sync_cb | ||
300 | * @return handle to stop monitoring | ||
301 | */ | ||
302 | struct GNUNET_NAMESTORE_ZoneMonitor * | 294 | struct GNUNET_NAMESTORE_ZoneMonitor * |
303 | GNUNET_NAMESTORE_zone_monitor_start ( | 295 | GNUNET_NAMESTORE_zone_monitor_start ( |
304 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 296 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
@@ -333,6 +325,42 @@ GNUNET_NAMESTORE_zone_monitor_start ( | |||
333 | return zm; | 325 | return zm; |
334 | } | 326 | } |
335 | 327 | ||
328 | struct GNUNET_NAMESTORE_ZoneMonitor * | ||
329 | GNUNET_NAMESTORE_zone_monitor_start2 ( | ||
330 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
331 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
332 | int iterate_first, | ||
333 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
334 | void *error_cb_cls, | ||
335 | GNUNET_NAMESTORE_RecordSetMonitor monitor, | ||
336 | void *monitor_cls, | ||
337 | GNUNET_SCHEDULER_TaskCallback sync_cb, | ||
338 | void *sync_cb_cls, | ||
339 | enum GNUNET_GNSRECORD_Filter filter) | ||
340 | { | ||
341 | struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
342 | |||
343 | zm = GNUNET_new (struct GNUNET_NAMESTORE_ZoneMonitor); | ||
344 | if (NULL != zone) | ||
345 | zm->zone = *zone; | ||
346 | zm->iterate_first = iterate_first; | ||
347 | zm->error_cb = error_cb; | ||
348 | zm->error_cb_cls = error_cb_cls; | ||
349 | zm->monitor2 = monitor; | ||
350 | zm->monitor_cls = monitor_cls; | ||
351 | zm->sync_cb = sync_cb; | ||
352 | zm->sync_cb_cls = sync_cb_cls; | ||
353 | zm->cfg = cfg; | ||
354 | zm->filter = filter; | ||
355 | reconnect (zm); | ||
356 | if (NULL == zm->mq) | ||
357 | { | ||
358 | GNUNET_free (zm); | ||
359 | return NULL; | ||
360 | } | ||
361 | return zm; | ||
362 | } | ||
363 | |||
336 | 364 | ||
337 | /** | 365 | /** |
338 | * Calls the monitor processor specified in #GNUNET_NAMESTORE_zone_monitor_start | 366 | * Calls the monitor processor specified in #GNUNET_NAMESTORE_zone_monitor_start |
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] | ||
4 | DATABASE = flat | ||
5 | |||
6 | [namecache] | ||
7 | DISABLE = YES | ||
8 | |||
9 | [namestore-heap] | ||
10 | FILENAME = $GNUNET_TEST_HOME/namestore/heap.db | ||
diff --git a/src/namestore/perf_namestore_api_postgres.conf b/src/namestore/perf_namestore_api_postgres.conf index 52d0ecdd5..12fc24d4b 100644 --- a/src/namestore/perf_namestore_api_postgres.conf +++ b/src/namestore/perf_namestore_api_postgres.conf | |||
@@ -9,3 +9,4 @@ DISABLE = YES | |||
9 | [namestore-postgres] | 9 | [namestore-postgres] |
10 | CONFIG = connect_timeout=10 dbname=gnunetcheck | 10 | CONFIG = connect_timeout=10 dbname=gnunetcheck |
11 | TEMPORARY_TABLE = YES | 11 | TEMPORARY_TABLE = YES |
12 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/perf_namestore_api_sqlite.conf b/src/namestore/perf_namestore_api_sqlite.conf index de0fa3f1f..55c3dc812 100644 --- a/src/namestore/perf_namestore_api_sqlite.conf +++ b/src/namestore/perf_namestore_api_sqlite.conf | |||
@@ -5,3 +5,4 @@ DISABLE = YES | |||
5 | 5 | ||
6 | [namestore-sqlite] | 6 | [namestore-sqlite] |
7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | 7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db |
8 | INIT_ON_CONNECT = YES | ||
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 | */ | ||
36 | struct 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 | |||
52 | struct 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 | */ | ||
88 | static void | ||
89 | hash_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 | */ | ||
121 | static int | ||
122 | database_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 | */ | ||
334 | static int | ||
335 | store_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 | */ | ||
410 | static void | ||
411 | database_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 | */ | ||
452 | static int | ||
453 | namestore_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 | */ | ||
518 | static int | ||
519 | namestore_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 | */ | ||
556 | struct 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 | */ | ||
599 | static int | ||
600 | iterate_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 | */ | ||
647 | static int | ||
648 | namestore_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 | */ | ||
675 | struct 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 | |||
686 | static int | ||
687 | zone_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 | */ | ||
734 | static int | ||
735 | namestore_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 | */ | ||
767 | void * | ||
768 | libgnunet_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 | */ | ||
803 | void * | ||
804 | libgnunet_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..6e5c1c718 100644 --- a/src/namestore/plugin_namestore_postgres.c +++ b/src/namestore/plugin_namestore_postgres.c | |||
@@ -45,6 +45,11 @@ struct Plugin | |||
45 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 45 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * Database is prepared and ready | ||
49 | */ | ||
50 | int ready; | ||
51 | |||
52 | /** | ||
48 | * Postgres database handle. | 53 | * Postgres database handle. |
49 | */ | 54 | */ |
50 | struct GNUNET_PQ_Context *dbh; | 55 | struct GNUNET_PQ_Context *dbh; |
@@ -60,11 +65,11 @@ struct Plugin | |||
60 | * @return #GNUNET_OK on success | 65 | * @return #GNUNET_OK on success |
61 | */ | 66 | */ |
62 | static int | 67 | static int |
63 | database_setup (struct Plugin *plugin) | 68 | init_database (struct Plugin *plugin, char **emsg, int drop) |
64 | { | 69 | { |
65 | struct GNUNET_PQ_ExecuteStatement es_temporary = | 70 | struct GNUNET_PQ_ExecuteStatement es_temporary = |
66 | GNUNET_PQ_make_execute ( | 71 | GNUNET_PQ_make_execute ( |
67 | "CREATE TEMPORARY TABLE IF NOT EXISTS ns098records (" | 72 | "CREATE TEMPORARY TABLE ns098records (" |
68 | " seq BIGSERIAL PRIMARY KEY," | 73 | " seq BIGSERIAL PRIMARY KEY," |
69 | " zone_private_key BYTEA NOT NULL DEFAULT ''," | 74 | " zone_private_key BYTEA NOT NULL DEFAULT ''," |
70 | " pkey BYTEA DEFAULT ''," | 75 | " pkey BYTEA DEFAULT ''," |
@@ -75,7 +80,7 @@ database_setup (struct Plugin *plugin) | |||
75 | " CONSTRAINT zl UNIQUE (zone_private_key,label)" | 80 | " CONSTRAINT zl UNIQUE (zone_private_key,label)" |
76 | ")"); | 81 | ")"); |
77 | struct GNUNET_PQ_ExecuteStatement es_default = | 82 | struct GNUNET_PQ_ExecuteStatement es_default = |
78 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records (" | 83 | GNUNET_PQ_make_execute ("CREATE TABLE ns098records (" |
79 | " seq BIGSERIAL PRIMARY KEY," | 84 | " seq BIGSERIAL PRIMARY KEY," |
80 | " zone_private_key BYTEA NOT NULL DEFAULT ''," | 85 | " zone_private_key BYTEA NOT NULL DEFAULT ''," |
81 | " pkey BYTEA DEFAULT ''," | 86 | " pkey BYTEA DEFAULT ''," |
@@ -87,18 +92,15 @@ database_setup (struct Plugin *plugin) | |||
87 | ")"); | 92 | ")"); |
88 | const struct GNUNET_PQ_ExecuteStatement *cr; | 93 | const struct GNUNET_PQ_ExecuteStatement *cr; |
89 | struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END; | 94 | struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END; |
90 | 95 | struct GNUNET_PQ_ExecuteStatement es_drop = | |
96 | GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS ns098records"); | ||
91 | if (GNUNET_YES == | 97 | if (GNUNET_YES == |
92 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, | 98 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, |
93 | "namestore-postgres", | 99 | "namestore-postgres", |
94 | "TEMPORARY_TABLE")) | 100 | "TEMPORARY_TABLE")) |
95 | { | ||
96 | cr = &es_temporary; | 101 | cr = &es_temporary; |
97 | } | ||
98 | else | 102 | else |
99 | { | ||
100 | cr = &es_default; | 103 | cr = &es_default; |
101 | } | ||
102 | 104 | ||
103 | if (GNUNET_YES == | 105 | if (GNUNET_YES == |
104 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, | 106 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, |
@@ -120,46 +122,134 @@ database_setup (struct Plugin *plugin) | |||
120 | sc, | 122 | sc, |
121 | GNUNET_PQ_EXECUTE_STATEMENT_END | 123 | GNUNET_PQ_EXECUTE_STATEMENT_END |
122 | }; | 124 | }; |
123 | struct GNUNET_PQ_PreparedStatement ps[] = { | 125 | struct GNUNET_PQ_ExecuteStatement es_alt[] = { |
124 | GNUNET_PQ_make_prepare ("store_records", | 126 | es_drop, |
125 | "INSERT INTO ns098records" | 127 | *cr, |
126 | " (zone_private_key, pkey, rvalue, record_count, record_data, label)" | 128 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse " |
127 | " VALUES ($1, $2, $3, $4, $5, $6)" | 129 | "ON ns098records (zone_private_key,pkey)"), |
128 | " ON CONFLICT ON CONSTRAINT zl" | 130 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter " |
129 | " DO UPDATE" | 131 | "ON ns098records (zone_private_key,seq)"), |
130 | " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5" | 132 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label " |
131 | " WHERE ns098records.zone_private_key = $1" | 133 | "ON ns098records (label)"), |
132 | " AND ns098records.label = $6", | 134 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label " |
133 | 6), | 135 | "ON ns098records (zone_private_key,label)"), |
134 | GNUNET_PQ_make_prepare ("delete_records", | 136 | sc, |
135 | "DELETE FROM ns098records " | 137 | GNUNET_PQ_EXECUTE_STATEMENT_END |
136 | "WHERE zone_private_key=$1 AND label=$2", | ||
137 | 2), | ||
138 | GNUNET_PQ_make_prepare ("zone_to_name", | ||
139 | "SELECT seq,record_count,record_data,label FROM ns098records" | ||
140 | " WHERE zone_private_key=$1 AND pkey=$2", | ||
141 | 2), | ||
142 | GNUNET_PQ_make_prepare ("iterate_zone", | ||
143 | "SELECT seq,record_count,record_data,label FROM ns098records " | ||
144 | "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3", | ||
145 | 3), | ||
146 | GNUNET_PQ_make_prepare ("iterate_all_zones", | ||
147 | "SELECT seq,record_count,record_data,label,zone_private_key" | ||
148 | " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2", | ||
149 | 2), | ||
150 | GNUNET_PQ_make_prepare ("lookup_label", | ||
151 | "SELECT seq,record_count,record_data,label " | ||
152 | "FROM ns098records WHERE zone_private_key=$1 AND label=$2", | ||
153 | 2), | ||
154 | GNUNET_PQ_PREPARED_STATEMENT_END | ||
155 | }; | 138 | }; |
139 | if (GNUNET_NO == drop) | ||
140 | { | ||
141 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
142 | "namestore-postgres", | ||
143 | NULL, | ||
144 | es, | ||
145 | NULL); | ||
146 | } | ||
147 | else { | ||
148 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
149 | "namestore-postgres", | ||
150 | NULL, | ||
151 | es_alt, | ||
152 | NULL); | ||
153 | } | ||
154 | } | ||
155 | if (NULL == plugin->dbh) | ||
156 | { | ||
157 | *emsg = GNUNET_strdup ("Failed to connect to PQ database"); | ||
158 | return GNUNET_SYSERR; | ||
159 | } | ||
160 | GNUNET_PQ_disconnect (plugin->dbh); | ||
161 | plugin->dbh = NULL; | ||
162 | return GNUNET_OK; | ||
163 | } | ||
164 | |||
165 | static int | ||
166 | database_prepare (struct Plugin *plugin) | ||
167 | { | ||
168 | enum GNUNET_GenericReturnValue ret; | ||
169 | if (GNUNET_YES == plugin->ready) | ||
170 | return GNUNET_OK; | ||
171 | struct GNUNET_PQ_PreparedStatement ps[] = { | ||
172 | GNUNET_PQ_make_prepare ("store_records", | ||
173 | "INSERT INTO ns098records" | ||
174 | " (zone_private_key, pkey, rvalue, record_count, record_data, label)" | ||
175 | " VALUES ($1, $2, $3, $4, $5, $6)" | ||
176 | " ON CONFLICT ON CONSTRAINT zl" | ||
177 | " DO UPDATE" | ||
178 | " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5" | ||
179 | " WHERE ns098records.zone_private_key = $1" | ||
180 | " AND ns098records.label = $6", | ||
181 | 6), | ||
182 | GNUNET_PQ_make_prepare ("delete_records", | ||
183 | "DELETE FROM ns098records " | ||
184 | "WHERE zone_private_key=$1 AND label=$2", | ||
185 | 2), | ||
186 | GNUNET_PQ_make_prepare ("zone_to_name", | ||
187 | "SELECT seq,record_count,record_data,label FROM ns098records" | ||
188 | " WHERE zone_private_key=$1 AND pkey=$2", | ||
189 | 2), | ||
190 | GNUNET_PQ_make_prepare ("iterate_zone", | ||
191 | "SELECT seq,record_count,record_data,label FROM ns098records " | ||
192 | "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3", | ||
193 | 3), | ||
194 | GNUNET_PQ_make_prepare ("iterate_all_zones", | ||
195 | "SELECT seq,record_count,record_data,label,zone_private_key" | ||
196 | " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2", | ||
197 | 2), | ||
198 | GNUNET_PQ_make_prepare ("lookup_label", | ||
199 | "SELECT seq,record_count,record_data,label " | ||
200 | "FROM ns098records WHERE zone_private_key=$1 AND label=$2", | ||
201 | 2), | ||
202 | GNUNET_PQ_make_prepare ("edit_set", | ||
203 | "SELECT seq,record_count,record_data,label " | ||
204 | "FROM ns098records WHERE zone_private_key=$1 AND label=$2 FOR UPDATE NOWAIT", | ||
205 | 2), | ||
206 | GNUNET_PQ_PREPARED_STATEMENT_END | ||
207 | }; | ||
208 | ret = GNUNET_PQ_prepare_statements (plugin->dbh, ps); | ||
209 | if (GNUNET_OK != ret) | ||
210 | return ret; | ||
211 | plugin->ready = GNUNET_YES; | ||
212 | return GNUNET_OK; | ||
213 | } | ||
214 | |||
215 | |||
216 | /** | ||
217 | * Initialize the database connections and associated | ||
218 | * data structures (create tables and indices | ||
219 | * as needed as well). | ||
220 | * | ||
221 | * @param plugin the plugin context (state for this module) | ||
222 | * @return #GNUNET_OK on success | ||
223 | */ | ||
224 | static int | ||
225 | database_connect (struct Plugin *plugin) | ||
226 | { | ||
227 | const struct GNUNET_PQ_ExecuteStatement *cr; | ||
228 | char *emsg; | ||
229 | struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END; | ||
156 | 230 | ||
157 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | 231 | if (GNUNET_YES == |
158 | "namestore-postgres", | 232 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, |
159 | NULL, | 233 | "namestore-postgres", |
160 | es, | 234 | "INIT_ON_CONNECT")) |
161 | ps); | 235 | { |
236 | /** | ||
237 | * Gracefully fail as this should not be a critical error if the | ||
238 | * database is already created | ||
239 | */ | ||
240 | if (GNUNET_OK != init_database (plugin, &emsg, GNUNET_NO)) | ||
241 | { | ||
242 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
243 | "Failed to initialize database on connect: `%s'\n", | ||
244 | emsg); | ||
245 | GNUNET_free (emsg); | ||
246 | } | ||
162 | } | 247 | } |
248 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
249 | "namestore-postgres", | ||
250 | NULL, | ||
251 | NULL, | ||
252 | NULL); | ||
163 | if (NULL == plugin->dbh) | 253 | if (NULL == plugin->dbh) |
164 | return GNUNET_SYSERR; | 254 | return GNUNET_SYSERR; |
165 | return GNUNET_OK; | 255 | return GNUNET_OK; |
@@ -191,6 +281,7 @@ namestore_postgres_store_records (void *cls, | |||
191 | uint32_t rd_count32 = (uint32_t) rd_count; | 281 | uint32_t rd_count32 = (uint32_t) rd_count; |
192 | ssize_t data_size; | 282 | ssize_t data_size; |
193 | 283 | ||
284 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
194 | memset (&pkey, | 285 | memset (&pkey, |
195 | 0, | 286 | 0, |
196 | sizeof(pkey)); | 287 | sizeof(pkey)); |
@@ -323,7 +414,9 @@ parse_result_call_iterator (void *cls, | |||
323 | struct ParserContext *pc = cls; | 414 | struct ParserContext *pc = cls; |
324 | 415 | ||
325 | if (NULL == pc->iter) | 416 | if (NULL == pc->iter) |
326 | return; /* no need to do more work */ | 417 | return; /* no need to do more work */ |
418 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
419 | "Got %d results from PQ.\n", num_results); | ||
327 | for (unsigned int i = 0; i < num_results; i++) | 420 | for (unsigned int i = 0; i < num_results; i++) |
328 | { | 421 | { |
329 | uint64_t serial; | 422 | uint64_t serial; |
@@ -394,7 +487,6 @@ parse_result_call_iterator (void *cls, | |||
394 | pc->limit -= num_results; | 487 | pc->limit -= num_results; |
395 | } | 488 | } |
396 | 489 | ||
397 | |||
398 | /** | 490 | /** |
399 | * Lookup records in the datastore for which we are the authority. | 491 | * Lookup records in the datastore for which we are the authority. |
400 | * | 492 | * |
@@ -403,17 +495,20 @@ parse_result_call_iterator (void *cls, | |||
403 | * @param label name of the record in the zone | 495 | * @param label name of the record in the zone |
404 | * @param iter function to call with the result | 496 | * @param iter function to call with the result |
405 | * @param iter_cls closure for @a iter | 497 | * @param iter_cls closure for @a iter |
498 | * @param method the method to use "lookup_record" or "edit_set" | ||
406 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | 499 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR |
407 | */ | 500 | */ |
408 | static int | 501 | static int |
409 | namestore_postgres_lookup_records (void *cls, | 502 | lookup_records (void *cls, |
410 | const struct | 503 | const struct |
411 | GNUNET_IDENTITY_PrivateKey *zone, | 504 | GNUNET_IDENTITY_PrivateKey *zone, |
412 | const char *label, | 505 | const char *label, |
413 | GNUNET_NAMESTORE_RecordIterator iter, | 506 | GNUNET_NAMESTORE_RecordIterator iter, |
414 | void *iter_cls) | 507 | void *iter_cls, |
508 | const char*method) | ||
415 | { | 509 | { |
416 | struct Plugin *plugin = cls; | 510 | struct Plugin *plugin = cls; |
511 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
417 | struct GNUNET_PQ_QueryParam params[] = { | 512 | struct GNUNET_PQ_QueryParam params[] = { |
418 | GNUNET_PQ_query_param_auto_from_type (zone), | 513 | GNUNET_PQ_query_param_auto_from_type (zone), |
419 | GNUNET_PQ_query_param_string (label), | 514 | GNUNET_PQ_query_param_string (label), |
@@ -431,7 +526,7 @@ namestore_postgres_lookup_records (void *cls, | |||
431 | pc.iter_cls = iter_cls; | 526 | pc.iter_cls = iter_cls; |
432 | pc.zone_key = zone; | 527 | pc.zone_key = zone; |
433 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | 528 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, |
434 | "lookup_label", | 529 | method, |
435 | params, | 530 | params, |
436 | &parse_result_call_iterator, | 531 | &parse_result_call_iterator, |
437 | &pc); | 532 | &pc); |
@@ -442,6 +537,48 @@ namestore_postgres_lookup_records (void *cls, | |||
442 | return GNUNET_OK; | 537 | return GNUNET_OK; |
443 | } | 538 | } |
444 | 539 | ||
540 | /** | ||
541 | * Lookup records in the datastore for which we are the authority. | ||
542 | * | ||
543 | * @param cls closure (internal context for the plugin) | ||
544 | * @param zone private key of the zone | ||
545 | * @param label name of the record in the zone | ||
546 | * @param iter function to call with the result | ||
547 | * @param iter_cls closure for @a iter | ||
548 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
549 | */ | ||
550 | static int | ||
551 | namestore_postgres_lookup_records (void *cls, | ||
552 | const struct | ||
553 | GNUNET_IDENTITY_PrivateKey *zone, | ||
554 | const char *label, | ||
555 | GNUNET_NAMESTORE_RecordIterator iter, | ||
556 | void *iter_cls) | ||
557 | { | ||
558 | return lookup_records (cls, zone, label, iter, iter_cls, "lookup_label"); | ||
559 | } | ||
560 | |||
561 | /** | ||
562 | * Edit records in the datastore for which we are the authority. | ||
563 | * | ||
564 | * @param cls closure (internal context for the plugin) | ||
565 | * @param zone private key of the zone | ||
566 | * @param label name of the record in the zone | ||
567 | * @param iter function to call with the result | ||
568 | * @param iter_cls closure for @a iter | ||
569 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
570 | */ | ||
571 | static int | ||
572 | namestore_postgres_edit_records (void *cls, | ||
573 | const struct | ||
574 | GNUNET_IDENTITY_PrivateKey *zone, | ||
575 | const char *label, | ||
576 | GNUNET_NAMESTORE_RecordIterator iter, | ||
577 | void *iter_cls) | ||
578 | { | ||
579 | return lookup_records (cls, zone, label, iter, iter_cls, "edit_set"); | ||
580 | } | ||
581 | |||
445 | 582 | ||
446 | /** | 583 | /** |
447 | * Iterate over the results for a particular key and zone in the | 584 | * Iterate over the results for a particular key and zone in the |
@@ -468,6 +605,7 @@ namestore_postgres_iterate_records (void *cls, | |||
468 | enum GNUNET_DB_QueryStatus res; | 605 | enum GNUNET_DB_QueryStatus res; |
469 | struct ParserContext pc; | 606 | struct ParserContext pc; |
470 | 607 | ||
608 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
471 | pc.iter = iter; | 609 | pc.iter = iter; |
472 | pc.iter_cls = iter_cls; | 610 | pc.iter_cls = iter_cls; |
473 | pc.zone_key = zone; | 611 | pc.zone_key = zone; |
@@ -532,6 +670,7 @@ namestore_postgres_zone_to_name (void *cls, | |||
532 | void *iter_cls) | 670 | void *iter_cls) |
533 | { | 671 | { |
534 | struct Plugin *plugin = cls; | 672 | struct Plugin *plugin = cls; |
673 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
535 | struct GNUNET_PQ_QueryParam params[] = { | 674 | struct GNUNET_PQ_QueryParam params[] = { |
536 | GNUNET_PQ_query_param_auto_from_type (zone), | 675 | GNUNET_PQ_query_param_auto_from_type (zone), |
537 | GNUNET_PQ_query_param_auto_from_type (value_zone), | 676 | GNUNET_PQ_query_param_auto_from_type (value_zone), |
@@ -553,6 +692,88 @@ namestore_postgres_zone_to_name (void *cls, | |||
553 | return GNUNET_OK; | 692 | return GNUNET_OK; |
554 | } | 693 | } |
555 | 694 | ||
695 | /** | ||
696 | * Begin a transaction for a client. | ||
697 | * | ||
698 | * @param cls closure (internal context for the plugin) | ||
699 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
700 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
701 | */ | ||
702 | static enum GNUNET_GenericReturnValue | ||
703 | namestore_postgres_transaction_begin (void *cls, | ||
704 | char **emsg) | ||
705 | { | ||
706 | struct Plugin *plugin = cls; | ||
707 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
708 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
709 | GNUNET_PQ_make_execute ("BEGIN"), | ||
710 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
711 | }; | ||
712 | |||
713 | return GNUNET_PQ_exec_statements (plugin->dbh, es); | ||
714 | } | ||
715 | |||
716 | /** | ||
717 | * Commit a transaction for a client. | ||
718 | * This releases the lock on the database. | ||
719 | * | ||
720 | * @param cls closure (internal context for the plugin) | ||
721 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
722 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
723 | */ | ||
724 | static enum GNUNET_GenericReturnValue | ||
725 | namestore_postgres_transaction_rollback (void *cls, | ||
726 | char **emsg) | ||
727 | { | ||
728 | struct Plugin *plugin = cls; | ||
729 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
730 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
731 | GNUNET_PQ_make_execute ("ROLLBACK"), | ||
732 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
733 | }; | ||
734 | |||
735 | return GNUNET_PQ_exec_statements (plugin->dbh, es); | ||
736 | } | ||
737 | |||
738 | /** | ||
739 | * Roll back a transaction for a client. | ||
740 | * This releases the lock on the database. | ||
741 | * | ||
742 | * @param cls closure (internal context for the plugin) | ||
743 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
744 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
745 | */ | ||
746 | static enum GNUNET_GenericReturnValue | ||
747 | namestore_postgres_transaction_commit (void *cls, | ||
748 | char **emsg) | ||
749 | { | ||
750 | struct Plugin *plugin = cls; | ||
751 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
752 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
753 | GNUNET_PQ_make_execute ("COMMIT"), | ||
754 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
755 | }; | ||
756 | |||
757 | return GNUNET_PQ_exec_statements (plugin->dbh, es); | ||
758 | } | ||
759 | |||
760 | |||
761 | static enum GNUNET_GenericReturnValue | ||
762 | namestore_postgres_initialize_database (void *cls, | ||
763 | char **emsg) | ||
764 | { | ||
765 | return init_database (cls, emsg, GNUNET_NO); | ||
766 | } | ||
767 | |||
768 | |||
769 | static enum GNUNET_GenericReturnValue | ||
770 | namestore_postgres_reset_database (void *cls, | ||
771 | char **emsg) | ||
772 | { | ||
773 | return init_database (cls, emsg, GNUNET_YES); | ||
774 | } | ||
775 | |||
776 | |||
556 | 777 | ||
557 | /** | 778 | /** |
558 | * Shutdown database connection and associate data | 779 | * Shutdown database connection and associate data |
@@ -577,25 +798,30 @@ database_shutdown (struct Plugin *plugin) | |||
577 | void * | 798 | void * |
578 | libgnunet_plugin_namestore_postgres_init (void *cls) | 799 | libgnunet_plugin_namestore_postgres_init (void *cls) |
579 | { | 800 | { |
580 | static struct Plugin plugin; | 801 | struct Plugin *plugin; |
581 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | 802 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; |
582 | struct GNUNET_NAMESTORE_PluginFunctions *api; | 803 | struct GNUNET_NAMESTORE_PluginFunctions *api; |
583 | 804 | ||
584 | if (NULL != plugin.cfg) | 805 | plugin = GNUNET_new (struct Plugin); |
585 | return NULL; /* can only initialize once! */ | 806 | plugin->cfg = cfg; |
586 | memset (&plugin, 0, sizeof(struct Plugin)); | 807 | if (GNUNET_OK != database_connect (plugin)) |
587 | plugin.cfg = cfg; | ||
588 | if (GNUNET_OK != database_setup (&plugin)) | ||
589 | { | 808 | { |
590 | database_shutdown (&plugin); | 809 | database_shutdown (plugin); |
810 | GNUNET_free (plugin); | ||
591 | return NULL; | 811 | return NULL; |
592 | } | 812 | } |
593 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); | 813 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); |
594 | api->cls = &plugin; | 814 | api->cls = plugin; |
595 | api->store_records = &namestore_postgres_store_records; | 815 | api->store_records = &namestore_postgres_store_records; |
596 | api->iterate_records = &namestore_postgres_iterate_records; | 816 | api->iterate_records = &namestore_postgres_iterate_records; |
597 | api->zone_to_name = &namestore_postgres_zone_to_name; | 817 | api->zone_to_name = &namestore_postgres_zone_to_name; |
598 | api->lookup_records = &namestore_postgres_lookup_records; | 818 | api->lookup_records = &namestore_postgres_lookup_records; |
819 | api->transaction_begin = &namestore_postgres_transaction_begin; | ||
820 | api->transaction_commit = &namestore_postgres_transaction_commit; | ||
821 | api->transaction_rollback = &namestore_postgres_transaction_rollback; | ||
822 | api->initialize_database = &namestore_postgres_initialize_database; | ||
823 | api->reset_database = &namestore_postgres_reset_database; | ||
824 | api->edit_records = &namestore_postgres_edit_records; | ||
599 | LOG (GNUNET_ERROR_TYPE_INFO, | 825 | LOG (GNUNET_ERROR_TYPE_INFO, |
600 | "Postgres namestore plugin running\n"); | 826 | "Postgres namestore plugin running\n"); |
601 | return api; | 827 | return api; |
@@ -616,6 +842,7 @@ libgnunet_plugin_namestore_postgres_done (void *cls) | |||
616 | 842 | ||
617 | database_shutdown (plugin); | 843 | database_shutdown (plugin); |
618 | plugin->cfg = NULL; | 844 | plugin->cfg = NULL; |
845 | GNUNET_free (plugin); | ||
619 | GNUNET_free (api); | 846 | GNUNET_free (api); |
620 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 847 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
621 | "Postgres namestore plugin is finished\n"); | 848 | "Postgres namestore plugin is finished\n"); |
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c index 0b3aac84f..35fd340ab 100644 --- a/src/namestore/plugin_namestore_sqlite.c +++ b/src/namestore/plugin_namestore_sqlite.c | |||
@@ -75,6 +75,11 @@ struct Plugin | |||
75 | char *fn; | 75 | char *fn; |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * Statements prepared, we are ready to go if GNUNET_YES | ||
79 | */ | ||
80 | int ready; | ||
81 | |||
82 | /** | ||
78 | * Native SQLite database handle. | 83 | * Native SQLite database handle. |
79 | */ | 84 | */ |
80 | sqlite3 *dbh; | 85 | sqlite3 *dbh; |
@@ -120,31 +125,19 @@ struct Plugin | |||
120 | * @return #GNUNET_OK on success | 125 | * @return #GNUNET_OK on success |
121 | */ | 126 | */ |
122 | static int | 127 | static int |
123 | database_setup (struct Plugin *plugin) | 128 | database_prepare (struct Plugin *plugin) |
124 | { | 129 | { |
125 | char *sqlite_filename; | 130 | if (GNUNET_YES == plugin->ready) |
131 | return GNUNET_OK; | ||
126 | struct GNUNET_SQ_ExecuteStatement es[] = { | 132 | struct GNUNET_SQ_ExecuteStatement es[] = { |
127 | GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"), | 133 | GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"), |
128 | GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"), | 134 | GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"), |
129 | GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"), | 135 | GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"), |
130 | GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"), | 136 | GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"), |
131 | GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""), | 137 | GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""), |
132 | GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=EXCLUSIVE"), | 138 | GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"), |
133 | GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"), | 139 | GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"), |
134 | GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"), | 140 | GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"), |
135 | GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records (" | ||
136 | " uid INTEGER PRIMARY KEY," | ||
137 | " zone_private_key BLOB NOT NULL," | ||
138 | " pkey BLOB," | ||
139 | " rvalue INT8 NOT NULL," | ||
140 | " record_count INT NOT NULL," | ||
141 | " record_data BLOB NOT NULL," | ||
142 | " label TEXT NOT NULL" | ||
143 | ")"), | ||
144 | GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse " | ||
145 | "ON ns098records (zone_private_key,pkey)"), | ||
146 | GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter " | ||
147 | "ON ns098records (zone_private_key,uid)"), | ||
148 | GNUNET_SQ_EXECUTE_STATEMENT_END | 141 | GNUNET_SQ_EXECUTE_STATEMENT_END |
149 | }; | 142 | }; |
150 | struct GNUNET_SQ_PrepareStatement ps[] = { | 143 | struct GNUNET_SQ_PrepareStatement ps[] = { |
@@ -180,64 +173,25 @@ database_setup (struct Plugin *plugin) | |||
180 | }; | 173 | }; |
181 | 174 | ||
182 | if (GNUNET_OK != | 175 | if (GNUNET_OK != |
183 | GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, | ||
184 | "namestore-sqlite", | ||
185 | "FILENAME", | ||
186 | &sqlite_filename)) | ||
187 | { | ||
188 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
189 | "namestore-sqlite", | ||
190 | "FILENAME"); | ||
191 | return GNUNET_SYSERR; | ||
192 | } | ||
193 | if (GNUNET_OK != | ||
194 | GNUNET_DISK_file_test (sqlite_filename)) | ||
195 | { | ||
196 | if (GNUNET_OK != | ||
197 | GNUNET_DISK_directory_create_for_file (sqlite_filename)) | ||
198 | { | ||
199 | GNUNET_break (0); | ||
200 | GNUNET_free (sqlite_filename); | ||
201 | return GNUNET_SYSERR; | ||
202 | } | ||
203 | } | ||
204 | /* sqlite_filename should be UTF-8-encoded. If it isn't, it's a bug */ | ||
205 | plugin->fn = sqlite_filename; | ||
206 | |||
207 | /* Open database and precompile statements */ | ||
208 | if (SQLITE_OK != | ||
209 | sqlite3_open (plugin->fn, | ||
210 | &plugin->dbh)) | ||
211 | { | ||
212 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
213 | _ ("Unable to initialize SQLite: %s.\n"), | ||
214 | sqlite3_errmsg (plugin->dbh)); | ||
215 | return GNUNET_SYSERR; | ||
216 | } | ||
217 | GNUNET_break (SQLITE_OK == | ||
218 | sqlite3_busy_timeout (plugin->dbh, | ||
219 | BUSY_TIMEOUT_MS)); | ||
220 | if (GNUNET_OK != | ||
221 | GNUNET_SQ_exec_statements (plugin->dbh, | 176 | GNUNET_SQ_exec_statements (plugin->dbh, |
222 | es)) | 177 | es)) |
223 | { | 178 | { |
224 | GNUNET_break (0); | ||
225 | LOG (GNUNET_ERROR_TYPE_ERROR, | 179 | LOG (GNUNET_ERROR_TYPE_ERROR, |
226 | _ ("Failed to setup database at `%s'\n"), | 180 | _("Failed to setup database with: `%s'\n"), |
227 | plugin->fn); | 181 | sqlite3_errmsg (plugin->dbh)); |
228 | return GNUNET_SYSERR; | 182 | return GNUNET_SYSERR; |
229 | } | 183 | } |
230 | |||
231 | if (GNUNET_OK != | 184 | if (GNUNET_OK != |
232 | GNUNET_SQ_prepare (plugin->dbh, | 185 | GNUNET_SQ_prepare (plugin->dbh, |
233 | ps)) | 186 | ps)) |
234 | { | 187 | { |
235 | GNUNET_break (0); | 188 | GNUNET_break (0); |
236 | LOG (GNUNET_ERROR_TYPE_ERROR, | 189 | LOG (GNUNET_ERROR_TYPE_ERROR, |
237 | _ ("Failed to setup database at `%s'\n"), | 190 | _ ("Failed to setup database with: `%s'\n"), |
238 | plugin->fn); | 191 | sqlite3_errmsg (plugin->dbh)); |
239 | return GNUNET_SYSERR; | 192 | return GNUNET_SYSERR; |
240 | } | 193 | } |
194 | plugin->ready = GNUNET_YES; | ||
241 | return GNUNET_OK; | 195 | return GNUNET_OK; |
242 | } | 196 | } |
243 | 197 | ||
@@ -296,7 +250,6 @@ database_shutdown (struct Plugin *plugin) | |||
296 | GNUNET_ERROR_TYPE_ERROR, | 250 | GNUNET_ERROR_TYPE_ERROR, |
297 | "sqlite3_close"); | 251 | "sqlite3_close"); |
298 | 252 | ||
299 | GNUNET_free (plugin->fn); | ||
300 | } | 253 | } |
301 | 254 | ||
302 | 255 | ||
@@ -325,14 +278,15 @@ namestore_sqlite_store_records (void *cls, | |||
325 | uint64_t rvalue; | 278 | uint64_t rvalue; |
326 | ssize_t data_size; | 279 | ssize_t data_size; |
327 | 280 | ||
281 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
328 | memset (&pkey, | 282 | memset (&pkey, |
329 | 0, | 283 | 0, |
330 | sizeof(pkey)); | 284 | sizeof(pkey)); |
331 | for (unsigned int i = 0; i < rd_count; i++) | 285 | for (unsigned int i = 0; i < rd_count; i++) |
332 | { | 286 | { |
333 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 287 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
334 | "Checking if `%d' is zonekey type\n", | 288 | "Checking if `%d' is zonekey type\n", |
335 | rd[i].record_type); | 289 | rd[i].record_type); |
336 | 290 | ||
337 | if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) | 291 | if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) |
338 | { | 292 | { |
@@ -342,8 +296,8 @@ namestore_sqlite_store_records (void *cls, | |||
342 | rd[i].record_type, | 296 | rd[i].record_type, |
343 | &pkey)); | 297 | &pkey)); |
344 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 298 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
345 | "Storing delegation zone record value `%s'\n", | 299 | "Storing delegation zone record value `%s'\n", |
346 | GNUNET_GNSRECORD_z2s (&pkey)); | 300 | GNUNET_GNSRECORD_z2s (&pkey)); |
347 | 301 | ||
348 | break; | 302 | break; |
349 | } | 303 | } |
@@ -594,6 +548,7 @@ namestore_sqlite_lookup_records (void *cls, | |||
594 | void *iter_cls) | 548 | void *iter_cls) |
595 | { | 549 | { |
596 | struct Plugin *plugin = cls; | 550 | struct Plugin *plugin = cls; |
551 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
597 | struct GNUNET_SQ_QueryParam params[] = { | 552 | struct GNUNET_SQ_QueryParam params[] = { |
598 | GNUNET_SQ_query_param_auto_from_type (zone), | 553 | GNUNET_SQ_query_param_auto_from_type (zone), |
599 | GNUNET_SQ_query_param_string (label), | 554 | GNUNET_SQ_query_param_string (label), |
@@ -649,6 +604,7 @@ namestore_sqlite_iterate_records (void *cls, | |||
649 | sqlite3_stmt *stmt; | 604 | sqlite3_stmt *stmt; |
650 | int err; | 605 | int err; |
651 | 606 | ||
607 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
652 | if (NULL == zone) | 608 | if (NULL == zone) |
653 | { | 609 | { |
654 | struct GNUNET_SQ_QueryParam params[] = { | 610 | struct GNUNET_SQ_QueryParam params[] = { |
@@ -712,6 +668,7 @@ namestore_sqlite_zone_to_name (void *cls, | |||
712 | void *iter_cls) | 668 | void *iter_cls) |
713 | { | 669 | { |
714 | struct Plugin *plugin = cls; | 670 | struct Plugin *plugin = cls; |
671 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
715 | struct GNUNET_SQ_QueryParam params[] = { | 672 | struct GNUNET_SQ_QueryParam params[] = { |
716 | GNUNET_SQ_query_param_auto_from_type (zone), | 673 | GNUNET_SQ_query_param_auto_from_type (zone), |
717 | GNUNET_SQ_query_param_auto_from_type (value_zone), | 674 | GNUNET_SQ_query_param_auto_from_type (value_zone), |
@@ -740,6 +697,204 @@ namestore_sqlite_zone_to_name (void *cls, | |||
740 | iter_cls); | 697 | iter_cls); |
741 | } | 698 | } |
742 | 699 | ||
700 | /** | ||
701 | * Begin a transaction for a client. | ||
702 | * This locks the database. SQLite is unable to discern between different | ||
703 | * rows with a specific zone key but the API looks like this anyway. | ||
704 | * https://www.sqlite.org/lang_transaction.html | ||
705 | * | ||
706 | * @param cls closure (internal context for the plugin) | ||
707 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
708 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
709 | */ | ||
710 | static enum GNUNET_GenericReturnValue | ||
711 | namestore_sqlite_transaction_begin (void *cls, | ||
712 | char **emsg) | ||
713 | { | ||
714 | struct Plugin *plugin = cls; | ||
715 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
716 | return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, | ||
717 | "BEGIN IMMEDIATE TRANSACTION;", NULL, | ||
718 | NULL, emsg)) ? GNUNET_SYSERR : | ||
719 | GNUNET_YES; | ||
720 | } | ||
721 | |||
722 | /** | ||
723 | * Commit a transaction for a client. | ||
724 | * This releases the lock on the database. | ||
725 | * | ||
726 | * @param cls closure (internal context for the plugin) | ||
727 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
728 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
729 | */ | ||
730 | static enum GNUNET_GenericReturnValue | ||
731 | namestore_sqlite_transaction_rollback (void *cls, | ||
732 | char **emsg) | ||
733 | { | ||
734 | struct Plugin *plugin = cls; | ||
735 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
736 | return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "ROLLBACK;", NULL, | ||
737 | NULL, emsg)) ? GNUNET_SYSERR : | ||
738 | GNUNET_YES; | ||
739 | } | ||
740 | |||
741 | /** | ||
742 | * Roll back a transaction for a client. | ||
743 | * This releases the lock on the database. | ||
744 | * | ||
745 | * @param cls closure (internal context for the plugin) | ||
746 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
747 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
748 | */ | ||
749 | static enum GNUNET_GenericReturnValue | ||
750 | namestore_sqlite_transaction_commit (void *cls, | ||
751 | char **emsg) | ||
752 | { | ||
753 | struct Plugin *plugin = cls; | ||
754 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
755 | return (SQLITE_BUSY == sqlite3_exec (plugin->dbh, "END TRANSACTION;", NULL, | ||
756 | NULL, emsg)) ? GNUNET_SYSERR : | ||
757 | GNUNET_YES; | ||
758 | } | ||
759 | |||
760 | static enum GNUNET_GenericReturnValue | ||
761 | init_database (void *cls, char **emsg, int drop) | ||
762 | { | ||
763 | struct Plugin *plugin = cls; | ||
764 | struct GNUNET_SQ_ExecuteStatement es_drop[] = { | ||
765 | GNUNET_SQ_make_execute ("DROP TABLE IF EXISTS ns098records"), | ||
766 | GNUNET_SQ_EXECUTE_STATEMENT_END | ||
767 | }; | ||
768 | struct GNUNET_SQ_ExecuteStatement es[] = { | ||
769 | GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"), | ||
770 | GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"), | ||
771 | GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"), | ||
772 | GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"), | ||
773 | GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""), | ||
774 | GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"), | ||
775 | GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"), | ||
776 | GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"), | ||
777 | GNUNET_SQ_make_execute ("CREATE TABLE ns098records (" | ||
778 | " uid INTEGER PRIMARY KEY," | ||
779 | " zone_private_key BLOB NOT NULL," | ||
780 | " pkey BLOB," | ||
781 | " rvalue INT8 NOT NULL," | ||
782 | " record_count INT NOT NULL," | ||
783 | " record_data BLOB NOT NULL," | ||
784 | " label TEXT NOT NULL" | ||
785 | ")"), | ||
786 | GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_reverse " | ||
787 | "ON ns098records (zone_private_key,pkey)"), | ||
788 | GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_iter " | ||
789 | "ON ns098records (zone_private_key,uid)"), | ||
790 | GNUNET_SQ_EXECUTE_STATEMENT_END | ||
791 | }; | ||
792 | if ((GNUNET_YES == drop) && | ||
793 | (GNUNET_OK != GNUNET_SQ_exec_statements (plugin->dbh, | ||
794 | es_drop))) | ||
795 | { | ||
796 | GNUNET_asprintf (emsg, | ||
797 | _ ("Failed to drop database with: `%s'\n"), | ||
798 | sqlite3_errmsg (plugin->dbh)); | ||
799 | return GNUNET_SYSERR; | ||
800 | } | ||
801 | if (GNUNET_OK != | ||
802 | GNUNET_SQ_exec_statements (plugin->dbh, | ||
803 | es)) | ||
804 | { | ||
805 | GNUNET_asprintf (emsg, | ||
806 | _ ("Failed to setup database with: `%s'\n"), | ||
807 | sqlite3_errmsg (plugin->dbh)); | ||
808 | return GNUNET_SYSERR; | ||
809 | } | ||
810 | return GNUNET_OK; | ||
811 | } | ||
812 | |||
813 | enum GNUNET_GenericReturnValue | ||
814 | namestore_sqlite_initialize_database (void *cls, char **emsg) | ||
815 | { | ||
816 | return init_database (cls, emsg, GNUNET_NO); | ||
817 | } | ||
818 | |||
819 | enum GNUNET_GenericReturnValue | ||
820 | namestore_sqlite_reset_database (void *cls, char **emsg) | ||
821 | { | ||
822 | return init_database (cls, emsg, GNUNET_YES); | ||
823 | } | ||
824 | |||
825 | /** | ||
826 | * Initialize the database connections and associated | ||
827 | * data structures (create tables and indices | ||
828 | * as needed as well). | ||
829 | * | ||
830 | * @param plugin the plugin context (state for this module) | ||
831 | * @return #GNUNET_OK on success | ||
832 | */ | ||
833 | static int | ||
834 | database_connect (struct Plugin *plugin) | ||
835 | { | ||
836 | char *sqlite_filename; | ||
837 | char *emsg; | ||
838 | int try_create = GNUNET_NO; | ||
839 | |||
840 | if (GNUNET_OK != | ||
841 | GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, | ||
842 | "namestore-sqlite", | ||
843 | "FILENAME", | ||
844 | &sqlite_filename)) | ||
845 | { | ||
846 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
847 | "namestore-sqlite", | ||
848 | "FILENAME"); | ||
849 | return GNUNET_SYSERR; | ||
850 | } | ||
851 | if (GNUNET_OK != | ||
852 | GNUNET_DISK_file_test (sqlite_filename)) | ||
853 | { | ||
854 | if (GNUNET_OK != | ||
855 | GNUNET_DISK_directory_create_for_file (sqlite_filename)) | ||
856 | { | ||
857 | GNUNET_break (0); | ||
858 | GNUNET_free (sqlite_filename); | ||
859 | return GNUNET_SYSERR; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | /* Open database and precompile statements */ | ||
864 | if ((NULL == plugin->dbh) && | ||
865 | (SQLITE_OK != sqlite3_open (sqlite_filename, | ||
866 | &plugin->dbh))) | ||
867 | { | ||
868 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
869 | _ ("Unable to initialize SQLite: %s.\n"), | ||
870 | sqlite3_errmsg (plugin->dbh)); | ||
871 | GNUNET_free (sqlite_filename); | ||
872 | return GNUNET_SYSERR; | ||
873 | } | ||
874 | GNUNET_free (sqlite_filename); | ||
875 | GNUNET_break (SQLITE_OK == | ||
876 | sqlite3_busy_timeout (plugin->dbh, | ||
877 | BUSY_TIMEOUT_MS)); | ||
878 | if (GNUNET_YES == | ||
879 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, | ||
880 | "namestore-sqlite", | ||
881 | "INIT_ON_CONNECT")) | ||
882 | { | ||
883 | /** | ||
884 | * Gracefully fail as this should not be a critical error if the | ||
885 | * database is already created | ||
886 | */ | ||
887 | if (GNUNET_OK != init_database (plugin, &emsg, GNUNET_NO)) | ||
888 | { | ||
889 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
890 | "Failed to initialize database on connect: `%s'\n", | ||
891 | emsg); | ||
892 | GNUNET_free (emsg); | ||
893 | } | ||
894 | } | ||
895 | return GNUNET_OK; | ||
896 | } | ||
897 | |||
743 | 898 | ||
744 | /** | 899 | /** |
745 | * Entry point for the plugin. | 900 | * Entry point for the plugin. |
@@ -750,29 +905,38 @@ namestore_sqlite_zone_to_name (void *cls, | |||
750 | void * | 905 | void * |
751 | libgnunet_plugin_namestore_sqlite_init (void *cls) | 906 | libgnunet_plugin_namestore_sqlite_init (void *cls) |
752 | { | 907 | { |
753 | static struct Plugin plugin; | 908 | struct Plugin *plugin; |
754 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | 909 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; |
755 | struct GNUNET_NAMESTORE_PluginFunctions *api; | 910 | struct GNUNET_NAMESTORE_PluginFunctions *api; |
756 | 911 | ||
757 | if (NULL != plugin.cfg) | 912 | plugin = GNUNET_new (struct Plugin); |
758 | return NULL; /* can only initialize once! */ | 913 | plugin->cfg = cfg; |
759 | memset (&plugin, | 914 | if (GNUNET_OK != database_connect (plugin)) |
760 | 0, | ||
761 | sizeof(struct Plugin)); | ||
762 | plugin.cfg = cfg; | ||
763 | if (GNUNET_OK != database_setup (&plugin)) | ||
764 | { | 915 | { |
765 | database_shutdown (&plugin); | 916 | LOG (GNUNET_ERROR_TYPE_ERROR, |
917 | "Database could not be connected to.\n"); | ||
918 | GNUNET_free (plugin); | ||
766 | return NULL; | 919 | return NULL; |
767 | } | 920 | } |
768 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); | 921 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); |
769 | api->cls = &plugin; | 922 | api->cls = plugin; |
770 | api->store_records = &namestore_sqlite_store_records; | 923 | api->store_records = &namestore_sqlite_store_records; |
771 | api->iterate_records = &namestore_sqlite_iterate_records; | 924 | api->iterate_records = &namestore_sqlite_iterate_records; |
772 | api->zone_to_name = &namestore_sqlite_zone_to_name; | 925 | api->zone_to_name = &namestore_sqlite_zone_to_name; |
773 | api->lookup_records = &namestore_sqlite_lookup_records; | 926 | api->lookup_records = &namestore_sqlite_lookup_records; |
774 | LOG (GNUNET_ERROR_TYPE_INFO, | 927 | api->transaction_begin = &namestore_sqlite_transaction_begin; |
775 | _ ("Sqlite database running\n")); | 928 | api->transaction_commit = &namestore_sqlite_transaction_commit; |
929 | api->transaction_rollback = &namestore_sqlite_transaction_rollback; | ||
930 | api->initialize_database = &namestore_sqlite_initialize_database; | ||
931 | api->reset_database = &namestore_sqlite_reset_database; | ||
932 | /** | ||
933 | * NOTE: Since SQlite does not support SELECT ... FOR UPDATE this is | ||
934 | * just an alias to lookup_records. The BEGIN IMMEDIATE mechanic currently | ||
935 | * implicitly ensures this API behaves as it should | ||
936 | */ | ||
937 | api->edit_records = &namestore_sqlite_lookup_records; | ||
938 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
939 | _ ("SQlite database running\n")); | ||
776 | return api; | 940 | return api; |
777 | } | 941 | } |
778 | 942 | ||
@@ -791,9 +955,10 @@ libgnunet_plugin_namestore_sqlite_done (void *cls) | |||
791 | 955 | ||
792 | database_shutdown (plugin); | 956 | database_shutdown (plugin); |
793 | plugin->cfg = NULL; | 957 | plugin->cfg = NULL; |
958 | GNUNET_free (plugin); | ||
794 | GNUNET_free (api); | 959 | GNUNET_free (api); |
795 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 960 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
796 | "sqlite plugin is finished\n"); | 961 | "SQlite plugin is finished\n"); |
797 | return NULL; | 962 | return NULL; |
798 | } | 963 | } |
799 | 964 | ||
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index 0475960eb..0eef1aaeb 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c | |||
@@ -721,6 +721,148 @@ ns_lookup_cb (void *cls, | |||
721 | } | 721 | } |
722 | } | 722 | } |
723 | 723 | ||
724 | /** | ||
725 | * Import callback | ||
726 | * | ||
727 | * @param cls the `struct RequestHandle` | ||
728 | * @param success the success indicating integer, GNUNET_OK on success | ||
729 | * @param emsg the error message (can be NULL) | ||
730 | */ | ||
731 | static void | ||
732 | import_finished_cb (void *cls, int32_t success, const char *emsg) | ||
733 | { | ||
734 | struct RequestHandle *handle = cls; | ||
735 | struct MHD_Response *resp; | ||
736 | |||
737 | handle->ns_qe = NULL; | ||
738 | if (GNUNET_YES != success) | ||
739 | { | ||
740 | if (NULL != emsg) | ||
741 | { | ||
742 | handle->emsg = GNUNET_strdup (emsg); | ||
743 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
744 | return; | ||
745 | } | ||
746 | handle->emsg = GNUNET_strdup ("Error importing records"); | ||
747 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
748 | return; | ||
749 | } | ||
750 | resp = GNUNET_REST_create_response (NULL); | ||
751 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); | ||
752 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
753 | } | ||
754 | |||
755 | |||
756 | /** | ||
757 | * Handle namestore POST import | ||
758 | * | ||
759 | * @param con_handle the connection handle | ||
760 | * @param url the url | ||
761 | * @param cls the RequestHandle | ||
762 | */ | ||
763 | void | ||
764 | namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | ||
765 | const char *url, | ||
766 | void *cls) | ||
767 | { | ||
768 | struct RequestHandle *handle = cls; | ||
769 | struct EgoEntry *ego_entry; | ||
770 | char *egoname; | ||
771 | json_t *data_js; | ||
772 | json_error_t err; | ||
773 | |||
774 | char term_data[handle->rest_handle->data_size + 1]; | ||
775 | // set zone to name if given | ||
776 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | ||
777 | { | ||
778 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
779 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
780 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
781 | return; | ||
782 | } | ||
783 | ego_entry = NULL; | ||
784 | |||
785 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
786 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
787 | |||
788 | if (NULL == ego_entry) | ||
789 | { | ||
790 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
791 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
792 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
793 | return; | ||
794 | } | ||
795 | |||
796 | if (0 >= handle->rest_handle->data_size) | ||
797 | { | ||
798 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
799 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DATA); | ||
800 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
801 | return; | ||
802 | } | ||
803 | term_data[handle->rest_handle->data_size] = '\0'; | ||
804 | GNUNET_memcpy (term_data, | ||
805 | handle->rest_handle->data, | ||
806 | handle->rest_handle->data_size); | ||
807 | data_js = json_loads (term_data, JSON_DECODE_ANY, &err); | ||
808 | if (NULL == data_js) | ||
809 | { | ||
810 | GNUNET_asprintf (&handle->emsg, "Error parsing data: %s", err.text); | ||
811 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
812 | return; | ||
813 | } | ||
814 | if (! json_is_array (data_js)) | ||
815 | { | ||
816 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA); | ||
817 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
818 | json_decref (data_js); | ||
819 | return; | ||
820 | } | ||
821 | size_t rd_set_count = json_array_size (data_js); | ||
822 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
823 | "Got record set of size %d\n", rd_set_count); | ||
824 | const struct GNUNET_GNSRECORD_Data *a_rd[rd_set_count]; | ||
825 | unsigned int a_rd_count[rd_set_count]; | ||
826 | char *a_label[rd_set_count]; | ||
827 | size_t index; | ||
828 | json_t *value; | ||
829 | json_array_foreach (data_js, index, value) { | ||
830 | { | ||
831 | struct GNUNET_GNSRECORD_Data *rd; | ||
832 | struct GNUNET_JSON_Specification gnsspec[] = | ||
833 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&rd, &a_rd_count[index], | ||
834 | &a_label[index]), | ||
835 | GNUNET_JSON_spec_end () }; | ||
836 | if (GNUNET_OK != GNUNET_JSON_parse (value, gnsspec, NULL, NULL)) | ||
837 | { | ||
838 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA); | ||
839 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
840 | json_decref (data_js); | ||
841 | return; | ||
842 | } | ||
843 | a_rd[index] = rd; | ||
844 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
845 | "Parsed record set for name %s\n", a_label[index]); | ||
846 | } | ||
847 | } | ||
848 | //json_decref (data_js); | ||
849 | |||
850 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
851 | handle->ns_qe = GNUNET_NAMESTORE_records_store2 (ns_handle, | ||
852 | handle->zone_pkey, | ||
853 | rd_set_count, | ||
854 | (const char**) a_label, | ||
855 | a_rd_count, | ||
856 | a_rd, | ||
857 | &import_finished_cb, | ||
858 | handle); | ||
859 | if (NULL == handle->ns_qe) | ||
860 | { | ||
861 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
862 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
863 | return; | ||
864 | } | ||
865 | } | ||
724 | 866 | ||
725 | /** | 867 | /** |
726 | * Handle namestore POST/PUT request | 868 | * Handle namestore POST/PUT request |
@@ -756,7 +898,7 @@ namestore_add_or_update (struct GNUNET_REST_RequestHandle *con_handle, | |||
756 | data_js = json_loads (term_data, JSON_DECODE_ANY, &err); | 898 | data_js = json_loads (term_data, JSON_DECODE_ANY, &err); |
757 | struct GNUNET_JSON_Specification gnsspec[] = | 899 | struct GNUNET_JSON_Specification gnsspec[] = |
758 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count, | 900 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count, |
759 | &handle->record_name), | 901 | &handle->record_name), |
760 | GNUNET_JSON_spec_end () }; | 902 | GNUNET_JSON_spec_end () }; |
761 | if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)) | 903 | if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)) |
762 | { | 904 | { |
@@ -932,7 +1074,8 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
932 | 1074 | ||
933 | // independent of path return all options | 1075 | // independent of path return all options |
934 | resp = GNUNET_REST_create_response (NULL); | 1076 | resp = GNUNET_REST_create_response (NULL); |
935 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); | 1077 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", |
1078 | allow_methods); | ||
936 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | 1079 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); |
937 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | 1080 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
938 | return; | 1081 | return; |
@@ -1007,7 +1150,7 @@ list_ego (void *cls, | |||
1007 | break; | 1150 | break; |
1008 | } | 1151 | } |
1009 | if (NULL == ego_entry) | 1152 | if (NULL == ego_entry) |
1010 | return; /* Not found */ | 1153 | return; /* Not found */ |
1011 | 1154 | ||
1012 | GNUNET_CONTAINER_DLL_remove (ego_head, | 1155 | GNUNET_CONTAINER_DLL_remove (ego_head, |
1013 | ego_tail, | 1156 | ego_tail, |
@@ -1041,9 +1184,11 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | |||
1041 | struct GNUNET_REST_RequestHandlerError err; | 1184 | struct GNUNET_REST_RequestHandlerError err; |
1042 | static const struct GNUNET_REST_RequestHandler handlers[] = | 1185 | static const struct GNUNET_REST_RequestHandler handlers[] = |
1043 | { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get }, | 1186 | { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get }, |
1044 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add }, | 1187 | //{ MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add }, |
1188 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_import }, | ||
1045 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update }, | 1189 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update }, |
1046 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete }, | 1190 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, |
1191 | &namestore_delete }, | ||
1047 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont }, | 1192 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont }, |
1048 | GNUNET_REST_HANDLER_END }; | 1193 | GNUNET_REST_HANDLER_END }; |
1049 | 1194 | ||
@@ -1063,7 +1208,8 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | |||
1063 | handle); | 1208 | handle); |
1064 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); | 1209 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); |
1065 | if (GNUNET_NO == | 1210 | if (GNUNET_NO == |
1066 | GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) | 1211 | GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, |
1212 | handle)) | ||
1067 | { | 1213 | { |
1068 | cleanup_handle (handle); | 1214 | cleanup_handle (handle); |
1069 | return GNUNET_NO; | 1215 | return GNUNET_NO; |
@@ -1088,7 +1234,7 @@ libgnunet_plugin_rest_namestore_init (void *cls) | |||
1088 | 1234 | ||
1089 | cfg = cls; | 1235 | cfg = cls; |
1090 | if (NULL != plugin.cfg) | 1236 | if (NULL != plugin.cfg) |
1091 | return NULL; /* can only initialize once! */ | 1237 | return NULL; /* can only initialize once! */ |
1092 | memset (&plugin, 0, sizeof(struct Plugin)); | 1238 | memset (&plugin, 0, sizeof(struct Plugin)); |
1093 | plugin.cfg = cfg; | 1239 | plugin.cfg = cfg; |
1094 | api = GNUNET_new (struct GNUNET_REST_Plugin); | 1240 | api = GNUNET_new (struct GNUNET_REST_Plugin); |
@@ -1106,7 +1252,8 @@ libgnunet_plugin_rest_namestore_init (void *cls) | |||
1106 | ns_handle = GNUNET_NAMESTORE_connect (cfg); | 1252 | ns_handle = GNUNET_NAMESTORE_connect (cfg); |
1107 | identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); | 1253 | identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); |
1108 | 1254 | ||
1109 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Namestore REST API initialized\n")); | 1255 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ( |
1256 | "Namestore REST API initialized\n")); | ||
1110 | return api; | 1257 | return api; |
1111 | } | 1258 | } |
1112 | 1259 | ||
diff --git a/src/namestore/test_common.c b/src/namestore/test_common.c index 58afb0a32..24a88c180 100644 --- a/src/namestore/test_common.c +++ b/src/namestore/test_common.c | |||
@@ -21,6 +21,7 @@ | |||
21 | * @file namestore/test_common.c | 21 | * @file namestore/test_common.c |
22 | * @brief common functions for testcase setup | 22 | * @brief common functions for testcase setup |
23 | */ | 23 | */ |
24 | #include <gnunet_namestore_plugin.h> | ||
24 | 25 | ||
25 | /** | 26 | /** |
26 | * test if we can load the plugin @a name. | 27 | * test if we can load the plugin @a name. |
@@ -30,6 +31,7 @@ TNC_test_plugin (const char *cfg_name) | |||
30 | { | 31 | { |
31 | char *database; | 32 | char *database; |
32 | char *db_lib_name; | 33 | char *db_lib_name; |
34 | char *emsg; | ||
33 | struct GNUNET_NAMESTORE_PluginFunctions *db; | 35 | struct GNUNET_NAMESTORE_PluginFunctions *db; |
34 | struct GNUNET_CONFIGURATION_Handle *cfg; | 36 | struct GNUNET_CONFIGURATION_Handle *cfg; |
35 | 37 | ||
@@ -53,7 +55,15 @@ TNC_test_plugin (const char *cfg_name) | |||
53 | GNUNET_free (database); | 55 | GNUNET_free (database); |
54 | db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); | 56 | db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); |
55 | if (NULL != db) | 57 | if (NULL != db) |
58 | { | ||
59 | if (GNUNET_OK != db->reset_database (db->cls, &emsg)) | ||
60 | { | ||
61 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error resetting database: %s\n", emsg); | ||
62 | GNUNET_free (emsg); | ||
63 | return GNUNET_SYSERR; | ||
64 | } | ||
56 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db)); | 65 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db)); |
66 | } | ||
57 | GNUNET_free (db_lib_name); | 67 | GNUNET_free (db_lib_name); |
58 | GNUNET_CONFIGURATION_destroy (cfg); | 68 | GNUNET_CONFIGURATION_destroy (cfg); |
59 | if (NULL == db) | 69 | if (NULL == db) |
diff --git a/src/namestore/test_namestore_api.conf b/src/namestore/test_namestore_api.conf index 3e75c2ded..ec685e2fe 100644 --- a/src/namestore/test_namestore_api.conf +++ b/src/namestore/test_namestore_api.conf | |||
@@ -18,5 +18,11 @@ START_ON_DEMAND = YES | |||
18 | [nse] | 18 | [nse] |
19 | WORKBITS = 0 | 19 | WORKBITS = 0 |
20 | 20 | ||
21 | [rest] | ||
22 | BASIC_AUTH_ENABLED=NO | ||
23 | # PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/v_log | ||
24 | |||
25 | |||
26 | |||
21 | [transport] | 27 | [transport] |
22 | PLUGINS = | 28 | PLUGINS = |
diff --git a/src/namestore/test_namestore_api_edit_records.c b/src/namestore/test_namestore_api_edit_records.c new file mode 100644 index 000000000..c1c64ee9c --- /dev/null +++ b/src/namestore/test_namestore_api_edit_records.c | |||
@@ -0,0 +1,404 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2022 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_edit_records.c | ||
22 | * @brief testcase for namestore_api.c: Multiple clients work with record set. | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "gnunet_dnsparser_lib.h" | ||
28 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | #define TEST_RECORD_DATALEN 123 | ||
32 | |||
33 | #define TEST_RECORD_DATA 'a' | ||
34 | |||
35 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
36 | |||
37 | |||
38 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
39 | |||
40 | static struct GNUNET_NAMESTORE_Handle *nsh2; | ||
41 | |||
42 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
43 | |||
44 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
45 | |||
46 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
47 | |||
48 | static int res; | ||
49 | |||
50 | static int removed; | ||
51 | |||
52 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
53 | |||
54 | static int nonce = 0; | ||
55 | |||
56 | static void | ||
57 | cleanup () | ||
58 | { | ||
59 | if (NULL != nsh) | ||
60 | { | ||
61 | GNUNET_NAMESTORE_disconnect (nsh); | ||
62 | nsh = NULL; | ||
63 | } | ||
64 | GNUNET_SCHEDULER_shutdown (); | ||
65 | } | ||
66 | |||
67 | |||
68 | /** | ||
69 | * Re-establish the connection to the service. | ||
70 | * | ||
71 | * @param cls handle to use to re-connect. | ||
72 | */ | ||
73 | static void | ||
74 | endbadly (void *cls) | ||
75 | { | ||
76 | if (NULL != nsqe) | ||
77 | { | ||
78 | GNUNET_NAMESTORE_cancel (nsqe); | ||
79 | nsqe = NULL; | ||
80 | } | ||
81 | cleanup (); | ||
82 | res = 1; | ||
83 | } | ||
84 | |||
85 | |||
86 | static void | ||
87 | end (void *cls) | ||
88 | { | ||
89 | cleanup (); | ||
90 | res = 0; | ||
91 | } | ||
92 | |||
93 | static void | ||
94 | lookup_it (void *cls, | ||
95 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
96 | const char *label, | ||
97 | unsigned int rd_count, | ||
98 | const struct GNUNET_GNSRECORD_Data *rd) | ||
99 | { | ||
100 | GNUNET_assert (0 == rd_count); | ||
101 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
102 | } | ||
103 | |||
104 | static void | ||
105 | fail_cb (void *cls) | ||
106 | { | ||
107 | if (endbadly_task != NULL) | ||
108 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
109 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | static void | ||
114 | remove_cont (void *cls, | ||
115 | int32_t success, | ||
116 | const char *emsg) | ||
117 | { | ||
118 | nsqe = NULL; | ||
119 | if (GNUNET_YES != success) | ||
120 | { | ||
121 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
122 | _ ("Unable to roll back: `%s'\n"), | ||
123 | emsg); | ||
124 | if (NULL != endbadly_task) | ||
125 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
126 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
127 | NULL); | ||
128 | return; | ||
129 | } | ||
130 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
131 | "Rolled back, perform lookup\n"); | ||
132 | removed = GNUNET_YES; | ||
133 | if (NULL != endbadly_task) | ||
134 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
135 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
136 | } | ||
137 | |||
138 | static void | ||
139 | fail_cb_lock (void *cls); | ||
140 | |||
141 | static void | ||
142 | edit_cont_b (void *cls, | ||
143 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
144 | const char *label, | ||
145 | unsigned int rd_count, | ||
146 | const struct GNUNET_GNSRECORD_Data *rd) | ||
147 | { | ||
148 | const char *name = cls; | ||
149 | /** | ||
150 | * We should probably never get here right at first. | ||
151 | * We may want to change the blocking of nsh2 so that we do get this | ||
152 | * eventually instead of the error callback above when locked. | ||
153 | */ | ||
154 | if (0 == nonce) | ||
155 | { | ||
156 | if (endbadly_task != NULL) | ||
157 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
158 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
159 | return; | ||
160 | |||
161 | } | ||
162 | /* Abort transaction for B */ | ||
163 | nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh2, remove_cont, | ||
164 | (void *) name); | ||
165 | } | ||
166 | |||
167 | |||
168 | static void | ||
169 | commit_cont_a (void *cls, | ||
170 | int32_t success, | ||
171 | const char *emsg) | ||
172 | { | ||
173 | const char *name = cls; | ||
174 | |||
175 | GNUNET_assert (NULL != cls); | ||
176 | nsqe = NULL; | ||
177 | if (GNUNET_SYSERR == success) | ||
178 | { | ||
179 | GNUNET_break (0); | ||
180 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
181 | "Namestore could not store record: `%s'\n", | ||
182 | emsg); | ||
183 | if (endbadly_task != NULL) | ||
184 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
185 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
190 | "Name store added record for `%s': %s\n", | ||
191 | name, | ||
192 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
193 | /** | ||
194 | * Try again for B | ||
195 | */ | ||
196 | nsqe = GNUNET_NAMESTORE_records_edit (nsh2, | ||
197 | &privkey, | ||
198 | name, | ||
199 | &fail_cb_lock, | ||
200 | (void *) name, | ||
201 | &edit_cont_b, | ||
202 | (void *) name); | ||
203 | |||
204 | GNUNET_assert (NULL != nsqe); | ||
205 | } | ||
206 | |||
207 | static void | ||
208 | fail_cb_lock (void *cls) | ||
209 | { | ||
210 | const char *name = cls; | ||
211 | if (1 == nonce) | ||
212 | { | ||
213 | if (endbadly_task != NULL) | ||
214 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
215 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
216 | return; | ||
217 | } | ||
218 | nonce = 1; | ||
219 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
220 | "Failed to aquire additional lock\n"); | ||
221 | /* Now, we stop the transaction for B */ | ||
222 | nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont_a, | ||
223 | (void *) name); | ||
224 | } | ||
225 | |||
226 | |||
227 | static void | ||
228 | begin_cont_b (void *cls, | ||
229 | int32_t success, | ||
230 | const char *emsg) | ||
231 | { | ||
232 | const char *name = cls; | ||
233 | |||
234 | GNUNET_assert (success == GNUNET_YES); | ||
235 | /** Now, we expect this to "hang" let's see how this behaves in practice. */ | ||
236 | nsqe = GNUNET_NAMESTORE_records_edit (nsh2, | ||
237 | &privkey, | ||
238 | name, | ||
239 | &fail_cb_lock, | ||
240 | (void *) name, | ||
241 | &edit_cont_b, | ||
242 | (void *) name); | ||
243 | |||
244 | GNUNET_assert (NULL != nsqe); | ||
245 | } | ||
246 | |||
247 | |||
248 | static void | ||
249 | edit_cont (void *cls, | ||
250 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
251 | const char *label, | ||
252 | unsigned int rd_count, | ||
253 | const struct GNUNET_GNSRECORD_Data *rd) | ||
254 | { | ||
255 | const char *name = cls; | ||
256 | |||
257 | GNUNET_assert (1 == rd_count); | ||
258 | /* Now, we start a transaction for B */ | ||
259 | nsqe = GNUNET_NAMESTORE_transaction_begin (nsh2, begin_cont_b, (void *) name); | ||
260 | } | ||
261 | |||
262 | |||
263 | static void | ||
264 | begin_cont (void *cls, | ||
265 | int32_t success, | ||
266 | const char *emsg) | ||
267 | { | ||
268 | const char *name = cls; | ||
269 | |||
270 | GNUNET_assert (success == GNUNET_YES); | ||
271 | nsqe = GNUNET_NAMESTORE_records_edit (nsh, | ||
272 | &privkey, | ||
273 | name, | ||
274 | &fail_cb, | ||
275 | (void *) name, | ||
276 | &edit_cont, | ||
277 | (void *) name); | ||
278 | |||
279 | GNUNET_assert (NULL != nsqe); | ||
280 | } | ||
281 | |||
282 | static void | ||
283 | preload_cont (void *cls, | ||
284 | int32_t success, | ||
285 | const char *emsg) | ||
286 | { | ||
287 | const char *name = cls; | ||
288 | |||
289 | GNUNET_assert (NULL != cls); | ||
290 | nsqe = NULL; | ||
291 | if (GNUNET_SYSERR == success) | ||
292 | { | ||
293 | GNUNET_break (0); | ||
294 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
295 | "Namestore could not store record: `%s'\n", | ||
296 | emsg); | ||
297 | if (endbadly_task != NULL) | ||
298 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
299 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
304 | "Name store added record for `%s': %s\n", | ||
305 | name, | ||
306 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
307 | /* We start transaction for A */ | ||
308 | nsqe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, (void *) name); | ||
309 | |||
310 | } | ||
311 | |||
312 | |||
313 | static void | ||
314 | run (void *cls, | ||
315 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
316 | struct GNUNET_TESTING_Peer *peer) | ||
317 | { | ||
318 | struct GNUNET_GNSRECORD_Data rd; | ||
319 | const char *name = "dummy"; | ||
320 | |||
321 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
322 | &endbadly, | ||
323 | NULL); | ||
324 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
325 | nsh2 = GNUNET_NAMESTORE_connect (cfg); | ||
326 | GNUNET_break (NULL != nsh); | ||
327 | GNUNET_break (NULL != nsh2); | ||
328 | |||
329 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
330 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
331 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
332 | &pubkey); | ||
333 | |||
334 | removed = GNUNET_NO; | ||
335 | |||
336 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
337 | rd.record_type = TEST_RECORD_TYPE; | ||
338 | rd.data_size = TEST_RECORD_DATALEN; | ||
339 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
340 | rd.flags = 0; | ||
341 | memset ((char *) rd.data, | ||
342 | 'a', | ||
343 | TEST_RECORD_DATALEN); | ||
344 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
345 | &privkey, | ||
346 | name, | ||
347 | 1, | ||
348 | &rd, | ||
349 | &preload_cont, | ||
350 | (void *) name); | ||
351 | GNUNET_assert (NULL != nsqe); | ||
352 | GNUNET_free_nz ((void *) rd.data); | ||
353 | |||
354 | /*nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont); | ||
355 | nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, rollback_cont); Must also happen on disconnect | ||
356 | nsqe = GNUNET_NAMESTORE_records_edit (nsh, | ||
357 | &privkey, | ||
358 | name, | ||
359 | 1, | ||
360 | &rd, | ||
361 | &edit_cont, | ||
362 | (void *) name); | ||
363 | nsqe = GNUNET_NAMESTORE_records_insert_bulk (nsh, | ||
364 | count, | ||
365 | &rd, | ||
366 | & | ||
367 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
368 | &privkey, | ||
369 | name, | ||
370 | 1, | ||
371 | &rd, | ||
372 | &put_cont, | ||
373 | (void *) name);*/ | ||
374 | GNUNET_assert (NULL != nsqe); | ||
375 | } | ||
376 | |||
377 | |||
378 | #include "test_common.c" | ||
379 | |||
380 | |||
381 | int | ||
382 | main (int argc, char *argv[]) | ||
383 | { | ||
384 | const char *plugin_name; | ||
385 | char *cfg_name; | ||
386 | |||
387 | SETUP_CFG (plugin_name, cfg_name); | ||
388 | res = 1; | ||
389 | if (0 != | ||
390 | GNUNET_TESTING_peer_run ("test-namestore-api-remove", | ||
391 | cfg_name, | ||
392 | &run, | ||
393 | NULL)) | ||
394 | { | ||
395 | res = 1; | ||
396 | } | ||
397 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
398 | "GNUNET_TEST_HOME"); | ||
399 | GNUNET_free (cfg_name); | ||
400 | return res; | ||
401 | } | ||
402 | |||
403 | |||
404 | /* end of test_namestore_api_remove.c */ | ||
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] | ||
4 | DATABASE = flat | ||
5 | |||
6 | [namestore-heap] | ||
7 | FILENAME = $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..1803b8ba4 100644 --- a/src/namestore/test_namestore_api_monitoring_existing.c +++ b/src/namestore/test_namestore_api_monitoring_existing.c | |||
@@ -248,28 +248,6 @@ put_cont (void *cls, | |||
248 | return; | 248 | return; |
249 | } | 249 | } |
250 | 250 | ||
251 | if (3 == c) | ||
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 | } | ||
273 | } | 251 | } |
274 | 252 | ||
275 | 253 | ||
@@ -324,6 +302,25 @@ run (void *cls, | |||
324 | NULL); | 302 | NULL); |
325 | return; | 303 | return; |
326 | } | 304 | } |
305 | /* Start monitoring */ | ||
306 | zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, | ||
307 | &privkey, | ||
308 | GNUNET_YES, | ||
309 | &fail_cb, | ||
310 | NULL, | ||
311 | &zone_proc, | ||
312 | NULL, | ||
313 | &sync_cb, | ||
314 | NULL); | ||
315 | if (NULL == zm) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
318 | "Failed to create zone monitor\n"); | ||
319 | GNUNET_break (0); | ||
320 | res = 1; | ||
321 | GNUNET_SCHEDULER_shutdown (); | ||
322 | return; | ||
323 | } | ||
327 | 324 | ||
328 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 325 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
329 | "Created record 3\n"); | 326 | "Created record 3\n"); |
diff --git a/src/namestore/test_namestore_api_postgres.conf b/src/namestore/test_namestore_api_postgres.conf index 93ef935b5..007168280 100644 --- a/src/namestore/test_namestore_api_postgres.conf +++ b/src/namestore/test_namestore_api_postgres.conf | |||
@@ -6,4 +6,5 @@ DATABASE = postgres | |||
6 | 6 | ||
7 | [namestore-postgres] | 7 | [namestore-postgres] |
8 | CONFIG = connect_timeout=10 dbname=gnunetcheck | 8 | CONFIG = connect_timeout=10 dbname=gnunetcheck |
9 | TEMPORARY_TABLE = YES | 9 | TEMPORARY_TABLE = NO |
10 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/test_namestore_api_sqlite.conf b/src/namestore/test_namestore_api_sqlite.conf index cd4822097..342356247 100644 --- a/src/namestore/test_namestore_api_sqlite.conf +++ b/src/namestore/test_namestore_api_sqlite.conf | |||
@@ -6,3 +6,4 @@ DATABASE = sqlite | |||
6 | 6 | ||
7 | [namestore-sqlite] | 7 | [namestore-sqlite] |
8 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | 8 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db |
9 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/test_namestore_api_tx_rollback.c b/src/namestore/test_namestore_api_tx_rollback.c new file mode 100644 index 000000000..ccfd8d701 --- /dev/null +++ b/src/namestore/test_namestore_api_tx_rollback.c | |||
@@ -0,0 +1,268 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2022 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_tx_rollback.c | ||
22 | * @brief testcase for namestore_api_tx_rollback.c to: rollback changes in TX | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "gnunet_dnsparser_lib.h" | ||
28 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | #define TEST_RECORD_DATALEN 123 | ||
32 | |||
33 | #define TEST_RECORD_DATA 'a' | ||
34 | |||
35 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
36 | |||
37 | |||
38 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
39 | |||
40 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
41 | |||
42 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
43 | |||
44 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
45 | |||
46 | static int res; | ||
47 | |||
48 | static int removed; | ||
49 | |||
50 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
51 | |||
52 | |||
53 | static void | ||
54 | cleanup () | ||
55 | { | ||
56 | if (NULL != nsh) | ||
57 | { | ||
58 | GNUNET_NAMESTORE_disconnect (nsh); | ||
59 | nsh = NULL; | ||
60 | } | ||
61 | GNUNET_SCHEDULER_shutdown (); | ||
62 | } | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Re-establish the connection to the service. | ||
67 | * | ||
68 | * @param cls handle to use to re-connect. | ||
69 | */ | ||
70 | static void | ||
71 | endbadly (void *cls) | ||
72 | { | ||
73 | if (NULL != nsqe) | ||
74 | { | ||
75 | GNUNET_NAMESTORE_cancel (nsqe); | ||
76 | nsqe = NULL; | ||
77 | } | ||
78 | cleanup (); | ||
79 | res = 1; | ||
80 | } | ||
81 | |||
82 | |||
83 | static void | ||
84 | end (void *cls) | ||
85 | { | ||
86 | cleanup (); | ||
87 | res = 0; | ||
88 | } | ||
89 | |||
90 | static void | ||
91 | lookup_it (void *cls, | ||
92 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
93 | const char *label, | ||
94 | unsigned int rd_count, | ||
95 | const struct GNUNET_GNSRECORD_Data *rd) | ||
96 | { | ||
97 | GNUNET_assert (0 == rd_count); | ||
98 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | fail_cb (void *cls) | ||
103 | { | ||
104 | GNUNET_assert (0); | ||
105 | } | ||
106 | |||
107 | static void | ||
108 | remove_cont (void *cls, | ||
109 | int32_t success, | ||
110 | const char *emsg) | ||
111 | { | ||
112 | nsqe = NULL; | ||
113 | if (GNUNET_YES != success) | ||
114 | { | ||
115 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
116 | _ ("Unable to roll back: `%s'\n"), | ||
117 | emsg); | ||
118 | if (NULL != endbadly_task) | ||
119 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
120 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
121 | NULL); | ||
122 | return; | ||
123 | } | ||
124 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
125 | "Rolled back, perform lookup\n"); | ||
126 | removed = GNUNET_YES; | ||
127 | if (NULL != endbadly_task) | ||
128 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
129 | /* FIXME not actually doing lookup here */ | ||
130 | nsqe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
131 | &privkey, | ||
132 | (char*) cls, | ||
133 | &fail_cb, | ||
134 | NULL, | ||
135 | &lookup_it, | ||
136 | NULL); | ||
137 | } | ||
138 | |||
139 | |||
140 | static void | ||
141 | put_cont (void *cls, | ||
142 | int32_t success, | ||
143 | const char *emsg) | ||
144 | { | ||
145 | const char *name = cls; | ||
146 | |||
147 | GNUNET_assert (NULL != cls); | ||
148 | nsqe = NULL; | ||
149 | if (GNUNET_SYSERR == success) | ||
150 | { | ||
151 | GNUNET_break (0); | ||
152 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
153 | "Namestore could not store record: `%s'\n", | ||
154 | emsg); | ||
155 | if (endbadly_task != NULL) | ||
156 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
157 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
162 | "Name store added record for `%s': %s\n", | ||
163 | name, | ||
164 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
165 | nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, remove_cont, | ||
166 | (void *) name); | ||
167 | } | ||
168 | |||
169 | static void | ||
170 | begin_cont (void *cls, | ||
171 | int32_t success, | ||
172 | const char *emsg) | ||
173 | { | ||
174 | struct GNUNET_GNSRECORD_Data rd; | ||
175 | const char *name = cls; | ||
176 | |||
177 | GNUNET_assert (success == GNUNET_YES); | ||
178 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
179 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
180 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
181 | &pubkey); | ||
182 | |||
183 | removed = GNUNET_NO; | ||
184 | |||
185 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
186 | rd.record_type = TEST_RECORD_TYPE; | ||
187 | rd.data_size = TEST_RECORD_DATALEN; | ||
188 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
189 | rd.flags = 0; | ||
190 | memset ((char *) rd.data, | ||
191 | 'a', | ||
192 | TEST_RECORD_DATALEN); | ||
193 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
194 | &privkey, | ||
195 | name, | ||
196 | 1, | ||
197 | &rd, | ||
198 | &put_cont, | ||
199 | (void *) name); | ||
200 | GNUNET_assert (NULL != nsqe); | ||
201 | GNUNET_free_nz ((void *) rd.data); | ||
202 | } | ||
203 | |||
204 | static void | ||
205 | run (void *cls, | ||
206 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
207 | struct GNUNET_TESTING_Peer *peer) | ||
208 | { | ||
209 | struct GNUNET_GNSRECORD_Data rd; | ||
210 | const char *name = "dummy"; | ||
211 | |||
212 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
213 | &endbadly, | ||
214 | NULL); | ||
215 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
216 | GNUNET_break (NULL != nsh); | ||
217 | nsqe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, (void *) name); | ||
218 | /*nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont); | ||
219 | nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, rollback_cont); Must also happen on disconnect | ||
220 | nsqe = GNUNET_NAMESTORE_records_edit (nsh, | ||
221 | &privkey, | ||
222 | name, | ||
223 | 1, | ||
224 | &rd, | ||
225 | &edit_cont, | ||
226 | (void *) name); | ||
227 | nsqe = GNUNET_NAMESTORE_records_insert_bulk (nsh, | ||
228 | count, | ||
229 | &rd, | ||
230 | & | ||
231 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
232 | &privkey, | ||
233 | name, | ||
234 | 1, | ||
235 | &rd, | ||
236 | &put_cont, | ||
237 | (void *) name);*/ | ||
238 | GNUNET_assert (NULL != nsqe); | ||
239 | } | ||
240 | |||
241 | |||
242 | #include "test_common.c" | ||
243 | |||
244 | |||
245 | int | ||
246 | main (int argc, char *argv[]) | ||
247 | { | ||
248 | const char *plugin_name; | ||
249 | char *cfg_name; | ||
250 | |||
251 | SETUP_CFG (plugin_name, cfg_name); | ||
252 | res = 1; | ||
253 | if (0 != | ||
254 | GNUNET_TESTING_peer_run ("test-namestore-api-remove", | ||
255 | cfg_name, | ||
256 | &run, | ||
257 | NULL)) | ||
258 | { | ||
259 | res = 1; | ||
260 | } | ||
261 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
262 | "GNUNET_TEST_HOME"); | ||
263 | GNUNET_free (cfg_name); | ||
264 | return res; | ||
265 | } | ||
266 | |||
267 | |||
268 | /* end of test_namestore_api_remove.c */ | ||
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] | ||
2 | FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-flat/flatdb | ||
diff --git a/src/namestore/test_plugin_namestore_postgres.conf b/src/namestore/test_plugin_namestore_postgres.conf index 2ce8a7792..3b5cb8699 100644 --- a/src/namestore/test_plugin_namestore_postgres.conf +++ b/src/namestore/test_plugin_namestore_postgres.conf | |||
@@ -1,3 +1,4 @@ | |||
1 | [namestore-postgres] | 1 | [namestore-postgres] |
2 | CONFIG = connect_timeout=10 dbname=gnunetcheck | 2 | CONFIG = connect_timeout=10 dbname=gnunetcheck |
3 | INIT_ON_CONNECT = YES | ||
3 | TEMPORARY_TABLE = YES | 4 | TEMPORARY_TABLE = YES |
diff --git a/src/namestore/test_plugin_namestore_sqlite.conf b/src/namestore/test_plugin_namestore_sqlite.conf index 24eecd286..365198db2 100644 --- a/src/namestore/test_plugin_namestore_sqlite.conf +++ b/src/namestore/test_plugin_namestore_sqlite.conf | |||
@@ -1,2 +1,3 @@ | |||
1 | [namestore-sqlite] | 1 | [namestore-sqlite] |
2 | FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-sqlite/sqlite.db | 2 | FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-sqlite/sqlite.db |
3 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh index 50b3c8c12..83c6015c7 100755 --- a/src/namestore/test_plugin_rest_namestore.sh +++ b/src/namestore/test_plugin_rest_namestore.sh | |||
@@ -18,7 +18,6 @@ rm -rf `gnunet-config -c test_namestore_api.conf -f -s paths -o GNUNET_TEST_HOME | |||
18 | namestore_link="http://localhost:7776/namestore" | 18 | namestore_link="http://localhost:7776/namestore" |
19 | wrong_link="http://localhost:7776/namestoreandmore" | 19 | wrong_link="http://localhost:7776/namestoreandmore" |
20 | 20 | ||
21 | |||
22 | curl_get () { | 21 | curl_get () { |
23 | #$1 is link | 22 | #$1 is link |
24 | #$2 is grep | 23 | #$2 is grep |