aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2024-02-23 15:42:20 +0100
committerMartin Schanzenbach <schanzen@gnunet.org>2024-02-23 15:42:32 +0100
commit83dda01ce3bb6c9af87e73addc1275a542fc7fbd (patch)
tree15bb13d1ea4af12108741d02b1e821fbfbda4730
parentd8a247e343a85d0e184aeebdab9c26f85afb320c (diff)
downloadgnunet-dev/schanzen/peerstore_cleanup.tar.gz
gnunet-dev/schanzen/peerstore_cleanup.zip
PEERSTORE: Deprecate and remove flat plugindev/schanzen/peerstore_cleanup
-rw-r--r--src/plugin/peerstore/Makefile.am25
-rw-r--r--src/plugin/peerstore/plugin_peerstore_flat.c606
-rw-r--r--src/plugin/peerstore/test_plugin_peerstore_flat.conf5
3 files changed, 2 insertions, 634 deletions
diff --git a/src/plugin/peerstore/Makefile.am b/src/plugin/peerstore/Makefile.am
index 225e9a71e..7202aef84 100644
--- a/src/plugin/peerstore/Makefile.am
+++ b/src/plugin/peerstore/Makefile.am
@@ -11,18 +11,6 @@ if USE_COVERAGE
11 AM_CFLAGS = -fprofile-arcs -ftest-coverage 11 AM_CFLAGS = -fprofile-arcs -ftest-coverage
12endif 12endif
13 13
14if HAVE_EXPERIMENTAL
15FLAT_PLUGIN = libgnunet_plugin_peerstore_flat.la
16FLAT_TESTS = test_plugin_peerstore_flat
17libgnunet_plugin_peerstore_flat_la_SOURCES = \
18 plugin_peerstore_flat.c
19libgnunet_plugin_peerstore_flat_la_LIBADD = \
20 $(top_builddir)/src/lib/util/libgnunetutil.la $(XLIBS) \
21 $(LTLIBINTL)
22libgnunet_plugin_peerstore_flat_la_LDFLAGS = \
23 $(GN_PLUGIN_LDFLAGS)
24endif
25
26if HAVE_SQLITE 14if HAVE_SQLITE
27SQLITE_PLUGIN = libgnunet_plugin_peerstore_sqlite.la 15SQLITE_PLUGIN = libgnunet_plugin_peerstore_sqlite.la
28SQLITE_TESTS = test_plugin_peerstore_sqlite 16SQLITE_TESTS = test_plugin_peerstore_sqlite
@@ -38,8 +26,7 @@ libgnunet_plugin_peerstore_sqlite_la_LDFLAGS = \
38endif 26endif
39 27
40plugin_LTLIBRARIES = \ 28plugin_LTLIBRARIES = \
41 $(SQLITE_PLUGIN) \ 29 $(SQLITE_PLUGIN)
42 $(FLAT_PLUGIN)
43 30
44test_plugin_peerstore_sqlite_SOURCES = \ 31test_plugin_peerstore_sqlite_SOURCES = \
45 test_plugin_peerstore.c 32 test_plugin_peerstore.c
@@ -47,18 +34,10 @@ test_plugin_peerstore_sqlite_LDADD = \
47 $(top_builddir)/src/service/testing/libgnunettesting.la \ 34 $(top_builddir)/src/service/testing/libgnunettesting.la \
48 $(top_builddir)/src/lib/util/libgnunetutil.la 35 $(top_builddir)/src/lib/util/libgnunetutil.la
49 36
50test_plugin_peerstore_flat_SOURCES = \
51 test_plugin_peerstore.c
52test_plugin_peerstore_flat_LDADD = \
53 $(top_builddir)/src/service/testing/libgnunettesting.la \
54 $(top_builddir)/src/lib/util/libgnunetutil.la
55
56check_PROGRAMS = \ 37check_PROGRAMS = \
57 $(SQLITE_TESTS) \ 38 $(SQLITE_TESTS)
58 $(FLAT_TESTS)
59 39
60EXTRA_DIST = \ 40EXTRA_DIST = \
61 test_plugin_peerstore_flat.conf \
62 test_plugin_peerstore_sqlite.conf 41 test_plugin_peerstore_sqlite.conf
63 42
64if ENABLE_TEST_RUN 43if ENABLE_TEST_RUN
diff --git a/src/plugin/peerstore/plugin_peerstore_flat.c b/src/plugin/peerstore/plugin_peerstore_flat.c
deleted file mode 100644
index cc304d4db..000000000
--- a/src/plugin/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 "../../service/peerstore/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/plugin/peerstore/test_plugin_peerstore_flat.conf b/src/plugin/peerstore/test_plugin_peerstore_flat.conf
deleted file mode 100644
index c55b1e9d6..000000000
--- a/src/plugin/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