aboutsummaryrefslogtreecommitdiff
path: root/src/service/peerstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/peerstore')
-rw-r--r--src/service/peerstore/Makefile.am52
-rw-r--r--src/service/peerstore/meson.build10
-rw-r--r--src/service/peerstore/plugin_peerstore_flat.c606
-rw-r--r--src/service/peerstore/plugin_peerstore_sqlite.c702
-rw-r--r--src/service/peerstore/test_plugin_peerstore.c224
-rw-r--r--src/service/peerstore/test_plugin_peerstore_flat.conf5
-rw-r--r--src/service/peerstore/test_plugin_peerstore_sqlite.conf2
7 files changed, 2 insertions, 1599 deletions
diff --git a/src/service/peerstore/Makefile.am b/src/service/peerstore/Makefile.am
index 28948b7db..de301bbcf 100644
--- a/src/service/peerstore/Makefile.am
+++ b/src/service/peerstore/Makefile.am
@@ -51,63 +51,15 @@ libgnunetpeerstore_la_LDFLAGS = \
51 $(GN_LIBINTL) \ 51 $(GN_LIBINTL) \
52 $(GN_LIB_LDFLAGS) 52 $(GN_LIB_LDFLAGS)
53 53
54if HAVE_EXPERIMENTAL
55FLAT_PLUGIN = libgnunet_plugin_peerstore_flat.la
56FLAT_TESTS = test_plugin_peerstore_flat
57libgnunet_plugin_peerstore_flat_la_SOURCES = \
58 plugin_peerstore_flat.c
59libgnunet_plugin_peerstore_flat_la_LIBADD = \
60 libgnunetpeerstore.la \
61 $(top_builddir)/src/lib/util/libgnunetutil.la $(XLIBS) \
62 $(LTLIBINTL)
63libgnunet_plugin_peerstore_flat_la_LDFLAGS = \
64 $(GN_PLUGIN_LDFLAGS)
65endif
66
67if HAVE_SQLITE
68SQLITE_PLUGIN = libgnunet_plugin_peerstore_sqlite.la
69SQLITE_TESTS = test_plugin_peerstore_sqlite
70libgnunet_plugin_peerstore_sqlite_la_SOURCES = \
71 plugin_peerstore_sqlite.c
72libgnunet_plugin_peerstore_sqlite_la_LIBADD = \
73 libgnunetpeerstore.la \
74 $(top_builddir)/src/lib/sq/libgnunetsq.la \
75 $(top_builddir)/src/lib/util/libgnunetutil.la \
76 $(XLIBS) -lsqlite3 \
77 $(LTLIBINTL)
78libgnunet_plugin_peerstore_sqlite_la_LDFLAGS = \
79 $(GN_PLUGIN_LDFLAGS)
80endif
81
82plugin_LTLIBRARIES = \
83 $(SQLITE_PLUGIN) \
84 $(FLAT_PLUGIN)
85
86test_plugin_peerstore_sqlite_SOURCES = \
87 test_plugin_peerstore.c
88test_plugin_peerstore_sqlite_LDADD = \
89 $(top_builddir)/src/service/testing/libgnunettesting.la \
90 $(top_builddir)/src/lib/util/libgnunetutil.la
91
92test_plugin_peerstore_flat_SOURCES = \
93 test_plugin_peerstore.c
94test_plugin_peerstore_flat_LDADD = \
95 $(top_builddir)/src/service/testing/libgnunettesting.la \
96 $(top_builddir)/src/lib/util/libgnunetutil.la
97
98check_PROGRAMS = \ 54check_PROGRAMS = \
99 test_peerstore_api_store \ 55 test_peerstore_api_store \
100 test_peerstore_api_iterate \ 56 test_peerstore_api_iterate \
101 test_peerstore_api_watch \ 57 test_peerstore_api_watch \
102 test_peerstore_api_sync \ 58 test_peerstore_api_sync \
103 perf_peerstore_store \ 59 perf_peerstore_store
104 $(SQLITE_TESTS) \
105 $(FLAT_TESTS)
106 60
107EXTRA_DIST = \ 61EXTRA_DIST = \
108 test_peerstore_api_data.conf \ 62 test_peerstore_api_data.conf
109 test_plugin_peerstore_flat.conf \
110 test_plugin_peerstore_sqlite.conf
111 63
112if ENABLE_TEST_RUN 64if ENABLE_TEST_RUN
113AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 65AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
diff --git a/src/service/peerstore/meson.build b/src/service/peerstore/meson.build
index 7d8710c4b..db70b0b9e 100644
--- a/src/service/peerstore/meson.build
+++ b/src/service/peerstore/meson.build
@@ -28,16 +28,6 @@ pkg.generate(libgnunetpeerstore, url: 'https://www.gnunet.org',
28 description : 'Provides API for accessing the peerstore service') 28 description : 'Provides API for accessing the peerstore service')
29libgnunetpeerstore_dep = declare_dependency(link_with : libgnunetpeerstore) 29libgnunetpeerstore_dep = declare_dependency(link_with : libgnunetpeerstore)
30 30
31shared_module('gnunet_plugin_peerstore_sqlite',
32 ['plugin_peerstore_sqlite.c'],
33 dependencies: [libgnunetutil_dep,
34 libgnunetpeerstore_dep,
35 libgnunetsq_dep,
36 sqlite_dep],
37 include_directories: [incdir, configuration_inc],
38 install: true,
39 install_dir: get_option('libdir')/'gnunet')
40
41executable ('gnunet-service-peerstore', 31executable ('gnunet-service-peerstore',
42 gnunetservicepeerstore_src, 32 gnunetservicepeerstore_src,
43 dependencies: [libgnunetpeerstore_dep, 33 dependencies: [libgnunetpeerstore_dep,
diff --git a/src/service/peerstore/plugin_peerstore_flat.c b/src/service/peerstore/plugin_peerstore_flat.c
deleted file mode 100644
index cc5b8b76b..000000000
--- a/src/service/peerstore/plugin_peerstore_flat.c
+++ /dev/null
@@ -1,606 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2015 Christian Grothoff (and other contributing authors)
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/**
22 * @file peerstore/plugin_peerstore_flat.c
23 * @brief flat file-based peerstore backend
24 * @author Martin Schanzenbach
25 */
26
27#include "platform.h"
28#include "gnunet_peerstore_plugin.h"
29#include "gnunet_peerstore_service.h"
30#include "peerstore.h"
31
32/**
33 * Context for all functions in this plugin.
34 */
35struct Plugin
36{
37 /**
38 * Configuration handle
39 */
40 const struct GNUNET_CONFIGURATION_Handle *cfg;
41
42 /**
43 * HashMap
44 */
45 struct GNUNET_CONTAINER_MultiHashMap *hm;
46
47 /**
48 * Iterator
49 */
50 GNUNET_PEERSTORE_Processor iter;
51
52 /**
53 * Iterator cls
54 */
55 void *iter_cls;
56
57 /**
58 * iterator key
59 */
60 const char *iter_key;
61
62 /**
63 * Iterator peer
64 */
65 const struct GNUNET_PeerIdentity *iter_peer;
66
67 /**
68 * Iterator subsystem
69 */
70 const char *iter_sub_system;
71
72 /**
73 * Iterator time
74 */
75 struct GNUNET_TIME_Absolute iter_now;
76
77 /**
78 * Deleted entries
79 */
80 uint64_t deleted_entries;
81
82 /**
83 * Expired entries
84 */
85 uint64_t exp_changes;
86
87 /**
88 * Database filename.
89 */
90 char *fn;
91
92 /**
93 * Result found bool
94 */
95 int iter_result_found;
96};
97
98
99static int
100delete_entries (void *cls,
101 const struct GNUNET_HashCode *key,
102 void *value)
103{
104 struct Plugin *plugin = cls;
105 struct GNUNET_PEERSTORE_Record *entry = value;
106
107 if (0 != strcmp (plugin->iter_key, entry->key))
108 return GNUNET_YES;
109 if (0 != memcmp (plugin->iter_peer,
110 &entry->peer,
111 sizeof(struct GNUNET_PeerIdentity)))
112 return GNUNET_YES;
113 if (0 != strcmp (plugin->iter_sub_system, entry->sub_system))
114 return GNUNET_YES;
115
116 GNUNET_CONTAINER_multihashmap_remove (plugin->hm, key, value);
117 plugin->deleted_entries++;
118 return GNUNET_YES;
119}
120
121
122/**
123 * Delete records with the given key
124 *
125 * @param cls closure (internal context for the plugin)
126 * @param sub_system name of sub system
127 * @param peer Peer identity (can be NULL)
128 * @param key entry key string (can be NULL)
129 * @return number of deleted records
130 */
131static int
132peerstore_flat_delete_records (void *cls, const char *sub_system,
133 const struct GNUNET_PeerIdentity *peer,
134 const char *key)
135{
136 struct Plugin *plugin = cls;
137
138 plugin->iter_sub_system = sub_system;
139 plugin->iter_peer = peer;
140 plugin->iter_key = key;
141 plugin->deleted_entries = 0;
142
143 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
144 &delete_entries,
145 plugin);
146 return plugin->deleted_entries;
147}
148
149
150static int
151expire_entries (void *cls,
152 const struct GNUNET_HashCode *key,
153 void *value)
154{
155 struct Plugin *plugin = cls;
156 struct GNUNET_PEERSTORE_Record *entry = value;
157
158 if (entry->expiry.abs_value_us < plugin->iter_now.abs_value_us)
159 {
160 GNUNET_CONTAINER_multihashmap_remove (plugin->hm, key, value);
161 plugin->exp_changes++;
162 }
163 return GNUNET_YES;
164}
165
166
167/**
168 * Delete expired records (expiry < now)
169 *
170 * @param cls closure (internal context for the plugin)
171 * @param now time to use as reference
172 * @param cont continuation called with the number of records expired
173 * @param cont_cls continuation closure
174 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and cont is not
175 * called
176 */
177static int
178peerstore_flat_expire_records (void *cls, struct GNUNET_TIME_Absolute now,
179 GNUNET_PEERSTORE_Continuation cont,
180 void *cont_cls)
181{
182 struct Plugin *plugin = cls;
183
184 plugin->exp_changes = 0;
185 plugin->iter_now = now;
186
187 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
188 &expire_entries,
189 plugin);
190 if (NULL != cont)
191 {
192 cont (cont_cls, plugin->exp_changes);
193 }
194 return GNUNET_OK;
195}
196
197
198static int
199iterate_entries (void *cls,
200 const struct GNUNET_HashCode *key,
201 void *value)
202{
203 struct Plugin *plugin = cls;
204 struct GNUNET_PEERSTORE_Record *entry = value;
205
206 if ((NULL != plugin->iter_peer) &&
207 (0 != memcmp (plugin->iter_peer,
208 &entry->peer,
209 sizeof(struct GNUNET_PeerIdentity))))
210 {
211 return GNUNET_YES;
212 }
213 if ((NULL != plugin->iter_key) &&
214 (0 != strcmp (plugin->iter_key,
215 entry->key)))
216 {
217 return GNUNET_YES;
218 }
219 if (NULL != plugin->iter)
220 plugin->iter (plugin->iter_cls, entry, NULL);
221 plugin->iter_result_found = GNUNET_YES;
222 return GNUNET_YES;
223}
224
225
226/**
227 * Iterate over the records given an optional peer id
228 * and/or key.
229 *
230 * @param cls closure (internal context for the plugin)
231 * @param sub_system name of sub system
232 * @param peer Peer identity (can be NULL)
233 * @param key entry key string (can be NULL)
234 * @param iter function to call asynchronously with the results, terminated
235 * by a NULL result
236 * @param iter_cls closure for @a iter
237 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and iter is not
238 * called
239 */
240static int
241peerstore_flat_iterate_records (void *cls, const char *sub_system,
242 const struct GNUNET_PeerIdentity *peer,
243 const char *key,
244 GNUNET_PEERSTORE_Processor iter,
245 void *iter_cls)
246{
247 struct Plugin *plugin = cls;
248
249 plugin->iter = iter;
250 plugin->iter_cls = iter_cls;
251 plugin->iter_peer = peer;
252 plugin->iter_sub_system = sub_system;
253 plugin->iter_key = key;
254
255 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
256 &iterate_entries,
257 plugin);
258 if (NULL != iter)
259 iter (iter_cls, NULL, NULL);
260 return GNUNET_OK;
261}
262
263
264/**
265 * Store a record in the peerstore.
266 * Key is the combination of sub system and peer identity.
267 * One key can store multiple values.
268 *
269 * @param cls closure (internal context for the plugin)
270 * @param sub_system name of the GNUnet sub system responsible
271 * @param peer peer identity
272 * @param key record key string
273 * @param value value to be stored
274 * @param size size of value to be stored
275 * @param expiry absolute time after which the record is (possibly) deleted
276 * @param options options related to the store operation
277 * @param cont continuation called when record is stored
278 * @param cont_cls continuation closure
279 * @return #GNUNET_OK on success, else #GNUNET_SYSERR and cont is not called
280 */
281static int
282peerstore_flat_store_record (void *cls, const char *sub_system,
283 const struct GNUNET_PeerIdentity *peer,
284 const char *key, const void *value, size_t size,
285 struct GNUNET_TIME_Absolute expiry,
286 enum GNUNET_PEERSTORE_StoreOption options,
287 GNUNET_PEERSTORE_Continuation cont,
288 void *cont_cls)
289{
290 struct Plugin *plugin = cls;
291 struct GNUNET_HashCode hkey;
292 struct GNUNET_PEERSTORE_Record *entry;
293 const char *peer_id;
294
295
296 entry = GNUNET_new (struct GNUNET_PEERSTORE_Record);
297 entry->sub_system = GNUNET_strdup (sub_system);
298 entry->key = GNUNET_strdup (key);
299 entry->value = GNUNET_malloc (size);
300 GNUNET_memcpy (entry->value, value, size);
301 entry->value_size = size;
302 entry->peer = *peer;
303 entry->expiry = expiry;
304
305 peer_id = GNUNET_i2s (peer);
306 GNUNET_CRYPTO_hash (peer_id,
307 strlen (peer_id),
308 &hkey);
309
310 if (GNUNET_PEERSTORE_STOREOPTION_REPLACE == options)
311 {
312 peerstore_flat_delete_records (cls, sub_system, peer, key);
313 }
314
315 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
316 &hkey,
317 entry,
318 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
319 if (NULL != cont)
320 {
321 cont (cont_cls, GNUNET_OK);
322 }
323 return GNUNET_OK;
324}
325
326
327/**
328 * Initialize the database connections and associated
329 * data structures (create tables and indices
330 * as needed as well).
331 *
332 * @param plugin the plugin context (state for this module)
333 * @return GNUNET_OK on success
334 */
335static int
336database_setup (struct Plugin *plugin)
337{
338 char *afsdir;
339 char *key;
340 char *sub_system;
341 const char *peer_id;
342 char *peer;
343 char *value;
344 char *expiry;
345 struct GNUNET_DISK_FileHandle *fh;
346 struct GNUNET_PEERSTORE_Record *entry;
347 struct GNUNET_HashCode hkey;
348 uint64_t size;
349 char *buffer;
350 char *line;
351
352 if (GNUNET_OK !=
353 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "peerstore-flat",
354 "FILENAME", &afsdir))
355 {
356 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "peerstore-flat",
357 "FILENAME");
358 return GNUNET_SYSERR;
359 }
360 if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
361 {
362 if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir))
363 {
364 GNUNET_break (0);
365 GNUNET_free (afsdir);
366 return GNUNET_SYSERR;
367 }
368 }
369 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
370 plugin->fn = afsdir;
371
372 fh = GNUNET_DISK_file_open (afsdir,
373 GNUNET_DISK_OPEN_CREATE
374 | GNUNET_DISK_OPEN_READWRITE,
375 GNUNET_DISK_PERM_USER_WRITE
376 | GNUNET_DISK_PERM_USER_READ);
377 if (NULL == fh)
378 {
379 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
380 _ ("Unable to initialize file: %s.\n"),
381 afsdir);
382 return GNUNET_SYSERR;
383 }
384
385 /* Load data from file into hashmap */
386 plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
387 GNUNET_NO);
388
389 if (GNUNET_SYSERR == GNUNET_DISK_file_size (afsdir,
390 &size,
391 GNUNET_YES,
392 GNUNET_YES))
393 {
394 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
395 _ ("Unable to get filesize: %s.\n"),
396 afsdir);
397 return GNUNET_SYSERR;
398 }
399
400 buffer = GNUNET_malloc (size + 1);
401
402 if (GNUNET_SYSERR == GNUNET_DISK_file_read (fh,
403 buffer,
404 size))
405 {
406 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
407 _ ("Unable to read file: %s.\n"),
408 afsdir);
409 GNUNET_DISK_file_close (fh);
410 GNUNET_free (buffer);
411 return GNUNET_SYSERR;
412 }
413
414 buffer[size] = '\0';
415 GNUNET_DISK_file_close (fh);
416 if (0 < size)
417 {
418 line = strtok (buffer, "\n");
419 while (line != NULL)
420 {
421 sub_system = strtok (line, ",");
422 if (NULL == sub_system)
423 break;
424 peer = strtok (NULL, ",");
425 if (NULL == peer)
426 break;
427 key = strtok (NULL, ",");
428 if (NULL == key)
429 break;
430 value = strtok (NULL, ",");
431 if (NULL == value)
432 break;
433 expiry = strtok (NULL, ",");
434 if (NULL == expiry)
435 break;
436 entry = GNUNET_new (struct GNUNET_PEERSTORE_Record);
437 entry->sub_system = GNUNET_strdup (sub_system);
438 entry->key = GNUNET_strdup (key);
439 {
440 size_t s;
441 char *o;
442
443 o = NULL;
444 s = GNUNET_STRINGS_base64_decode (peer,
445 strlen (peer),
446 (void **) &o);
447 if (sizeof(struct GNUNET_PeerIdentity) == s)
448 GNUNET_memcpy (&entry->peer,
449 o,
450 s);
451 else
452 GNUNET_break (0);
453 GNUNET_free (o);
454 }
455 entry->value_size = GNUNET_STRINGS_base64_decode (value,
456 strlen (value),
457 (void **) &entry->value);
458 if (GNUNET_SYSERR ==
459 GNUNET_STRINGS_fancy_time_to_absolute (expiry,
460 &entry->expiry))
461 {
462 GNUNET_free (entry->sub_system);
463 GNUNET_free (entry->key);
464 GNUNET_free (entry);
465 break;
466 }
467 peer_id = GNUNET_i2s (&entry->peer);
468 GNUNET_CRYPTO_hash (peer_id,
469 strlen (peer_id),
470 &hkey);
471
472 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (plugin->hm,
473 &hkey,
474 entry,
475 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
476 }
477 }
478 GNUNET_free (buffer);
479 return GNUNET_OK;
480}
481
482
483static int
484store_and_free_entries (void *cls,
485 const struct GNUNET_HashCode *key,
486 void *value)
487{
488 struct GNUNET_DISK_FileHandle *fh = cls;
489 struct GNUNET_PEERSTORE_Record *entry = value;
490 char *line;
491 char *peer;
492 const char *expiry;
493 char *val;
494
495 GNUNET_STRINGS_base64_encode (entry->value,
496 entry->value_size,
497 &val);
498 expiry = GNUNET_STRINGS_absolute_time_to_string (entry->expiry);
499 GNUNET_STRINGS_base64_encode ((char *) &entry->peer,
500 sizeof(struct GNUNET_PeerIdentity),
501 &peer);
502 GNUNET_asprintf (&line,
503 "%s,%s,%s,%s,%s",
504 entry->sub_system,
505 peer,
506 entry->key,
507 val,
508 expiry);
509 GNUNET_free (val);
510 GNUNET_free (peer);
511 GNUNET_DISK_file_write (fh,
512 line,
513 strlen (line));
514 GNUNET_free (entry->sub_system);
515 GNUNET_free (entry->key);
516 GNUNET_free (entry->value);
517 GNUNET_free (entry);
518 GNUNET_free (line);
519 return GNUNET_YES;
520}
521
522
523/**
524 * Shutdown database connection and associate data
525 * structures.
526 * @param plugin the plugin context (state for this module)
527 */
528static void
529database_shutdown (struct Plugin *plugin)
530{
531 struct GNUNET_DISK_FileHandle *fh;
532
533 fh = GNUNET_DISK_file_open (plugin->fn,
534 GNUNET_DISK_OPEN_CREATE
535 | GNUNET_DISK_OPEN_TRUNCATE
536 | GNUNET_DISK_OPEN_READWRITE,
537 GNUNET_DISK_PERM_USER_WRITE
538 | GNUNET_DISK_PERM_USER_READ);
539 if (NULL == fh)
540 {
541 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
542 _ ("Unable to initialize file: %s.\n"),
543 plugin->fn);
544 return;
545 }
546 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
547 &store_and_free_entries,
548 fh);
549 GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
550 GNUNET_DISK_file_close (fh);
551}
552
553
554/**
555 * Entry point for the plugin.
556 *
557 * @param cls The struct GNUNET_CONFIGURATION_Handle.
558 * @return NULL on error, otherwise the plugin context
559 */
560void *
561libgnunet_plugin_peerstore_flat_init (void *cls)
562{
563 static struct Plugin plugin;
564 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
565 struct GNUNET_PEERSTORE_PluginFunctions *api;
566
567 if (NULL != plugin.cfg)
568 return NULL; /* can only initialize once! */
569 memset (&plugin, 0, sizeof(struct Plugin));
570 plugin.cfg = cfg;
571 if (GNUNET_OK != database_setup (&plugin))
572 {
573 database_shutdown (&plugin);
574 return NULL;
575 }
576 api = GNUNET_new (struct GNUNET_PEERSTORE_PluginFunctions);
577 api->cls = &plugin;
578 api->store_record = &peerstore_flat_store_record;
579 api->iterate_records = &peerstore_flat_iterate_records;
580 api->expire_records = &peerstore_flat_expire_records;
581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Flat plugin is running\n");
582 return api;
583}
584
585
586/**
587 * Exit point from the plugin.
588 *
589 * @param cls The plugin context (as returned by "init")
590 * @return Always NULL
591 */
592void *
593libgnunet_plugin_peerstore_flat_done (void *cls)
594{
595 struct GNUNET_PEERSTORE_PluginFunctions *api = cls;
596 struct Plugin *plugin = api->cls;
597
598 database_shutdown (plugin);
599 plugin->cfg = NULL;
600 GNUNET_free (api);
601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Flat plugin is finished\n");
602 return NULL;
603}
604
605
606/* end of plugin_peerstore_sqlite.c */
diff --git a/src/service/peerstore/plugin_peerstore_sqlite.c b/src/service/peerstore/plugin_peerstore_sqlite.c
deleted file mode 100644
index ad69efdf4..000000000
--- a/src/service/peerstore/plugin_peerstore_sqlite.c
+++ /dev/null
@@ -1,702 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2013, 2017 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/**
22 * @file peerstore/plugin_peerstore_sqlite.c
23 * @brief sqlite-based peerstore backend
24 * @author Omar Tarabai
25 * @author Christian Grothoff
26 */
27
28#include "platform.h"
29#include "gnunet_peerstore_plugin.h"
30#include "gnunet_peerstore_service.h"
31#include "gnunet_sq_lib.h"
32#include "peerstore.h"
33#include <sqlite3.h>
34
35/**
36 * After how many ms "busy" should a DB operation fail for good? A
37 * low value makes sure that we are more responsive to requests
38 * (especially PUTs). A high value guarantees a higher success rate
39 * (SELECTs in iterate can take several seconds despite LIMIT=1).
40 *
41 * The default value of 1s should ensure that users do not experience
42 * huge latencies while at the same time allowing operations to
43 * succeed with reasonable probability.
44 */
45#define BUSY_TIMEOUT_MS 1000
46
47/**
48 * Log an error message at log-level 'level' that indicates
49 * a failure of the command 'cmd' on file 'filename'
50 * with the message given by strerror(errno).
51 */
52#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, \
53 "peerstore-sqlite", _ ( \
54 "`%s' failed at %s:%d with error: %s\n"), \
55 cmd, \
56 __FILE__, __LINE__, \
57 sqlite3_errmsg ( \
58 db->dbh)); \
59} while (0)
60
61#define LOG(kind, ...) GNUNET_log_from (kind, "peerstore-sqlite", __VA_ARGS__)
62
63/**
64 * Context for all functions in this plugin.
65 */
66struct Plugin
67{
68 /**
69 * Configuration handle
70 */
71 const struct GNUNET_CONFIGURATION_Handle *cfg;
72
73 /**
74 * Database filename.
75 */
76 char *fn;
77
78 /**
79 * Native SQLite database handle.
80 */
81 sqlite3 *dbh;
82
83 /**
84 * Precompiled SQL for inserting into peerstoredata
85 */
86 sqlite3_stmt *insert_peerstoredata;
87
88 /**
89 * Precompiled SQL for selecting from peerstoredata
90 */
91 sqlite3_stmt *select_peerstoredata;
92
93 /**
94 * Precompiled SQL for selecting from peerstoredata
95 */
96 sqlite3_stmt *select_peerstoredata_by_pid;
97
98 /**
99 * Precompiled SQL for selecting from peerstoredata
100 */
101 sqlite3_stmt *select_peerstoredata_by_key;
102
103 /**
104 * Precompiled SQL for selecting from peerstoredata
105 */
106 sqlite3_stmt *select_peerstoredata_by_all;
107
108 /**
109 * Precompiled SQL for deleting expired
110 * records from peerstoredata
111 */
112 sqlite3_stmt *expire_peerstoredata;
113
114 /**
115 * Precompiled SQL for deleting records
116 * with given key
117 */
118 sqlite3_stmt *delete_peerstoredata;
119};
120
121
122/**
123 * Delete records with the given key
124 *
125 * @param cls closure (internal context for the plugin)
126 * @param sub_system name of sub system
127 * @param peer Peer identity (can be NULL)
128 * @param key entry key string (can be NULL)
129 * @return number of deleted records, #GNUNE_SYSERR on error
130 */
131static int
132peerstore_sqlite_delete_records (void *cls,
133 const char *sub_system,
134 const struct GNUNET_PeerIdentity *peer,
135 const char *key)
136{
137 struct Plugin *plugin = cls;
138 sqlite3_stmt *stmt = plugin->delete_peerstoredata;
139 struct GNUNET_SQ_QueryParam params[] = {
140 GNUNET_SQ_query_param_string (sub_system),
141 GNUNET_SQ_query_param_auto_from_type (peer),
142 GNUNET_SQ_query_param_string (key),
143 GNUNET_SQ_query_param_end
144 };
145 int ret;
146
147 if (GNUNET_OK !=
148 GNUNET_SQ_bind (stmt,
149 params))
150 {
151 LOG_SQLITE (plugin,
152 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
153 "sqlite3_bind");
154 GNUNET_SQ_reset (plugin->dbh,
155 stmt);
156 return GNUNET_SYSERR;
157 }
158 if (SQLITE_DONE !=
159 sqlite3_step (stmt))
160 {
161 LOG_SQLITE (plugin,
162 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
163 "sqlite3_step");
164 ret = GNUNET_SYSERR;
165 }
166 else
167 {
168 ret = sqlite3_changes (plugin->dbh);
169 }
170 GNUNET_SQ_reset (plugin->dbh,
171 stmt);
172 return ret;
173}
174
175
176/**
177 * Delete expired records (expiry < now)
178 *
179 * @param cls closure (internal context for the plugin)
180 * @param now time to use as reference
181 * @param cont continuation called with the number of records expired
182 * @param cont_cls continuation closure
183 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and cont is not
184 * called
185 */
186static int
187peerstore_sqlite_expire_records (void *cls, struct GNUNET_TIME_Absolute now,
188 GNUNET_PEERSTORE_Continuation cont,
189 void *cont_cls)
190{
191 struct Plugin *plugin = cls;
192 sqlite3_stmt *stmt = plugin->expire_peerstoredata;
193 struct GNUNET_SQ_QueryParam params[] = {
194 GNUNET_SQ_query_param_absolute_time (&now),
195 GNUNET_SQ_query_param_end
196 };
197
198 if (GNUNET_OK !=
199 GNUNET_SQ_bind (stmt,
200 params))
201 {
202 LOG_SQLITE (plugin,
203 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
204 "sqlite3_bind");
205 GNUNET_SQ_reset (plugin->dbh,
206 stmt);
207 return GNUNET_SYSERR;
208 }
209 if (SQLITE_DONE != sqlite3_step (stmt))
210 {
211 LOG_SQLITE (plugin,
212 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
213 "sqlite3_step");
214 GNUNET_SQ_reset (plugin->dbh,
215 stmt);
216 return GNUNET_SYSERR;
217 }
218 if (NULL != cont)
219 cont (cont_cls,
220 sqlite3_changes (plugin->dbh));
221 GNUNET_SQ_reset (plugin->dbh,
222 stmt);
223 return GNUNET_OK;
224}
225
226
227/**
228 * Iterate over the records given an optional peer id
229 * and/or key.
230 *
231 * @param cls closure (internal context for the plugin)
232 * @param sub_system name of sub system
233 * @param peer Peer identity (can be NULL)
234 * @param key entry key string (can be NULL)
235 * @param iter function to call asynchronously with the results, terminated
236 * by a NULL result
237 * @param iter_cls closure for @a iter
238 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and iter is not
239 * called
240 */
241static int
242peerstore_sqlite_iterate_records (void *cls,
243 const char *sub_system,
244 const struct GNUNET_PeerIdentity *peer,
245 const char *key,
246 GNUNET_PEERSTORE_Processor iter,
247 void *iter_cls)
248{
249 struct Plugin *plugin = cls;
250 sqlite3_stmt *stmt;
251 int err = 0;
252 int sret;
253 struct GNUNET_PEERSTORE_Record rec;
254
255 LOG (GNUNET_ERROR_TYPE_DEBUG,
256 "Executing iterate request on sqlite db.\n");
257 if (NULL == peer)
258 {
259 if (NULL == key)
260 {
261 struct GNUNET_SQ_QueryParam params[] = {
262 GNUNET_SQ_query_param_string (sub_system),
263 GNUNET_SQ_query_param_end
264 };
265
266 stmt = plugin->select_peerstoredata;
267 err = GNUNET_SQ_bind (stmt,
268 params);
269 }
270 else
271 {
272 struct GNUNET_SQ_QueryParam params[] = {
273 GNUNET_SQ_query_param_string (sub_system),
274 GNUNET_SQ_query_param_string (key),
275 GNUNET_SQ_query_param_end
276 };
277
278 stmt = plugin->select_peerstoredata_by_key;
279 err = GNUNET_SQ_bind (stmt,
280 params);
281 }
282 }
283 else
284 {
285 if (NULL == key)
286 {
287 struct GNUNET_SQ_QueryParam params[] = {
288 GNUNET_SQ_query_param_string (sub_system),
289 GNUNET_SQ_query_param_auto_from_type (peer),
290 GNUNET_SQ_query_param_end
291 };
292
293 stmt = plugin->select_peerstoredata_by_pid;
294 err = GNUNET_SQ_bind (stmt,
295 params);
296 }
297 else
298 {
299 struct GNUNET_SQ_QueryParam params[] = {
300 GNUNET_SQ_query_param_string (sub_system),
301 GNUNET_SQ_query_param_auto_from_type (peer),
302 GNUNET_SQ_query_param_string (key),
303 GNUNET_SQ_query_param_end
304 };
305
306 stmt = plugin->select_peerstoredata_by_all;
307 err = GNUNET_SQ_bind (stmt,
308 params);
309 }
310 }
311
312 if (GNUNET_OK != err)
313 {
314 LOG_SQLITE (plugin,
315 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
316 "sqlite3_bind_XXXX");
317 GNUNET_SQ_reset (plugin->dbh,
318 stmt);
319 return GNUNET_SYSERR;
320 }
321
322 err = 0;
323 while (SQLITE_ROW == (sret = sqlite3_step (stmt)))
324 {
325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Returning a matched record.\n");
327 struct GNUNET_SQ_ResultSpec rs[] = {
328 GNUNET_SQ_result_spec_string (&rec.sub_system),
329 GNUNET_SQ_result_spec_auto_from_type (&rec.peer),
330 GNUNET_SQ_result_spec_string (&rec.key),
331 GNUNET_SQ_result_spec_variable_size (&rec.value, &rec.value_size),
332 GNUNET_SQ_result_spec_absolute_time (&rec.expiry),
333 GNUNET_SQ_result_spec_end
334 };
335
336 if (GNUNET_OK !=
337 GNUNET_SQ_extract_result (stmt,
338 rs))
339 {
340 GNUNET_break (0);
341 break;
342 }
343 if (NULL != iter)
344 iter (iter_cls,
345 &rec,
346 NULL);
347 GNUNET_SQ_cleanup_result (rs);
348 }
349 if (SQLITE_DONE != sret)
350 {
351 LOG_SQLITE (plugin,
352 GNUNET_ERROR_TYPE_ERROR,
353 "sqlite_step");
354 err = 1;
355 }
356 GNUNET_SQ_reset (plugin->dbh,
357 stmt);
358 if (NULL != iter)
359 iter (iter_cls,
360 NULL,
361 err ? "sqlite error" : NULL);
362 return GNUNET_OK;
363}
364
365
366/**
367 * Store a record in the peerstore.
368 * Key is the combination of sub system and peer identity.
369 * One key can store multiple values.
370 *
371 * @param cls closure (internal context for the plugin)
372 * @param sub_system name of the GNUnet sub system responsible
373 * @param peer peer identity
374 * @param key record key string
375 * @param value value to be stored
376 * @param size size of value to be stored
377 * @param expiry absolute time after which the record is (possibly) deleted
378 * @param options options related to the store operation
379 * @param cont continuation called when record is stored
380 * @param cont_cls continuation closure
381 * @return #GNUNET_OK on success, else #GNUNET_SYSERR and cont is not called
382 */
383static int
384peerstore_sqlite_store_record (void *cls,
385 const char *sub_system,
386 const struct GNUNET_PeerIdentity *peer,
387 const char *key,
388 const void *value,
389 size_t size,
390 struct GNUNET_TIME_Absolute expiry,
391 enum GNUNET_PEERSTORE_StoreOption options,
392 GNUNET_PEERSTORE_Continuation cont,
393 void *cont_cls)
394{
395 struct Plugin *plugin = cls;
396 sqlite3_stmt *stmt = plugin->insert_peerstoredata;
397 struct GNUNET_SQ_QueryParam params[] = {
398 GNUNET_SQ_query_param_string (sub_system),
399 GNUNET_SQ_query_param_auto_from_type (peer),
400 GNUNET_SQ_query_param_string (key),
401 GNUNET_SQ_query_param_fixed_size (value, size),
402 GNUNET_SQ_query_param_absolute_time (&expiry),
403 GNUNET_SQ_query_param_end
404 };
405
406 if (GNUNET_PEERSTORE_STOREOPTION_REPLACE == options)
407 {
408 peerstore_sqlite_delete_records (cls,
409 sub_system,
410 peer,
411 key);
412 }
413 if (GNUNET_OK !=
414 GNUNET_SQ_bind (stmt,
415 params))
416 LOG_SQLITE (plugin,
417 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
418 "sqlite3_bind");
419 else if (SQLITE_DONE != sqlite3_step (stmt))
420 {
421 LOG_SQLITE (plugin,
422 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
423 "sqlite3_step");
424 }
425 GNUNET_SQ_reset (plugin->dbh,
426 stmt);
427 if (NULL != cont)
428 cont (cont_cls,
429 GNUNET_OK);
430 return GNUNET_OK;
431}
432
433
434/**
435 * @brief Prepare a SQL statement
436 *
437 * @param dbh handle to the database
438 * @param sql SQL statement, UTF-8 encoded
439 * @return 0 on success
440 */
441static int
442sql_exec (sqlite3 *dbh,
443 const char *sql)
444{
445 int result;
446
447 result = sqlite3_exec (dbh,
448 sql,
449 NULL,
450 NULL,
451 NULL);
452 LOG (GNUNET_ERROR_TYPE_DEBUG,
453 "Executed `%s' / %d\n",
454 sql,
455 result);
456 if (SQLITE_OK != result)
457 LOG (GNUNET_ERROR_TYPE_ERROR,
458 _ ("Error executing SQL query: %s\n %s\n"),
459 sqlite3_errmsg (dbh),
460 sql);
461 return result;
462}
463
464
465/**
466 * @brief Prepare a SQL statement
467 *
468 * @param dbh handle to the database
469 * @param sql SQL statement, UTF-8 encoded
470 * @param stmt set to the prepared statement
471 * @return 0 on success
472 */
473static int
474sql_prepare (sqlite3 *dbh,
475 const char *sql,
476 sqlite3_stmt **stmt)
477{
478 char *tail;
479 int result;
480
481 result = sqlite3_prepare_v2 (dbh,
482 sql,
483 strlen (sql),
484 stmt,
485 (const char **) &tail);
486 LOG (GNUNET_ERROR_TYPE_DEBUG,
487 "Prepared `%s' / %p: %d\n",
488 sql,
489 *stmt,
490 result);
491 if (SQLITE_OK != result)
492 LOG (GNUNET_ERROR_TYPE_ERROR,
493 _ ("Error preparing SQL query: %s\n %s\n"),
494 sqlite3_errmsg (dbh),
495 sql);
496 return result;
497}
498
499
500/**
501 * Initialize the database connections and associated
502 * data structures (create tables and indices
503 * as needed as well).
504 *
505 * @param plugin the plugin context (state for this module)
506 * @return #GNUNET_OK on success
507 */
508static int
509database_setup (struct Plugin *plugin)
510{
511 char *filename;
512
513 if (GNUNET_OK !=
514 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
515 "peerstore-sqlite",
516 "FILENAME",
517 &filename))
518 {
519 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
520 "peerstore-sqlite",
521 "FILENAME");
522 return GNUNET_SYSERR;
523 }
524 if (GNUNET_OK != GNUNET_DISK_file_test (filename))
525 {
526 if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (filename))
527 {
528 GNUNET_break (0);
529 GNUNET_free (filename);
530 return GNUNET_SYSERR;
531 }
532 }
533 /* filename should be UTF-8-encoded. If it isn't, it's a bug */
534 plugin->fn = filename;
535 /* Open database and precompile statements */
536 if (SQLITE_OK != sqlite3_open (plugin->fn,
537 &plugin->dbh))
538 {
539 LOG (GNUNET_ERROR_TYPE_ERROR,
540 _ ("Unable to initialize SQLite: %s.\n"),
541 sqlite3_errmsg (plugin->dbh));
542 return GNUNET_SYSERR;
543 }
544 sql_exec (plugin->dbh,
545 "PRAGMA temp_store=MEMORY");
546 sql_exec (plugin->dbh,
547 "PRAGMA synchronous=OFF");
548 sql_exec (plugin->dbh,
549 "PRAGMA legacy_file_format=OFF");
550 sql_exec (plugin->dbh,
551 "PRAGMA auto_vacuum=INCREMENTAL");
552 sql_exec (plugin->dbh,
553 "PRAGMA encoding=\"UTF-8\"");
554 sql_exec (plugin->dbh,
555 "PRAGMA page_size=4096");
556 sqlite3_busy_timeout (plugin->dbh,
557 BUSY_TIMEOUT_MS);
558 /* Create tables */
559 sql_exec (plugin->dbh,
560 "CREATE TABLE IF NOT EXISTS peerstoredata (\n"
561 " sub_system TEXT NOT NULL,\n"
562 " peer_id BLOB NOT NULL,\n"
563 " key TEXT NOT NULL,\n"
564 " value BLOB NULL,\n"
565 " expiry INT8 NOT NULL" ");");
566 /* Create Indices */
567 if (SQLITE_OK !=
568 sqlite3_exec (plugin->dbh,
569 "CREATE INDEX IF NOT EXISTS peerstoredata_key_index ON peerstoredata (sub_system, peer_id, key)",
570 NULL,
571 NULL,
572 NULL))
573 {
574 LOG (GNUNET_ERROR_TYPE_ERROR,
575 _ ("Unable to create indices: %s.\n"),
576 sqlite3_errmsg (plugin->dbh));
577 return GNUNET_SYSERR;
578 }
579 /* Prepare statements */
580
581 sql_prepare (plugin->dbh,
582 "INSERT INTO peerstoredata (sub_system, peer_id, key, value, expiry)"
583 " VALUES (?,?,?,?,?);",
584 &plugin->insert_peerstoredata);
585 sql_prepare (plugin->dbh,
586 "SELECT sub_system,peer_id,key,value,expiry FROM peerstoredata"
587 " WHERE sub_system = ?",
588 &plugin->select_peerstoredata);
589 sql_prepare (plugin->dbh,
590 "SELECT sub_system,peer_id,key,value,expiry FROM peerstoredata"
591 " WHERE sub_system = ?"
592 " AND peer_id = ?",
593 &plugin->select_peerstoredata_by_pid);
594 sql_prepare (plugin->dbh,
595 "SELECT sub_system,peer_id,key,value,expiry FROM peerstoredata"
596 " WHERE sub_system = ?"
597 " AND key = ?",
598 &plugin->select_peerstoredata_by_key);
599 sql_prepare (plugin->dbh,
600 "SELECT sub_system,peer_id,key,value,expiry FROM peerstoredata"
601 " WHERE sub_system = ?"
602 " AND peer_id = ?" " AND key = ?",
603 &plugin->select_peerstoredata_by_all);
604 sql_prepare (plugin->dbh,
605 "DELETE FROM peerstoredata"
606 " WHERE expiry < ?",
607 &plugin->expire_peerstoredata);
608 sql_prepare (plugin->dbh,
609 "DELETE FROM peerstoredata"
610 " WHERE sub_system = ?"
611 " AND peer_id = ?" " AND key = ?",
612 &plugin->delete_peerstoredata);
613 return GNUNET_OK;
614}
615
616
617/**
618 * Shutdown database connection and associate data
619 * structures.
620 * @param plugin the plugin context (state for this module)
621 */
622static void
623database_shutdown (struct Plugin *plugin)
624{
625 int result;
626 sqlite3_stmt *stmt;
627
628 while (NULL != (stmt = sqlite3_next_stmt (plugin->dbh,
629 NULL)))
630 {
631 result = sqlite3_finalize (stmt);
632 if (SQLITE_OK != result)
633 LOG (GNUNET_ERROR_TYPE_WARNING,
634 "Failed to close statement %p: %d\n",
635 stmt,
636 result);
637 }
638 if (SQLITE_OK != sqlite3_close (plugin->dbh))
639 LOG_SQLITE (plugin,
640 GNUNET_ERROR_TYPE_ERROR,
641 "sqlite3_close");
642 GNUNET_free (plugin->fn);
643}
644
645
646/**
647 * Entry point for the plugin.
648 *
649 * @param cls The struct GNUNET_CONFIGURATION_Handle.
650 * @return NULL on error, otherwise the plugin context
651 */
652void *
653libgnunet_plugin_peerstore_sqlite_init (void *cls)
654{
655 static struct Plugin plugin;
656 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
657 struct GNUNET_PEERSTORE_PluginFunctions *api;
658
659 if (NULL != plugin.cfg)
660 return NULL; /* can only initialize once! */
661 memset (&plugin,
662 0,
663 sizeof(struct Plugin));
664 plugin.cfg = cfg;
665 if (GNUNET_OK != database_setup (&plugin))
666 {
667 database_shutdown (&plugin);
668 return NULL;
669 }
670 api = GNUNET_new (struct GNUNET_PEERSTORE_PluginFunctions);
671 api->cls = &plugin;
672 api->store_record = &peerstore_sqlite_store_record;
673 api->iterate_records = &peerstore_sqlite_iterate_records;
674 api->expire_records = &peerstore_sqlite_expire_records;
675 LOG (GNUNET_ERROR_TYPE_DEBUG,
676 "Sqlite plugin is running\n");
677 return api;
678}
679
680
681/**
682 * Exit point from the plugin.
683 *
684 * @param cls The plugin context (as returned by "init")
685 * @return Always NULL
686 */
687void *
688libgnunet_plugin_peerstore_sqlite_done (void *cls)
689{
690 struct GNUNET_PEERSTORE_PluginFunctions *api = cls;
691 struct Plugin *plugin = api->cls;
692
693 database_shutdown (plugin);
694 plugin->cfg = NULL;
695 GNUNET_free (api);
696 LOG (GNUNET_ERROR_TYPE_DEBUG,
697 "Sqlite plugin is finished\n");
698 return NULL;
699}
700
701
702/* end of plugin_peerstore_sqlite.c */
diff --git a/src/service/peerstore/test_plugin_peerstore.c b/src/service/peerstore/test_plugin_peerstore.c
deleted file mode 100644
index bce62dda9..000000000
--- a/src/service/peerstore/test_plugin_peerstore.c
+++ /dev/null
@@ -1,224 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2015 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_plugin_namestore.c
22 * @brief Test for the namestore plugins
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_peerstore_plugin.h"
28#include "gnunet_testing_lib.h"
29
30
31static int ok;
32
33/**
34 * Name of plugin under test.
35 */
36static const char *plugin_name;
37
38
39static struct GNUNET_PEERSTORE_PluginFunctions *psp;
40
41static struct GNUNET_PeerIdentity p1;
42
43
44/**
45 * Function called when the service shuts down. Unloads our namestore
46 * plugin.
47 *
48 * @param api api to unload
49 */
50static void
51unload_plugin (struct GNUNET_PEERSTORE_PluginFunctions *api)
52{
53 char *libname;
54
55 GNUNET_asprintf (&libname,
56 "libgnunet_plugin_peer_%s",
57 plugin_name);
58 GNUNET_break (NULL ==
59 GNUNET_PLUGIN_unload (libname,
60 api));
61 GNUNET_free (libname);
62}
63
64
65/**
66 * Load the namestore plugin.
67 *
68 * @param cfg configuration to pass
69 * @return NULL on error
70 */
71static struct GNUNET_PEERSTORE_PluginFunctions *
72load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg)
73{
74 struct GNUNET_PEERSTORE_PluginFunctions *ret;
75 char *libname;
76
77 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
78 _ ("Loading `%s' peer plugin\n"),
79 plugin_name);
80 GNUNET_asprintf (&libname,
81 "libgnunet_plugin_peerstore_%s",
82 plugin_name);
83 if (NULL == (ret = GNUNET_PLUGIN_load (libname,
84 (void *) cfg)))
85 {
86 fprintf (stderr,
87 "Failed to load plugin `%s'!\n",
88 plugin_name);
89 GNUNET_free (libname);
90 return NULL;
91 }
92 GNUNET_free (libname);
93 return ret;
94}
95
96
97static void
98test_record (void *cls,
99 const struct GNUNET_PEERSTORE_Record *record,
100 const char *error)
101{
102 const struct GNUNET_PeerIdentity *id = cls;
103 const char*testval = "test_val";
104
105 if (NULL == record)
106 {
107 unload_plugin (psp);
108 return;
109 }
110 GNUNET_assert (0 == memcmp (&record->peer,
111 id,
112 sizeof(struct GNUNET_PeerIdentity)));
113 GNUNET_assert (0 == strcmp ("subsys",
114 record->sub_system));
115 GNUNET_assert (0 == strcmp ("key",
116 record->key));
117 GNUNET_assert (0 == memcmp (testval,
118 record->value,
119 strlen (testval)));
120 ok = 0;
121}
122
123
124static void
125get_record (struct GNUNET_PEERSTORE_PluginFunctions *psp,
126 const struct GNUNET_PeerIdentity *identity)
127{
128 GNUNET_assert (GNUNET_OK ==
129 psp->iterate_records (psp->cls,
130 "subsys",
131 identity,
132 "key",
133 &test_record,
134 (void *) identity));
135}
136
137
138static void
139store_cont (void *cls,
140 int status)
141{
142 GNUNET_assert (GNUNET_OK == status);
143 get_record (psp,
144 &p1);
145}
146
147
148static void
149put_record (struct GNUNET_PEERSTORE_PluginFunctions *psp,
150 const struct GNUNET_PeerIdentity *identity)
151{
152 GNUNET_assert (GNUNET_OK ==
153 psp->store_record (psp->cls,
154 "subsys",
155 identity,
156 "key",
157 "test_value",
158 strlen ("test_value"),
159 GNUNET_TIME_absolute_get (),
160 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
161 &store_cont,
162 NULL));
163}
164
165
166static void
167run (void *cls,
168 char *const *args,
169 const char *cfgfile,
170 const struct GNUNET_CONFIGURATION_Handle *cfg)
171{
172 ok = 1;
173 psp = load_plugin (cfg);
174 if (NULL == psp)
175 {
176 fprintf (stderr,
177 "%s",
178 "Failed to initialize peerstore. Database likely not setup, skipping test.\n");
179 return;
180 }
181 memset (&p1, 1, sizeof(p1));
182 put_record (psp,
183 &p1);
184}
185
186
187int
188main (int argc, char *argv[])
189{
190 char cfg_name[PATH_MAX];
191 char *const xargv[] = {
192 "test-plugin-peerstore",
193 "-c",
194 cfg_name,
195 NULL
196 };
197 struct GNUNET_GETOPT_CommandLineOption options[] = {
198 GNUNET_GETOPT_OPTION_END
199 };
200
201 GNUNET_log_setup ("test-plugin-peerstore",
202 "WARNING",
203 NULL);
204 plugin_name = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]);
205 GNUNET_snprintf (cfg_name,
206 sizeof(cfg_name),
207 "test_plugin_peerstore_%s.conf",
208 plugin_name);
209 GNUNET_PROGRAM_run ((sizeof(xargv) / sizeof(char *)) - 1,
210 xargv,
211 "test-plugin-peerstore",
212 "nohelp",
213 options,
214 &run,
215 NULL);
216 if (ok != 0)
217 fprintf (stderr,
218 "Missed some testcases: %d\n",
219 ok);
220 return ok;
221}
222
223
224/* end of test_plugin_peerstore.c */
diff --git a/src/service/peerstore/test_plugin_peerstore_flat.conf b/src/service/peerstore/test_plugin_peerstore_flat.conf
deleted file mode 100644
index c55b1e9d6..000000000
--- a/src/service/peerstore/test_plugin_peerstore_flat.conf
+++ /dev/null
@@ -1,5 +0,0 @@
1[peerstore-flat]
2FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-flat/flatdb
3
4[peerstore]
5# PREFIX = valgrind --log-file=/home/schanzen/dev/gnunet/src/peerstore/vg_log
diff --git a/src/service/peerstore/test_plugin_peerstore_sqlite.conf b/src/service/peerstore/test_plugin_peerstore_sqlite.conf
deleted file mode 100644
index dcf1fc1a4..000000000
--- a/src/service/peerstore/test_plugin_peerstore_sqlite.conf
+++ /dev/null
@@ -1,2 +0,0 @@
1[peerstore-sqlite]
2FILENAME = $GNUNET_TMP/gnunet-test-plugin-peerstore-sqlite/sqlite.db