aboutsummaryrefslogtreecommitdiff
path: root/src/peerstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/peerstore')
-rw-r--r--src/peerstore/.gitignore9
-rw-r--r--src/peerstore/Makefile.am147
-rw-r--r--src/peerstore/gnunet-peerstore.c97
-rw-r--r--src/peerstore/gnunet-service-peerstore.c610
-rw-r--r--src/peerstore/peerstore.conf.in13
-rw-r--r--src/peerstore/peerstore.h108
-rw-r--r--src/peerstore/peerstore_api.c939
-rw-r--r--src/peerstore/peerstore_common.c193
-rw-r--r--src/peerstore/peerstore_common.h82
-rw-r--r--src/peerstore/perf_peerstore_store.c109
-rw-r--r--src/peerstore/plugin_peerstore_flat.c606
-rw-r--r--src/peerstore/plugin_peerstore_sqlite.c702
-rw-r--r--src/peerstore/test_peerstore_api_data.conf14
-rw-r--r--src/peerstore/test_peerstore_api_iterate.c176
-rw-r--r--src/peerstore/test_peerstore_api_store.c233
-rw-r--r--src/peerstore/test_peerstore_api_sync.c253
-rw-r--r--src/peerstore/test_peerstore_api_watch.c102
-rw-r--r--src/peerstore/test_plugin_peerstore.c224
-rw-r--r--src/peerstore/test_plugin_peerstore_flat.conf5
-rw-r--r--src/peerstore/test_plugin_peerstore_sqlite.conf2
20 files changed, 0 insertions, 4624 deletions
diff --git a/src/peerstore/.gitignore b/src/peerstore/.gitignore
deleted file mode 100644
index 7fc22bbdb..000000000
--- a/src/peerstore/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
1gnunet-service-peerstore
2gnunet-peerstore
3perf_peerstore_store
4test_peerstore_api_iterate
5test_peerstore_api_store
6test_peerstore_api_sync
7test_peerstore_api_watch
8test_plugin_peerstore_sqlite
9test_plugin_peerstore_flat
diff --git a/src/peerstore/Makefile.am b/src/peerstore/Makefile.am
deleted file mode 100644
index d9904e59d..000000000
--- a/src/peerstore/Makefile.am
+++ /dev/null
@@ -1,147 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8libexecdir= $(pkglibdir)/libexec/
9
10dist_pkgcfg_DATA = \
11 peerstore.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = -fprofile-arcs -ftest-coverage
15endif
16
17bin_PROGRAMS = \
18 gnunet-peerstore
19
20libexec_PROGRAMS = \
21 gnunet-service-peerstore
22
23lib_LTLIBRARIES = \
24 libgnunetpeerstore.la
25
26gnunet_peerstore_SOURCES = \
27 gnunet-peerstore.c
28gnunet_peerstore_LDADD = \
29 $(top_builddir)/src/util/libgnunetutil.la \
30 libgnunetpeerstore.la \
31 $(GN_LIBINTL)
32
33gnunet_service_peerstore_SOURCES = \
34 gnunet-service-peerstore.c \
35 peerstore_common.c peerstore_common.h \
36 peerstore.h
37gnunet_service_peerstore_CFLAGS = $(AM_CFLAGS)
38gnunet_service_peerstore_LDADD = \
39 $(top_builddir)/src/util/libgnunetutil.la \
40 $(GN_LIBINTL)
41
42libgnunetpeerstore_la_SOURCES = \
43 peerstore_api.c \
44 peerstore_common.c
45libgnunetpeerstore_la_LIBADD = \
46 $(top_builddir)/src/util/libgnunetutil.la
47libgnunetpeerstore_la_LDFLAGS = \
48 $(GN_LIBINTL) \
49 $(GN_LIB_LDFLAGS)
50
51if HAVE_EXPERIMENTAL
52FLAT_PLUGIN = libgnunet_plugin_peerstore_flat.la
53FLAT_TESTS = test_plugin_peerstore_flat
54libgnunet_plugin_peerstore_flat_la_SOURCES = \
55 plugin_peerstore_flat.c
56libgnunet_plugin_peerstore_flat_la_LIBADD = \
57 libgnunetpeerstore.la \
58 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
59 $(LTLIBINTL)
60libgnunet_plugin_peerstore_flat_la_LDFLAGS = \
61 $(GN_PLUGIN_LDFLAGS)
62endif
63
64if HAVE_SQLITE
65SQLITE_PLUGIN = libgnunet_plugin_peerstore_sqlite.la
66SQLITE_TESTS = test_plugin_peerstore_sqlite
67libgnunet_plugin_peerstore_sqlite_la_SOURCES = \
68 plugin_peerstore_sqlite.c
69libgnunet_plugin_peerstore_sqlite_la_LIBADD = \
70 libgnunetpeerstore.la \
71 $(top_builddir)/src/sq/libgnunetsq.la \
72 $(top_builddir)/src/util/libgnunetutil.la \
73 $(XLIBS) -lsqlite3 \
74 $(LTLIBINTL)
75libgnunet_plugin_peerstore_sqlite_la_LDFLAGS = \
76 $(GN_PLUGIN_LDFLAGS)
77endif
78
79plugin_LTLIBRARIES = \
80 $(SQLITE_PLUGIN) \
81 $(FLAT_PLUGIN)
82
83test_plugin_peerstore_sqlite_SOURCES = \
84 test_plugin_peerstore.c
85test_plugin_peerstore_sqlite_LDADD = \
86 $(top_builddir)/src/testing/libgnunettesting.la \
87 $(top_builddir)/src/util/libgnunetutil.la
88
89test_plugin_peerstore_flat_SOURCES = \
90 test_plugin_peerstore.c
91test_plugin_peerstore_flat_LDADD = \
92 $(top_builddir)/src/testing/libgnunettesting.la \
93 $(top_builddir)/src/util/libgnunetutil.la
94
95check_PROGRAMS = \
96 test_peerstore_api_store \
97 test_peerstore_api_iterate \
98 test_peerstore_api_watch \
99 test_peerstore_api_sync \
100 perf_peerstore_store \
101 $(SQLITE_TESTS) \
102 $(FLAT_TESTS)
103
104EXTRA_DIST = \
105 test_peerstore_api_data.conf \
106 test_plugin_peerstore_flat.conf \
107 test_plugin_peerstore_sqlite.conf
108
109if ENABLE_TEST_RUN
110AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
111TESTS = $(check_PROGRAMS)
112endif
113
114test_peerstore_api_store_SOURCES = \
115 test_peerstore_api_store.c
116test_peerstore_api_store_LDADD = \
117 libgnunetpeerstore.la \
118 $(top_builddir)/src/testing/libgnunettesting.la \
119 $(top_builddir)/src/util/libgnunetutil.la
120
121test_peerstore_api_iterate_SOURCES = \
122 test_peerstore_api_iterate.c
123test_peerstore_api_iterate_LDADD = \
124 libgnunetpeerstore.la \
125 $(top_builddir)/src/testing/libgnunettesting.la \
126 $(top_builddir)/src/util/libgnunetutil.la
127
128test_peerstore_api_watch_SOURCES = \
129 test_peerstore_api_watch.c
130test_peerstore_api_watch_LDADD = \
131 libgnunetpeerstore.la \
132 $(top_builddir)/src/testing/libgnunettesting.la \
133 $(top_builddir)/src/util/libgnunetutil.la
134
135test_peerstore_api_sync_SOURCES = \
136 test_peerstore_api_sync.c
137test_peerstore_api_sync_LDADD = \
138 libgnunetpeerstore.la \
139 $(top_builddir)/src/testing/libgnunettesting.la \
140 $(top_builddir)/src/util/libgnunetutil.la
141
142perf_peerstore_store_SOURCES = \
143 perf_peerstore_store.c
144perf_peerstore_store_LDADD = \
145 libgnunetpeerstore.la \
146 $(top_builddir)/src/testing/libgnunettesting.la \
147 $(top_builddir)/src/util/libgnunetutil.la
diff --git a/src/peerstore/gnunet-peerstore.c b/src/peerstore/gnunet-peerstore.c
deleted file mode 100644
index 11313b5d3..000000000
--- a/src/peerstore/gnunet-peerstore.c
+++ /dev/null
@@ -1,97 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
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/gnunet-peerstore.c
23 * @brief peerstore tool
24 * @author Omar Tarabai
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_peerstore_service.h"
29
30static int ret;
31
32/*
33 * Handle to PEERSTORE service
34 */
35static struct GNUNET_PEERSTORE_Handle *peerstore_handle;
36
37
38/**
39 * Run on shutdown
40 *
41 * @param cls unused
42 */
43static void
44shutdown_task (void *cls)
45{
46 if (NULL != peerstore_handle)
47 {
48 GNUNET_PEERSTORE_disconnect (peerstore_handle, GNUNET_YES);
49 peerstore_handle = NULL;
50 }
51}
52
53
54/**
55 * Main function that will be run by the scheduler.
56 *
57 * @param cls closure
58 * @param args remaining command-line arguments
59 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
60 * @param cfg configuration
61 */
62static void
63run (void *cls,
64 char *const *args,
65 const char *cfgfile,
66 const struct GNUNET_CONFIGURATION_Handle *cfg)
67{
68 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
69 NULL);
70 peerstore_handle = GNUNET_PEERSTORE_connect (cfg);
71 GNUNET_assert (NULL != peerstore_handle);
72 ret = 0;
73}
74
75
76/**
77 * The main function to peerstore.
78 *
79 * @param argc number of arguments from the command line
80 * @param argv command line arguments
81 * @return 0 ok, 1 on error
82 */
83int
84main (int argc, char *const *argv)
85{
86 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
87 GNUNET_GETOPT_OPTION_END
88 };
89
90 return (GNUNET_OK ==
91 GNUNET_PROGRAM_run (argc, argv, "gnunet-peerstore [options [value]]",
92 gettext_noop ("peerstore"), options, &run,
93 NULL)) ? ret : 1;
94}
95
96
97/* end of gnunet-peerstore.c */
diff --git a/src/peerstore/gnunet-service-peerstore.c b/src/peerstore/gnunet-service-peerstore.c
deleted file mode 100644
index 959d088f9..000000000
--- a/src/peerstore/gnunet-service-peerstore.c
+++ /dev/null
@@ -1,610 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014, 2015, 2016 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/gnunet-service-peerstore.c
23 * @brief peerstore service implementation
24 * @author Omar Tarabai
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "peerstore.h"
29#include "gnunet_peerstore_plugin.h"
30#include "peerstore_common.h"
31
32
33/**
34 * Interval for expired records cleanup (in seconds)
35 */
36#define EXPIRED_RECORDS_CLEANUP_INTERVAL 300 /* 5mins */
37
38/**
39 * Our configuration.
40 */
41static const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43/**
44 * Database plugin library name
45 */
46static char *db_lib_name;
47
48/**
49 * Database handle
50 */
51static struct GNUNET_PEERSTORE_PluginFunctions *db;
52
53/**
54 * Hashmap with all watch requests
55 */
56static struct GNUNET_CONTAINER_MultiHashMap *watchers;
57
58/**
59 * Task run to clean up expired records.
60 */
61static struct GNUNET_SCHEDULER_Task *expire_task;
62
63/**
64 * Are we in the process of shutting down the service? #GNUNET_YES / #GNUNET_NO
65 */
66static int in_shutdown;
67
68/**
69 * Number of connected clients.
70 */
71static unsigned int num_clients;
72
73
74/**
75 * Perform the actual shutdown operations
76 */
77static void
78do_shutdown ()
79{
80 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81 "Shutting down peerstore, bye.\n");
82 if (NULL != db_lib_name)
83 {
84 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db));
85 GNUNET_free (db_lib_name);
86 db_lib_name = NULL;
87 }
88 if (NULL != watchers)
89 {
90 GNUNET_CONTAINER_multihashmap_destroy (watchers);
91 watchers = NULL;
92 }
93 if (NULL != expire_task)
94 {
95 GNUNET_SCHEDULER_cancel (expire_task);
96 expire_task = NULL;
97 }
98 GNUNET_SCHEDULER_shutdown ();
99}
100
101
102/**
103 * Task run during shutdown.
104 *
105 * @param cls unused
106 */
107static void
108shutdown_task (void *cls)
109{
110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
111 "Priming PEERSTORE for shutdown.\n");
112 in_shutdown = GNUNET_YES;
113 if (0 == num_clients) /* Only when no connected clients. */
114 do_shutdown ();
115}
116
117
118/* Forward declaration */
119static void
120expire_records_continuation (void *cls, int success);
121
122
123/**
124 * Deletes any expired records from storage
125 */
126static void
127cleanup_expired_records (void *cls)
128{
129 int ret;
130
131 expire_task = NULL;
132 GNUNET_assert (NULL != db);
133 ret = db->expire_records (db->cls,
134 GNUNET_TIME_absolute_get (),
135 &expire_records_continuation,
136 NULL);
137 if (GNUNET_OK != ret)
138 {
139 GNUNET_assert (NULL == expire_task);
140 expire_task = GNUNET_SCHEDULER_add_delayed (
141 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
142 EXPIRED_RECORDS_CLEANUP_INTERVAL),
143 &cleanup_expired_records,
144 NULL);
145 }
146}
147
148
149/**
150 * Continuation to expire_records called by the peerstore plugin
151 *
152 * @param cls unused
153 * @param success count of records deleted or #GNUNET_SYSERR
154 */
155static void
156expire_records_continuation (void *cls, int success)
157{
158 if (success > 0)
159 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%d records expired.\n", success);
160 GNUNET_assert (NULL == expire_task);
161 expire_task = GNUNET_SCHEDULER_add_delayed (
162 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
163 EXPIRED_RECORDS_CLEANUP_INTERVAL),
164 &cleanup_expired_records,
165 NULL);
166}
167
168
169/**
170 * A client disconnected. Remove all of its data structure entries.
171 *
172 * @param cls closure, NULL
173 * @param client identification of the client
174 * @param mq the message queue
175 * @return
176 */
177static void *
178client_connect_cb (void *cls,
179 struct GNUNET_SERVICE_Client *client,
180 struct GNUNET_MQ_Handle *mq)
181{
182 num_clients++;
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184 "A client connected (now %u)\n", num_clients);
185 return client;
186}
187
188
189/**
190 * Search for a disconnected client and remove it
191 *
192 * @param cls closuer, a `struct GNUNET_SERVICE_Client`
193 * @param key hash of record key
194 * @param value the watcher client, a `struct GNUNET_SERVICE_Client *`
195 * @return #GNUNET_OK to continue iterating
196 */
197static int
198client_disconnect_it (void *cls, const struct GNUNET_HashCode *key, void *value)
199{
200 if (value == cls)
201 {
202 GNUNET_assert (GNUNET_YES ==
203 GNUNET_CONTAINER_multihashmap_remove (watchers, key, value));
204 num_clients++; /* Watchers do not count */
205 }
206 return GNUNET_OK;
207}
208
209
210/**
211 * A client disconnected. Remove all of its data structure entries.
212 *
213 * @param cls closure, NULL
214 * @param client identification of the client
215 */
216static void
217client_disconnect_cb (void *cls,
218 struct GNUNET_SERVICE_Client *client,
219 void *app_cls)
220{
221 num_clients--;
222 if (NULL != watchers)
223 GNUNET_CONTAINER_multihashmap_iterate (watchers,
224 &client_disconnect_it,
225 client);
226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
227 "A client disconnected (%u remaining).\n",
228 num_clients);
229 if ((0 == num_clients) && in_shutdown)
230 do_shutdown ();
231}
232
233
234/**
235 * Function called by for each matching record.
236 *
237 * @param cls closure
238 * @param record peerstore record found
239 * @param emsg error message or NULL if no errors
240 * @return #GNUNET_YES to continue iteration
241 */
242static void
243record_iterator (void *cls,
244 const struct GNUNET_PEERSTORE_Record *record,
245 const char *emsg)
246{
247 struct GNUNET_PEERSTORE_Record *cls_record = cls;
248 struct GNUNET_MQ_Envelope *env;
249
250 if (NULL == record)
251 {
252 /* No more records */
253 struct GNUNET_MessageHeader *endmsg;
254
255 env = GNUNET_MQ_msg (endmsg, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END);
256 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cls_record->client), env);
257 if (NULL == emsg)
258 {
259 GNUNET_SERVICE_client_continue (cls_record->client);
260 }
261 else
262 {
263 GNUNET_break (0);
264 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate: %s\n", emsg);
265 GNUNET_SERVICE_client_drop (cls_record->client);
266 }
267 PEERSTORE_destroy_record (cls_record);
268 return;
269 }
270
271 env = PEERSTORE_create_record_mq_envelope (
272 record->sub_system,
273 &record->peer,
274 record->key,
275 record->value,
276 record->value_size,
277 record->expiry,
278 0,
279 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_RECORD);
280 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cls_record->client), env);
281}
282
283
284/**
285 * Iterator over all watcher clients
286 * to notify them of a new record
287 *
288 * @param cls closure, a `struct GNUNET_PEERSTORE_Record *`
289 * @param key hash of record key
290 * @param value the watcher client, a `struct GNUNET_SERVICE_Client *`
291 * @return #GNUNET_YES to continue iterating
292 */
293static int
294watch_notifier_it (void *cls, const struct GNUNET_HashCode *key, void *value)
295{
296 struct GNUNET_PEERSTORE_Record *record = cls;
297 struct GNUNET_SERVICE_Client *client = value;
298 struct GNUNET_MQ_Envelope *env;
299
300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found a watcher to update.\n");
301 env = PEERSTORE_create_record_mq_envelope (
302 record->sub_system,
303 &record->peer,
304 record->key,
305 record->value,
306 record->value_size,
307 record->expiry,
308 0,
309 GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_RECORD);
310 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
311 return GNUNET_YES;
312}
313
314
315/**
316 * Given a new record, notifies watchers
317 *
318 * @param record changed record to update watchers with
319 */
320static void
321watch_notifier (struct GNUNET_PEERSTORE_Record *record)
322{
323 struct GNUNET_HashCode keyhash;
324
325 PEERSTORE_hash_key (record->sub_system, &record->peer, record->key, &keyhash);
326 GNUNET_CONTAINER_multihashmap_get_multiple (watchers,
327 &keyhash,
328 &watch_notifier_it,
329 record);
330}
331
332
333/**
334 * Handle a watch cancel request from client
335 *
336 * @param cls identification of the client
337 * @param hm the actual message
338 */
339static void
340handle_watch_cancel (void *cls, const struct StoreKeyHashMessage *hm)
341{
342 struct GNUNET_SERVICE_Client *client = cls;
343
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a watch cancel request.\n");
345 if (GNUNET_OK !=
346 GNUNET_CONTAINER_multihashmap_remove (watchers, &hm->keyhash, client))
347 {
348 GNUNET_break (0);
349 GNUNET_SERVICE_client_drop (client);
350 return;
351 }
352 num_clients++;
353 GNUNET_SERVICE_client_continue (client);
354}
355
356
357/**
358 * Handle a watch request from client
359 *
360 * @param cls identification of the client
361 * @param hm the actual message
362 */
363static void
364handle_watch (void *cls, const struct StoreKeyHashMessage *hm)
365{
366 struct GNUNET_SERVICE_Client *client = cls;
367
368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a watch request.\n");
369 num_clients--; /* do not count watchers */
370 GNUNET_SERVICE_client_mark_monitor (client);
371 GNUNET_CONTAINER_multihashmap_put (watchers,
372 &hm->keyhash,
373 client,
374 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
375 GNUNET_SERVICE_client_continue (client);
376}
377
378
379/**
380 * Check an iterate request from client
381 *
382 * @param cls client identification of the client
383 * @param srm the actual message
384 * @return #GNUNET_OK if @a srm is well-formed
385 */
386static int
387check_iterate (void *cls, const struct StoreRecordMessage *srm)
388{
389 struct GNUNET_PEERSTORE_Record *record;
390
391 record = PEERSTORE_parse_record_message (srm);
392 if (NULL == record)
393 {
394 GNUNET_break (0);
395 return GNUNET_SYSERR;
396 }
397 if (NULL == record->sub_system)
398 {
399 GNUNET_break (0);
400 PEERSTORE_destroy_record (record);
401 return GNUNET_SYSERR;
402 }
403 PEERSTORE_destroy_record (record);
404 return GNUNET_OK;
405}
406
407
408/**
409 * Handle an iterate request from client
410 *
411 * @param cls identification of the client
412 * @param srm the actual message
413 */
414static void
415handle_iterate (void *cls, const struct StoreRecordMessage *srm)
416{
417 struct GNUNET_SERVICE_Client *client = cls;
418 struct GNUNET_PEERSTORE_Record *record;
419
420 record = PEERSTORE_parse_record_message (srm);
421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
422 "Iterate request: ss `%s', peer `%s', key `%s'\n",
423 record->sub_system,
424 GNUNET_i2s (&record->peer),
425 (NULL == record->key) ? "NULL" : record->key);
426 record->client = client;
427 if (GNUNET_OK !=
428 db->iterate_records (db->cls,
429 record->sub_system,
430 (ntohs (srm->peer_set)) ? &record->peer : NULL,
431 record->key,
432 &record_iterator,
433 record))
434 {
435 GNUNET_break (0);
436 GNUNET_SERVICE_client_drop (client);
437 PEERSTORE_destroy_record (record);
438 }
439}
440
441
442/**
443 * Continuation of store_record called by the peerstore plugin
444 *
445 * @param cls closure
446 * @param success result
447 */
448static void
449store_record_continuation (void *cls, int success)
450{
451 struct GNUNET_PEERSTORE_Record *record = cls;
452
453 if (GNUNET_OK == success)
454 {
455 watch_notifier (record);
456 GNUNET_SERVICE_client_continue (record->client);
457 }
458 else
459 {
460 GNUNET_break (0);
461 GNUNET_SERVICE_client_drop (record->client);
462 }
463 PEERSTORE_destroy_record (record);
464}
465
466
467/**
468 * Check a store request from client
469 *
470 * @param cls client identification of the client
471 * @param srm the actual message
472 * @return #GNUNET_OK if @a srm is well-formed
473 */
474static int
475check_store (void *cls, const struct StoreRecordMessage *srm)
476{
477 struct GNUNET_PEERSTORE_Record *record;
478
479 record = PEERSTORE_parse_record_message (srm);
480 if (NULL == record)
481 {
482 GNUNET_break (0);
483 return GNUNET_SYSERR;
484 }
485 if ((NULL == record->sub_system) || (NULL == record->key))
486 {
487 GNUNET_break (0);
488 PEERSTORE_destroy_record (record);
489 return GNUNET_SYSERR;
490 }
491 PEERSTORE_destroy_record (record);
492 return GNUNET_OK;
493}
494
495
496/**
497 * Handle a store request from client
498 *
499 * @param cls client identification of the client
500 * @param srm the actual message
501 */
502static void
503handle_store (void *cls, const struct StoreRecordMessage *srm)
504{
505 struct GNUNET_SERVICE_Client *client = cls;
506 struct GNUNET_PEERSTORE_Record *record;
507
508 record = PEERSTORE_parse_record_message (srm);
509 GNUNET_log (
510 GNUNET_ERROR_TYPE_INFO,
511 "Received a store request. Sub system `%s' Peer `%s Key `%s' Options: %u.\n",
512 record->sub_system,
513 GNUNET_i2s (&record->peer),
514 record->key,
515 (uint32_t) ntohl (srm->options));
516 record->client = client;
517 if (GNUNET_OK != db->store_record (db->cls,
518 record->sub_system,
519 &record->peer,
520 record->key,
521 record->value,
522 record->value_size,
523 record->expiry,
524 ntohl (srm->options),
525 &store_record_continuation,
526 record))
527 {
528 GNUNET_break (0);
529 PEERSTORE_destroy_record (record);
530 GNUNET_SERVICE_client_drop (client);
531 return;
532 }
533}
534
535
536/**
537 * Peerstore service runner.
538 *
539 * @param cls closure
540 * @param c configuration to use
541 * @param service the initialized service
542 */
543static void
544run (void *cls,
545 const struct GNUNET_CONFIGURATION_Handle *c,
546 struct GNUNET_SERVICE_Handle *service)
547{
548 char *database;
549
550 in_shutdown = GNUNET_NO;
551 num_clients = 0;
552 cfg = c;
553 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
554 "peerstore",
555 "DATABASE",
556 &database))
557 {
558 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
559 "peerstore",
560 "DATABASE");
561 GNUNET_SCHEDULER_shutdown ();
562 return;
563 }
564 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_peerstore_%s", database);
565 db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
566 GNUNET_free (database);
567 if (NULL == db)
568 {
569 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
570 _ ("Could not load database backend `%s'\n"),
571 db_lib_name);
572 GNUNET_SCHEDULER_shutdown ();
573 return;
574 }
575 watchers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
576 expire_task = GNUNET_SCHEDULER_add_now (&cleanup_expired_records, NULL);
577 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
578}
579
580
581/**
582 * Define "main" method using service macro.
583 */
584GNUNET_SERVICE_MAIN (
585 "peerstore",
586 GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
587 &run,
588 &client_connect_cb,
589 &client_disconnect_cb,
590 NULL,
591 GNUNET_MQ_hd_var_size (store,
592 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE,
593 struct StoreRecordMessage,
594 NULL),
595 GNUNET_MQ_hd_var_size (iterate,
596 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE,
597 struct StoreRecordMessage,
598 NULL),
599 GNUNET_MQ_hd_fixed_size (watch,
600 GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH,
601 struct StoreKeyHashMessage,
602 NULL),
603 GNUNET_MQ_hd_fixed_size (watch_cancel,
604 GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_CANCEL,
605 struct StoreKeyHashMessage,
606 NULL),
607 GNUNET_MQ_handler_end ());
608
609
610/* end of gnunet-service-peerstore.c */
diff --git a/src/peerstore/peerstore.conf.in b/src/peerstore/peerstore.conf.in
deleted file mode 100644
index a3a7c672b..000000000
--- a/src/peerstore/peerstore.conf.in
+++ /dev/null
@@ -1,13 +0,0 @@
1[peerstore]
2START_ON_DEMAND = @START_ON_DEMAND@
3@JAVAPORT@PORT = 2110
4HOSTNAME = localhost
5BINARY = gnunet-service-peerstore
6UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-peerstore.sock
7UNIX_MATCH_UID = NO
8UNIX_MATCH_GID = YES
9DATABASE = sqlite
10
11[peerstore-sqlite]
12FILENAME = $GNUNET_DATA_HOME/peerstore/sqlite.db
13
diff --git a/src/peerstore/peerstore.h b/src/peerstore/peerstore.h
deleted file mode 100644
index 0dec03443..000000000
--- a/src/peerstore/peerstore.h
+++ /dev/null
@@ -1,108 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 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 peerstore/peerstore.h
22 * @brief IPC messages
23 * @author Omar Tarabai
24 */
25
26#ifndef PEERSTORE_H_
27#define PEERSTORE_H_
28
29#include "gnunet_peerstore_service.h"
30
31
32GNUNET_NETWORK_STRUCT_BEGIN
33/**
34 * Message carrying a PEERSTORE record message
35 */
36struct StoreRecordMessage
37{
38 /**
39 * GNUnet message header
40 */
41 struct GNUNET_MessageHeader header;
42
43 /**
44 * #GNUNET_YES if peer id value set, #GNUNET_NO otherwise
45 */
46 uint16_t peer_set GNUNET_PACKED;
47
48 /**
49 * Size of the sub_system string
50 * Allocated at position 0 after this struct
51 */
52 uint16_t sub_system_size GNUNET_PACKED;
53
54 /**
55 * Peer Identity
56 */
57 struct GNUNET_PeerIdentity peer;
58
59 /**
60 * Expiry time of entry
61 */
62 struct GNUNET_TIME_AbsoluteNBO expiry;
63
64 /**
65 * Size of the key string
66 * Allocated at position 1 after this struct
67 */
68 uint16_t key_size GNUNET_PACKED;
69
70 /**
71 * Size of value blob
72 * Allocated at position 2 after this struct
73 */
74 uint16_t value_size GNUNET_PACKED;
75
76 /**
77 * Options, needed only in case of a
78 * store operation
79 */
80 uint32_t /* enum GNUNET_PEERSTORE_StoreOption */ options GNUNET_PACKED;
81
82 /* Followed by key and value */
83};
84
85
86/**
87 * Message carrying record key hash
88 */
89struct StoreKeyHashMessage
90{
91 /**
92 * GNUnet message header
93 */
94 struct GNUNET_MessageHeader header;
95
96 /**
97 * Always 0, for alignment.
98 */
99 uint32_t reserved GNUNET_PACKED;
100
101 /**
102 * Hash of a record key
103 */
104 struct GNUNET_HashCode keyhash;
105};
106
107GNUNET_NETWORK_STRUCT_END
108#endif
diff --git a/src/peerstore/peerstore_api.c b/src/peerstore/peerstore_api.c
deleted file mode 100644
index 502b38646..000000000
--- a/src/peerstore/peerstore_api.c
+++ /dev/null
@@ -1,939 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013-2016, 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 peerstore/peerstore_api.c
22 * @brief API for peerstore
23 * @author Omar Tarabai
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "peerstore.h"
29#include "peerstore_common.h"
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "peerstore-api", __VA_ARGS__)
32
33/******************************************************************************/
34/************************ DATA STRUCTURES ****************************/
35/******************************************************************************/
36
37/**
38 * Handle to the PEERSTORE service.
39 */
40struct GNUNET_PEERSTORE_Handle
41{
42 /**
43 * Our configuration.
44 */
45 const struct GNUNET_CONFIGURATION_Handle *cfg;
46
47 /**
48 * Message queue
49 */
50 struct GNUNET_MQ_Handle *mq;
51
52 /**
53 * Head of active STORE requests.
54 */
55 struct GNUNET_PEERSTORE_StoreContext *store_head;
56
57 /**
58 * Tail of active STORE requests.
59 */
60 struct GNUNET_PEERSTORE_StoreContext *store_tail;
61
62 /**
63 * Head of active ITERATE requests.
64 */
65 struct GNUNET_PEERSTORE_IterateContext *iterate_head;
66
67 /**
68 * Tail of active ITERATE requests.
69 */
70 struct GNUNET_PEERSTORE_IterateContext *iterate_tail;
71
72 /**
73 * Hashmap of watch requests
74 */
75 struct GNUNET_CONTAINER_MultiHashMap *watches;
76
77 /**
78 * ID of the task trying to reconnect to the service.
79 */
80 struct GNUNET_SCHEDULER_Task *reconnect_task;
81
82 /**
83 * Delay until we try to reconnect.
84 */
85 struct GNUNET_TIME_Relative reconnect_delay;
86
87 /**
88 * Are we in the process of disconnecting but need to sync first?
89 */
90 int disconnecting;
91};
92
93/**
94 * Context for a store request
95 */
96struct GNUNET_PEERSTORE_StoreContext
97{
98 /**
99 * Kept in a DLL.
100 */
101 struct GNUNET_PEERSTORE_StoreContext *next;
102
103 /**
104 * Kept in a DLL.
105 */
106 struct GNUNET_PEERSTORE_StoreContext *prev;
107
108 /**
109 * Handle to the PEERSTORE service.
110 */
111 struct GNUNET_PEERSTORE_Handle *h;
112
113 /**
114 * Continuation called with service response
115 */
116 GNUNET_PEERSTORE_Continuation cont;
117
118 /**
119 * Closure for @e cont
120 */
121 void *cont_cls;
122
123 /**
124 * Which subsystem does the store?
125 */
126 char *sub_system;
127
128 /**
129 * Key for the store operation.
130 */
131 char *key;
132
133 /**
134 * Contains @e size bytes.
135 */
136 void *value;
137
138 /**
139 * Peer the store is for.
140 */
141 struct GNUNET_PeerIdentity peer;
142
143 /**
144 * Number of bytes in @e value.
145 */
146 size_t size;
147
148 /**
149 * When does the value expire?
150 */
151 struct GNUNET_TIME_Absolute expiry;
152
153 /**
154 * Options for the store operation.
155 */
156 enum GNUNET_PEERSTORE_StoreOption options;
157};
158
159/**
160 * Context for a iterate request
161 */
162struct GNUNET_PEERSTORE_IterateContext
163{
164 /**
165 * Kept in a DLL.
166 */
167 struct GNUNET_PEERSTORE_IterateContext *next;
168
169 /**
170 * Kept in a DLL.
171 */
172 struct GNUNET_PEERSTORE_IterateContext *prev;
173
174 /**
175 * Handle to the PEERSTORE service.
176 */
177 struct GNUNET_PEERSTORE_Handle *h;
178
179 /**
180 * Which subsystem does the store?
181 */
182 char *sub_system;
183
184 /**
185 * Peer the store is for.
186 */
187 struct GNUNET_PeerIdentity peer;
188
189 /**
190 * Key for the store operation.
191 */
192 char *key;
193
194 /**
195 * Callback with each matching record
196 */
197 GNUNET_PEERSTORE_Processor callback;
198
199 /**
200 * Closure for @e callback
201 */
202 void *callback_cls;
203
204 /**
205 * #GNUNET_YES if we are currently processing records.
206 */
207 int iterating;
208};
209
210/**
211 * Context for a watch request
212 */
213struct GNUNET_PEERSTORE_WatchContext
214{
215 /**
216 * Kept in a DLL.
217 */
218 struct GNUNET_PEERSTORE_WatchContext *next;
219
220 /**
221 * Kept in a DLL.
222 */
223 struct GNUNET_PEERSTORE_WatchContext *prev;
224
225 /**
226 * Handle to the PEERSTORE service.
227 */
228 struct GNUNET_PEERSTORE_Handle *h;
229
230 /**
231 * Callback with each record received
232 */
233 GNUNET_PEERSTORE_Processor callback;
234
235 /**
236 * Closure for @e callback
237 */
238 void *callback_cls;
239
240 /**
241 * Hash of the combined key
242 */
243 struct GNUNET_HashCode keyhash;
244};
245
246/******************************************************************************/
247/******************* DECLARATIONS *********************/
248/******************************************************************************/
249
250/**
251 * Close the existing connection to PEERSTORE and reconnect.
252 *
253 * @param cls a `struct GNUNET_PEERSTORE_Handle *h`
254 */
255static void
256reconnect (void *cls);
257
258
259/**
260 * Disconnect from the peerstore service.
261 *
262 * @param h peerstore handle to disconnect
263 */
264static void
265disconnect (struct GNUNET_PEERSTORE_Handle *h)
266{
267 struct GNUNET_PEERSTORE_IterateContext *next;
268
269 for (struct GNUNET_PEERSTORE_IterateContext *ic = h->iterate_head; NULL != ic;
270 ic = next)
271 {
272 next = ic->next;
273 if (GNUNET_YES == ic->iterating)
274 {
275 GNUNET_PEERSTORE_Processor icb;
276 void *icb_cls;
277
278 icb = ic->callback;
279 icb_cls = ic->callback_cls;
280 GNUNET_PEERSTORE_iterate_cancel (ic);
281 if (NULL != icb)
282 icb (icb_cls, NULL, "Iteration canceled due to reconnection");
283 }
284 }
285
286 if (NULL != h->mq)
287 {
288 GNUNET_MQ_destroy (h->mq);
289 h->mq = NULL;
290 }
291}
292
293
294/**
295 * Function that will schedule the job that will try
296 * to connect us again to the client.
297 *
298 * @param h peerstore to reconnect
299 */
300static void
301disconnect_and_schedule_reconnect (struct GNUNET_PEERSTORE_Handle *h)
302{
303 GNUNET_assert (NULL == h->reconnect_task);
304 disconnect (h);
305 LOG (GNUNET_ERROR_TYPE_DEBUG,
306 "Scheduling task to reconnect to PEERSTORE service in %s.\n",
307 GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, GNUNET_YES));
308 h->reconnect_task =
309 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
310 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
311}
312
313
314/**
315 * Callback after MQ envelope is sent
316 *
317 * @param cls a `struct GNUNET_PEERSTORE_StoreContext *`
318 */
319static void
320store_request_sent (void *cls)
321{
322 struct GNUNET_PEERSTORE_StoreContext *sc = cls;
323 GNUNET_PEERSTORE_Continuation cont;
324 void *cont_cls;
325
326 cont = sc->cont;
327 cont_cls = sc->cont_cls;
328 GNUNET_PEERSTORE_store_cancel (sc);
329 if (NULL != cont)
330 cont (cont_cls, GNUNET_OK);
331}
332
333
334/******************************************************************************/
335/******************* CONNECTION FUNCTIONS *********************/
336/******************************************************************************/
337
338
339/**
340 * Function called when we had trouble talking to the service.
341 */
342static void
343handle_client_error (void *cls, enum GNUNET_MQ_Error error)
344{
345 struct GNUNET_PEERSTORE_Handle *h = cls;
346
347 LOG (GNUNET_ERROR_TYPE_ERROR,
348 "Received an error notification from MQ of type: %d\n",
349 error);
350 disconnect_and_schedule_reconnect (h);
351}
352
353
354/**
355 * Iterator over previous watches to resend them
356 *
357 * @param cls the `struct GNUNET_PEERSTORE_Handle`
358 * @param key key for the watch
359 * @param value the `struct GNUNET_PEERSTORE_WatchContext *`
360 * @return #GNUNET_YES (continue to iterate)
361 */
362static int
363rewatch_it (void *cls, const struct GNUNET_HashCode *key, void *value)
364{
365 struct GNUNET_PEERSTORE_Handle *h = cls;
366 struct GNUNET_PEERSTORE_WatchContext *wc = value;
367 struct StoreKeyHashMessage *hm;
368 struct GNUNET_MQ_Envelope *ev;
369
370 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH);
371 hm->keyhash = wc->keyhash;
372 GNUNET_MQ_send (h->mq, ev);
373 return GNUNET_YES;
374}
375
376
377/**
378 * Iterator over watch requests to cancel them.
379 *
380 * @param cls unused
381 * @param key key to the watch request
382 * @param value watch context
383 * @return #GNUNET_YES to continue iteration
384 */
385static int
386destroy_watch (void *cls, const struct GNUNET_HashCode *key, void *value)
387{
388 struct GNUNET_PEERSTORE_WatchContext *wc = value;
389
390 GNUNET_PEERSTORE_watch_cancel (wc);
391 return GNUNET_YES;
392}
393
394
395/**
396 * Kill the connection to the service. This can be delayed in case of pending
397 * STORE requests and the user explicitly asked to sync first. Otherwise it is
398 * performed instantly.
399 *
400 * @param h Handle to the service.
401 */
402static void
403final_disconnect (struct GNUNET_PEERSTORE_Handle *h)
404{
405 if (NULL != h->mq)
406 {
407 GNUNET_MQ_destroy (h->mq);
408 h->mq = NULL;
409 }
410 GNUNET_free (h);
411}
412
413
414/**
415 * Connect to the PEERSTORE service.
416 *
417 * @param cfg configuration to use
418 * @return NULL on error
419 */
420struct GNUNET_PEERSTORE_Handle *
421GNUNET_PEERSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
422{
423 struct GNUNET_PEERSTORE_Handle *h;
424
425 h = GNUNET_new (struct GNUNET_PEERSTORE_Handle);
426 h->cfg = cfg;
427 h->disconnecting = GNUNET_NO;
428 reconnect (h);
429 if (NULL == h->mq)
430 {
431 GNUNET_free (h);
432 return NULL;
433 }
434 return h;
435}
436
437
438/**
439 * Disconnect from the PEERSTORE service. Any pending ITERATE and WATCH requests
440 * will be canceled.
441 * Any pending STORE requests will depend on @e snyc_first flag.
442 *
443 * @param h handle to disconnect
444 * @param sync_first send any pending STORE requests before disconnecting
445 */
446void
447GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h, int sync_first)
448{
449 struct GNUNET_PEERSTORE_IterateContext *ic;
450 struct GNUNET_PEERSTORE_StoreContext *sc;
451
452 LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting.\n");
453 if (NULL != h->watches)
454 {
455 GNUNET_CONTAINER_multihashmap_iterate (h->watches, &destroy_watch, NULL);
456 GNUNET_CONTAINER_multihashmap_destroy (h->watches);
457 h->watches = NULL;
458 }
459 while (NULL != (ic = h->iterate_head))
460 {
461 GNUNET_break (0);
462 GNUNET_PEERSTORE_iterate_cancel (ic);
463 }
464 if (NULL != h->store_head)
465 {
466 if (GNUNET_YES == sync_first)
467 {
468 LOG (GNUNET_ERROR_TYPE_DEBUG,
469 "Delaying disconnection due to pending store requests.\n");
470 h->disconnecting = GNUNET_YES;
471 return;
472 }
473 while (NULL != (sc = h->store_head))
474 GNUNET_PEERSTORE_store_cancel (sc);
475 }
476 final_disconnect (h);
477}
478
479
480/******************************************************************************/
481/******************* STORE FUNCTIONS *********************/
482/******************************************************************************/
483
484
485/**
486 * Cancel a store request
487 *
488 * @param sc Store request context
489 */
490void
491GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc)
492{
493 struct GNUNET_PEERSTORE_Handle *h = sc->h;
494
495 GNUNET_CONTAINER_DLL_remove (sc->h->store_head, sc->h->store_tail, sc);
496 GNUNET_free (sc->sub_system);
497 GNUNET_free (sc->value);
498 GNUNET_free (sc->key);
499 GNUNET_free (sc);
500 if ((GNUNET_YES == h->disconnecting) && (NULL == h->store_head))
501 final_disconnect (h);
502}
503
504
505/**
506 * Store a new entry in the PEERSTORE.
507 * Note that stored entries can be lost in some cases
508 * such as power failure.
509 *
510 * @param h Handle to the PEERSTORE service
511 * @param sub_system name of the sub system
512 * @param peer Peer Identity
513 * @param key entry key
514 * @param value entry value BLOB
515 * @param size size of @e value
516 * @param expiry absolute time after which the entry is (possibly) deleted
517 * @param options options specific to the storage operation
518 * @param cont Continuation function after the store request is sent
519 * @param cont_cls Closure for @a cont
520 */
521struct GNUNET_PEERSTORE_StoreContext *
522GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
523 const char *sub_system,
524 const struct GNUNET_PeerIdentity *peer,
525 const char *key,
526 const void *value,
527 size_t size,
528 struct GNUNET_TIME_Absolute expiry,
529 enum GNUNET_PEERSTORE_StoreOption options,
530 GNUNET_PEERSTORE_Continuation cont,
531 void *cont_cls)
532{
533 struct GNUNET_MQ_Envelope *ev;
534 struct GNUNET_PEERSTORE_StoreContext *sc;
535
536 LOG (GNUNET_ERROR_TYPE_DEBUG,
537 "Storing value (size: %lu) for subsystem `%s', peer `%s', key `%s'\n",
538 size,
539 sub_system,
540 GNUNET_i2s (peer),
541 key);
542 ev =
543 PEERSTORE_create_record_mq_envelope (sub_system,
544 peer,
545 key,
546 value,
547 size,
548 expiry,
549 options,
550 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
551 sc = GNUNET_new (struct GNUNET_PEERSTORE_StoreContext);
552
553 sc->sub_system = GNUNET_strdup (sub_system);
554 sc->peer = *peer;
555 sc->key = GNUNET_strdup (key);
556 sc->value = GNUNET_memdup (value, size);
557 sc->size = size;
558 sc->expiry = expiry;
559 sc->options = options;
560 sc->cont = cont;
561 sc->cont_cls = cont_cls;
562 sc->h = h;
563
564 GNUNET_CONTAINER_DLL_insert_tail (h->store_head, h->store_tail, sc);
565 GNUNET_MQ_notify_sent (ev, &store_request_sent, sc);
566 GNUNET_MQ_send (h->mq, ev);
567 return sc;
568}
569
570
571/******************************************************************************/
572/******************* ITERATE FUNCTIONS *********************/
573/******************************************************************************/
574
575
576/**
577 * When a response for iterate request is received
578 *
579 * @param cls a `struct GNUNET_PEERSTORE_Handle *`
580 * @param msg message received
581 */
582static void
583handle_iterate_end (void *cls, const struct GNUNET_MessageHeader *msg)
584{
585 struct GNUNET_PEERSTORE_Handle *h = cls;
586 struct GNUNET_PEERSTORE_IterateContext *ic;
587 GNUNET_PEERSTORE_Processor callback;
588 void *callback_cls;
589
590 ic = h->iterate_head;
591 if (NULL == ic)
592 {
593 LOG (GNUNET_ERROR_TYPE_ERROR,
594 _ ("Unexpected iteration response, this should not happen.\n"));
595 disconnect_and_schedule_reconnect (h);
596 return;
597 }
598 callback = ic->callback;
599 callback_cls = ic->callback_cls;
600 ic->iterating = GNUNET_NO;
601 GNUNET_PEERSTORE_iterate_cancel (ic);
602 if (NULL != callback)
603 callback (callback_cls, NULL, NULL);
604 h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
605}
606
607
608/**
609 * When a response for iterate request is received, check the
610 * message is well-formed.
611 *
612 * @param cls a `struct GNUNET_PEERSTORE_Handle *`
613 * @param msg message received
614 */
615static int
616check_iterate_result (void *cls, const struct StoreRecordMessage *msg)
617{
618 /* we defer validation to #handle_iterate_result */
619 return GNUNET_OK;
620}
621
622
623/**
624 * When a response for iterate request is received
625 *
626 * @param cls a `struct GNUNET_PEERSTORE_Handle *`
627 * @param msg message received
628 */
629static void
630handle_iterate_result (void *cls, const struct StoreRecordMessage *msg)
631{
632 struct GNUNET_PEERSTORE_Handle *h = cls;
633 struct GNUNET_PEERSTORE_IterateContext *ic;
634 GNUNET_PEERSTORE_Processor callback;
635 void *callback_cls;
636 struct GNUNET_PEERSTORE_Record *record;
637
638 ic = h->iterate_head;
639 if (NULL == ic)
640 {
641 LOG (GNUNET_ERROR_TYPE_ERROR,
642 _ ("Unexpected iteration response, this should not happen.\n"));
643 disconnect_and_schedule_reconnect (h);
644 return;
645 }
646 ic->iterating = GNUNET_YES;
647 callback = ic->callback;
648 callback_cls = ic->callback_cls;
649 if (NULL == callback)
650 return;
651 record = PEERSTORE_parse_record_message (msg);
652 if (NULL == record)
653 {
654 callback (callback_cls,
655 NULL,
656 _ ("Received a malformed response from service."));
657 }
658 else
659 {
660 callback (callback_cls, record, NULL);
661 PEERSTORE_destroy_record (record);
662 }
663}
664
665
666/**
667 * Cancel an iterate request
668 * Please do not call after the iterate request is done
669 *
670 * @param ic Iterate request context as returned by GNUNET_PEERSTORE_iterate()
671 */
672void
673GNUNET_PEERSTORE_iterate_cancel (struct GNUNET_PEERSTORE_IterateContext *ic)
674{
675 if (GNUNET_NO == ic->iterating)
676 {
677 GNUNET_CONTAINER_DLL_remove (ic->h->iterate_head, ic->h->iterate_tail, ic);
678 GNUNET_free (ic->sub_system);
679 GNUNET_free (ic->key);
680 GNUNET_free (ic);
681 }
682 else
683 ic->callback = NULL;
684}
685
686
687/**
688 * Iterate over records matching supplied key information
689 *
690 * @param h handle to the PEERSTORE service
691 * @param sub_system name of sub system
692 * @param peer Peer identity (can be NULL)
693 * @param key entry key string (can be NULL)
694 * @param callback function called with each matching record, all NULL's on end
695 * @param callback_cls closure for @a callback
696 * @return Handle to iteration request
697 */
698struct GNUNET_PEERSTORE_IterateContext *
699GNUNET_PEERSTORE_iterate (struct GNUNET_PEERSTORE_Handle *h,
700 const char *sub_system,
701 const struct GNUNET_PeerIdentity *peer,
702 const char *key,
703 GNUNET_PEERSTORE_Processor callback,
704 void *callback_cls)
705{
706 struct GNUNET_MQ_Envelope *ev;
707 struct GNUNET_PEERSTORE_IterateContext *ic;
708
709 ev =
710 PEERSTORE_create_record_mq_envelope (sub_system,
711 peer,
712 key,
713 NULL,
714 0,
715 GNUNET_TIME_UNIT_FOREVER_ABS,
716 0,
717 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE);
718 ic = GNUNET_new (struct GNUNET_PEERSTORE_IterateContext);
719 ic->callback = callback;
720 ic->callback_cls = callback_cls;
721 ic->h = h;
722 ic->sub_system = GNUNET_strdup (sub_system);
723 if (NULL != peer)
724 ic->peer = *peer;
725 if (NULL != key)
726 ic->key = GNUNET_strdup (key);
727 GNUNET_CONTAINER_DLL_insert_tail (h->iterate_head, h->iterate_tail, ic);
728 LOG (GNUNET_ERROR_TYPE_DEBUG,
729 "Sending an iterate request for sub system `%s'\n",
730 sub_system);
731 GNUNET_MQ_send (h->mq, ev);
732 return ic;
733}
734
735
736/******************************************************************************/
737/******************* WATCH FUNCTIONS *********************/
738/******************************************************************************/
739
740/**
741 * When a watch record is received, validate it is well-formed.
742 *
743 * @param cls a `struct GNUNET_PEERSTORE_Handle *`
744 * @param msg message received
745 */
746static int
747check_watch_record (void *cls, const struct StoreRecordMessage *msg)
748{
749 /* we defer validation to #handle_watch_result */
750 return GNUNET_OK;
751}
752
753
754/**
755 * When a watch record is received, process it.
756 *
757 * @param cls a `struct GNUNET_PEERSTORE_Handle *`
758 * @param msg message received
759 */
760static void
761handle_watch_record (void *cls, const struct StoreRecordMessage *msg)
762{
763 struct GNUNET_PEERSTORE_Handle *h = cls;
764 struct GNUNET_PEERSTORE_Record *record;
765 struct GNUNET_HashCode keyhash;
766 struct GNUNET_PEERSTORE_WatchContext *wc;
767
768 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a watch record from service.\n");
769 record = PEERSTORE_parse_record_message (msg);
770 if (NULL == record)
771 {
772 disconnect_and_schedule_reconnect (h);
773 return;
774 }
775 PEERSTORE_hash_key (record->sub_system, &record->peer, record->key, &keyhash);
776 // FIXME: what if there are multiple watches for the same key?
777 wc = GNUNET_CONTAINER_multihashmap_get (h->watches, &keyhash);
778 if (NULL == wc)
779 {
780 LOG (GNUNET_ERROR_TYPE_ERROR,
781 _ ("Received a watch result for a non existing watch.\n"));
782 PEERSTORE_destroy_record (record);
783 disconnect_and_schedule_reconnect (h);
784 return;
785 }
786 if (NULL != wc->callback)
787 wc->callback (wc->callback_cls, record, NULL);
788 h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
789 PEERSTORE_destroy_record (record);
790}
791
792
793/**
794 * Close the existing connection to PEERSTORE and reconnect.
795 *
796 * @param cls a `struct GNUNET_PEERSTORE_Handle *`
797 */
798static void
799reconnect (void *cls)
800{
801 struct GNUNET_PEERSTORE_Handle *h = cls;
802 struct GNUNET_MQ_MessageHandler mq_handlers[] =
803 { GNUNET_MQ_hd_fixed_size (iterate_end,
804 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END,
805 struct GNUNET_MessageHeader,
806 h),
807 GNUNET_MQ_hd_var_size (iterate_result,
808 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_RECORD,
809 struct StoreRecordMessage,
810 h),
811 GNUNET_MQ_hd_var_size (watch_record,
812 GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_RECORD,
813 struct StoreRecordMessage,
814 h),
815 GNUNET_MQ_handler_end () };
816 struct GNUNET_MQ_Envelope *ev;
817
818 h->reconnect_task = NULL;
819 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting...\n");
820 h->mq = GNUNET_CLIENT_connect (h->cfg,
821 "peerstore",
822 mq_handlers,
823 &handle_client_error,
824 h);
825 if (NULL == h->mq)
826 {
827 h->reconnect_task =
828 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
829 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
830 return;
831 }
832 LOG (GNUNET_ERROR_TYPE_DEBUG,
833 "Resending pending requests after reconnect.\n");
834 if (NULL != h->watches)
835 GNUNET_CONTAINER_multihashmap_iterate (h->watches, &rewatch_it, h);
836 for (struct GNUNET_PEERSTORE_IterateContext *ic = h->iterate_head; NULL != ic;
837 ic = ic->next)
838 {
839 ev =
840 PEERSTORE_create_record_mq_envelope (ic->sub_system,
841 &ic->peer,
842 ic->key,
843 NULL,
844 0,
845 GNUNET_TIME_UNIT_FOREVER_ABS,
846 0,
847 GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE);
848 GNUNET_MQ_send (h->mq, ev);
849 }
850 for (struct GNUNET_PEERSTORE_StoreContext *sc = h->store_head; NULL != sc;
851 sc = sc->next)
852 {
853 ev =
854 PEERSTORE_create_record_mq_envelope (sc->sub_system,
855 &sc->peer,
856 sc->key,
857 sc->value,
858 sc->size,
859 sc->expiry,
860 sc->options,
861 GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
862 GNUNET_MQ_notify_sent (ev, &store_request_sent, sc);
863 GNUNET_MQ_send (h->mq, ev);
864 }
865}
866
867
868/**
869 * Cancel a watch request
870 *
871 * @param wc handle to the watch request
872 */
873void
874GNUNET_PEERSTORE_watch_cancel (struct GNUNET_PEERSTORE_WatchContext *wc)
875{
876 struct GNUNET_PEERSTORE_Handle *h = wc->h;
877 struct GNUNET_MQ_Envelope *ev;
878 struct StoreKeyHashMessage *hm;
879
880 LOG (GNUNET_ERROR_TYPE_DEBUG, "Canceling watch.\n");
881 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_CANCEL);
882 hm->keyhash = wc->keyhash;
883 GNUNET_MQ_send (h->mq, ev);
884 GNUNET_assert (
885 GNUNET_YES ==
886 GNUNET_CONTAINER_multihashmap_remove (h->watches, &wc->keyhash, wc));
887 GNUNET_free (wc);
888}
889
890
891/**
892 * Request watching a given key
893 * User will be notified with any new values added to key
894 *
895 * @param h handle to the PEERSTORE service
896 * @param sub_system name of sub system
897 * @param peer Peer identity
898 * @param key entry key string
899 * @param callback function called with each new value
900 * @param callback_cls closure for @a callback
901 * @return Handle to watch request
902 */
903struct GNUNET_PEERSTORE_WatchContext *
904GNUNET_PEERSTORE_watch (struct GNUNET_PEERSTORE_Handle *h,
905 const char *sub_system,
906 const struct GNUNET_PeerIdentity *peer,
907 const char *key,
908 GNUNET_PEERSTORE_Processor callback,
909 void *callback_cls)
910{
911 struct GNUNET_MQ_Envelope *ev;
912 struct StoreKeyHashMessage *hm;
913 struct GNUNET_PEERSTORE_WatchContext *wc;
914
915 ev = GNUNET_MQ_msg (hm, GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH);
916 PEERSTORE_hash_key (sub_system, peer, key, &hm->keyhash);
917 wc = GNUNET_new (struct GNUNET_PEERSTORE_WatchContext);
918 wc->callback = callback;
919 wc->callback_cls = callback_cls;
920 wc->h = h;
921 wc->keyhash = hm->keyhash;
922 if (NULL == h->watches)
923 h->watches = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
924 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
925 h->watches,
926 &wc->keyhash,
927 wc,
928 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
929 LOG (GNUNET_ERROR_TYPE_DEBUG,
930 "Sending a watch request for subsystem `%s', peer `%s', key `%s'.\n",
931 sub_system,
932 GNUNET_i2s (peer),
933 key);
934 GNUNET_MQ_send (h->mq, ev);
935 return wc;
936}
937
938
939/* end of peerstore_api.c */
diff --git a/src/peerstore/peerstore_common.c b/src/peerstore/peerstore_common.c
deleted file mode 100644
index 0f6a73fa6..000000000
--- a/src/peerstore/peerstore_common.c
+++ /dev/null
@@ -1,193 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2013 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 peerstore/peerstore_common.c
22 * @brief Helper peerstore functions
23 * @author Omar Tarabai
24 */
25
26#include "peerstore_common.h"
27
28/**
29 * Creates a hash of the given key combination
30 *
31 */
32void
33PEERSTORE_hash_key (const char *sub_system,
34 const struct GNUNET_PeerIdentity *peer,
35 const char *key,
36 struct GNUNET_HashCode *ret)
37{
38 size_t sssize;
39 size_t psize;
40 size_t ksize;
41 size_t totalsize;
42 void *block;
43 void *blockptr;
44
45 sssize = strlen (sub_system) + 1;
46 psize = sizeof(struct GNUNET_PeerIdentity);
47 ksize = strlen (key) + 1;
48 totalsize = sssize + psize + ksize;
49 block = GNUNET_malloc (totalsize);
50 blockptr = block;
51 GNUNET_memcpy (blockptr, sub_system, sssize);
52 blockptr += sssize;
53 GNUNET_memcpy (blockptr, peer, psize);
54 blockptr += psize;
55 GNUNET_memcpy (blockptr, key, ksize);
56 GNUNET_CRYPTO_hash (block, totalsize, ret);
57 GNUNET_free (block);
58}
59
60
61/**
62 * Creates a MQ envelope for a single record
63 *
64 * @param sub_system sub system string
65 * @param peer Peer identity (can be NULL)
66 * @param key record key string (can be NULL)
67 * @param value record value BLOB (can be NULL)
68 * @param value_size record value size in bytes (set to 0 if value is NULL)
69 * @param expiry time after which the record expires
70 * @param options options specific to the storage operation
71 * @param msg_type message type to be set in header
72 * @return pointer to record message struct
73 */
74struct GNUNET_MQ_Envelope *
75PEERSTORE_create_record_mq_envelope (const char *sub_system,
76 const struct GNUNET_PeerIdentity *peer,
77 const char *key,
78 const void *value,
79 size_t value_size,
80 struct GNUNET_TIME_Absolute expiry,
81 enum GNUNET_PEERSTORE_StoreOption options,
82 uint16_t msg_type)
83{
84 struct StoreRecordMessage *srm;
85 struct GNUNET_MQ_Envelope *ev;
86 size_t ss_size;
87 size_t key_size;
88 size_t msg_size;
89 void *dummy;
90
91 GNUNET_assert (NULL != sub_system);
92 ss_size = strlen (sub_system) + 1;
93 if (NULL == key)
94 key_size = 0;
95 else
96 key_size = strlen (key) + 1;
97 msg_size = ss_size + key_size + value_size;
98 ev = GNUNET_MQ_msg_extra (srm, msg_size, msg_type);
99 srm->key_size = htons (key_size);
100 srm->expiry = GNUNET_TIME_absolute_hton (expiry);
101 if (NULL == peer)
102 srm->peer_set = htons (GNUNET_NO);
103 else
104 {
105 srm->peer_set = htons (GNUNET_YES);
106 srm->peer = *peer;
107 }
108 srm->sub_system_size = htons (ss_size);
109 srm->value_size = htons (value_size);
110 srm->options = htonl (options);
111 dummy = &srm[1];
112 GNUNET_memcpy (dummy, sub_system, ss_size);
113 dummy += ss_size;
114 GNUNET_memcpy (dummy, key, key_size);
115 dummy += key_size;
116 GNUNET_memcpy (dummy, value, value_size);
117 return ev;
118}
119
120
121/**
122 * Parses a message carrying a record
123 *
124 * @param srm the actual message
125 * @return Pointer to record or NULL if error
126 */
127struct GNUNET_PEERSTORE_Record *
128PEERSTORE_parse_record_message (const struct StoreRecordMessage *srm)
129{
130 struct GNUNET_PEERSTORE_Record *record;
131 uint16_t req_size;
132 uint16_t ss_size;
133 uint16_t key_size;
134 uint16_t value_size;
135 char *dummy;
136
137 req_size = ntohs (srm->header.size) - sizeof(*srm);
138 ss_size = ntohs (srm->sub_system_size);
139 key_size = ntohs (srm->key_size);
140 value_size = ntohs (srm->value_size);
141 if (ss_size + key_size + value_size != req_size)
142 {
143 GNUNET_break (0);
144 return NULL;
145 }
146 record = GNUNET_new (struct GNUNET_PEERSTORE_Record);
147 if (GNUNET_YES == ntohs (srm->peer_set))
148 {
149 record->peer = srm->peer;
150 }
151 record->expiry = GNUNET_TIME_absolute_ntoh (srm->expiry);
152 dummy = (char *) &srm[1];
153 if (ss_size > 0)
154 {
155 record->sub_system = GNUNET_strdup (dummy);
156 dummy += ss_size;
157 }
158 if (key_size > 0)
159 {
160 record->key = GNUNET_strdup (dummy);
161 dummy += key_size;
162 }
163 if (value_size > 0)
164 {
165 record->value = GNUNET_malloc (value_size);
166 GNUNET_memcpy (record->value,
167 dummy,
168 value_size);
169 }
170 record->value_size = value_size;
171 return record;
172}
173
174
175/**
176 * Free any memory allocated for this record
177 *
178 * @param record
179 */
180void
181PEERSTORE_destroy_record (struct GNUNET_PEERSTORE_Record *record)
182{
183 if (NULL != record->sub_system)
184 GNUNET_free (record->sub_system);
185 if (NULL != record->key)
186 GNUNET_free (record->key);
187 if (NULL != record->value)
188 {
189 GNUNET_free (record->value);
190 record->value = 0;
191 }
192 GNUNET_free (record);
193}
diff --git a/src/peerstore/peerstore_common.h b/src/peerstore/peerstore_common.h
deleted file mode 100644
index f5352f5a5..000000000
--- a/src/peerstore/peerstore_common.h
+++ /dev/null
@@ -1,82 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013-2016 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/peerstore_common.h
23 * @brief Helper peerstore functions
24 * @author Omar Tarabai
25 */
26#include "platform.h"
27#include "peerstore.h"
28
29/**
30 * Creates a hash of the given key combination
31 *
32 */
33void
34PEERSTORE_hash_key (const char *sub_system,
35 const struct GNUNET_PeerIdentity *peer,
36 const char *key,
37 struct GNUNET_HashCode *ret);
38
39
40/**
41 * Creates a MQ envelope for a single record
42 *
43 * @param sub_system sub system string
44 * @param peer Peer identity (can be NULL)
45 * @param key record key string (can be NULL)
46 * @param value record value BLOB (can be NULL)
47 * @param value_size record value size in bytes (set to 0 if value is NULL)
48 * @param expiry time after which the record expires
49 * @param options options specific to the storage operation
50 * @param msg_type message type to be set in header
51 * @return pointer to record message struct
52 */
53struct GNUNET_MQ_Envelope *
54PEERSTORE_create_record_mq_envelope (const char *sub_system,
55 const struct GNUNET_PeerIdentity *peer,
56 const char *key,
57 const void *value,
58 size_t value_size,
59 struct GNUNET_TIME_Absolute expiry,
60 enum GNUNET_PEERSTORE_StoreOption options,
61 uint16_t msg_type);
62
63
64/**
65 * Parses a message carrying a record
66 *
67 * @param srm the actual message
68 * @return Pointer to record or NULL on error
69 */
70struct GNUNET_PEERSTORE_Record *
71PEERSTORE_parse_record_message (const struct StoreRecordMessage *srm);
72
73
74/**
75 * Free any memory allocated for this record
76 *
77 * @param record
78 */
79void
80PEERSTORE_destroy_record (struct GNUNET_PEERSTORE_Record *record);
81
82/* end of peerstore_common.h */
diff --git a/src/peerstore/perf_peerstore_store.c b/src/peerstore/perf_peerstore_store.c
deleted file mode 100644
index 24c7e4f01..000000000
--- a/src/peerstore/perf_peerstore_store.c
+++ /dev/null
@@ -1,109 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
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 peerstore/perf_peerstore_store.c
22 * @brief performance test for peerstore store operation
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_testing_lib.h"
27#include "gnunet_peerstore_service.h"
28
29#define STORES 10000
30
31static int ok = 1;
32
33static struct GNUNET_PEERSTORE_Handle *h;
34
35static char *ss = "test_peerstore_stress";
36static struct GNUNET_PeerIdentity p;
37static char *k = "test_peerstore_stress_key";
38static char *v = "test_peerstore_stress_val";
39
40static int count = 0;
41
42static void
43disconnect ()
44{
45 if (NULL != h)
46 GNUNET_PEERSTORE_disconnect (h, GNUNET_YES);
47 GNUNET_SCHEDULER_shutdown ();
48}
49
50
51static void
52store ()
53{
54 GNUNET_PEERSTORE_store (h, ss, &p, k, v, strlen (v) + 1,
55 GNUNET_TIME_UNIT_FOREVER_ABS,
56 (count ==
57 0) ? GNUNET_PEERSTORE_STOREOPTION_REPLACE :
58 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, NULL, NULL);
59 count++;
60}
61
62
63static void
64watch_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record,
65 const char *emsg)
66{
67 GNUNET_assert (NULL == emsg);
68 if (STORES == count)
69 {
70 ok = 0;
71 disconnect ();
72 }
73 else
74 store ();
75}
76
77
78static void
79run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
80 struct GNUNET_TESTING_Peer *peer)
81{
82 memset (&p, 5, sizeof(p));
83 h = GNUNET_PEERSTORE_connect (cfg);
84 GNUNET_assert (NULL != h);
85 GNUNET_PEERSTORE_watch (h, ss, &p, k, &watch_cb, NULL);
86 store ();
87}
88
89
90int
91main (int argc, char *argv[])
92{
93 struct GNUNET_TIME_Absolute start;
94 struct GNUNET_TIME_Relative diff;
95
96 start = GNUNET_TIME_absolute_get ();
97 if (0 !=
98 GNUNET_TESTING_service_run ("perf-peerstore-store", "peerstore",
99 "test_peerstore_api_data.conf", &run, NULL))
100 return 1;
101 diff = GNUNET_TIME_absolute_get_duration (start);
102 fprintf (stderr, "Stored and retrieved %d records in %s (%s).\n", STORES,
103 GNUNET_STRINGS_relative_time_to_string (diff, GNUNET_YES),
104 GNUNET_STRINGS_relative_time_to_string (diff, GNUNET_NO));
105 return ok;
106}
107
108
109/* end of perf_peerstore_store.c */
diff --git a/src/peerstore/plugin_peerstore_flat.c b/src/peerstore/plugin_peerstore_flat.c
deleted file mode 100644
index cc5b8b76b..000000000
--- a/src/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/peerstore/plugin_peerstore_sqlite.c b/src/peerstore/plugin_peerstore_sqlite.c
deleted file mode 100644
index ad69efdf4..000000000
--- a/src/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/peerstore/test_peerstore_api_data.conf b/src/peerstore/test_peerstore_api_data.conf
deleted file mode 100644
index 614d0cf5b..000000000
--- a/src/peerstore/test_peerstore_api_data.conf
+++ /dev/null
@@ -1,14 +0,0 @@
1[PATHS]
2GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-peerstore
3
4[peerstore]
5START_ON_DEMAND = YES
6BINARY = gnunet-service-peerstore
7UNIXPATH = $GNUNET_TMP/gnunet-service-peerstore.sock
8DATABASE = sqlite
9UNIX_MATCH_UID = NO
10UNIX_MATCH_GID = YES
11#PREFIX = xterm -e gdb --args
12
13[peerstore-sqlite]
14FILENAME = $GNUNET_TEST_HOME/gnunet-peerstore-sqlite.db
diff --git a/src/peerstore/test_peerstore_api_iterate.c b/src/peerstore/test_peerstore_api_iterate.c
deleted file mode 100644
index b6cd51906..000000000
--- a/src/peerstore/test_peerstore_api_iterate.c
+++ /dev/null
@@ -1,176 +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 * @file peerstore/test_peerstore_api_iterate.c
22 * @brief testcase for peerstore iteration operation
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_testing_lib.h"
27#include "gnunet_peerstore_service.h"
28
29static int ok = 1;
30
31static struct GNUNET_PEERSTORE_Handle *h;
32static struct GNUNET_PEERSTORE_IterateContext *ic;
33
34static char *ss = "test_peerstore_api_iterate";
35static struct GNUNET_PeerIdentity p1;
36static struct GNUNET_PeerIdentity p2;
37static char *k1 = "test_peerstore_api_iterate_key1";
38static char *k2 = "test_peerstore_api_iterate_key2";
39static char *k3 = "test_peerstore_api_iterate_key3";
40static char *val = "test_peerstore_api_iterate_val";
41static int count = 0;
42
43
44static void
45iter3_cb (void *cls,
46 const struct GNUNET_PEERSTORE_Record *record,
47 const char *emsg)
48{
49 if (NULL != emsg)
50 {
51 GNUNET_PEERSTORE_iterate_cancel (ic);
52 return;
53 }
54 if (NULL != record)
55 {
56 count++;
57 return;
58 }
59 GNUNET_assert (count == 3);
60 ok = 0;
61 GNUNET_PEERSTORE_disconnect (h, GNUNET_NO);
62 GNUNET_SCHEDULER_shutdown ();
63}
64
65
66static void
67iter2_cb (void *cls,
68 const struct GNUNET_PEERSTORE_Record *record,
69 const char *emsg)
70{
71 if (NULL != emsg)
72 {
73 GNUNET_PEERSTORE_iterate_cancel (ic);
74 return;
75 }
76 if (NULL != record)
77 {
78 count++;
79 return;
80 }
81 GNUNET_assert (count == 2);
82 count = 0;
83 ic = GNUNET_PEERSTORE_iterate (h,
84 ss,
85 NULL,
86 NULL,
87 &iter3_cb,
88 NULL);
89}
90
91
92static void
93iter1_cb (void *cls,
94 const struct GNUNET_PEERSTORE_Record *record,
95 const char *emsg)
96{
97 if (NULL != emsg)
98 {
99 GNUNET_PEERSTORE_iterate_cancel (ic);
100 return;
101 }
102 if (NULL != record)
103 {
104 count++;
105 return;
106 }
107 GNUNET_assert (count == 1);
108 count = 0;
109 ic = GNUNET_PEERSTORE_iterate (h,
110 ss,
111 &p1,
112 NULL,
113 &iter2_cb,
114 NULL);
115}
116
117
118static void
119run (void *cls,
120 const struct GNUNET_CONFIGURATION_Handle *cfg,
121 struct GNUNET_TESTING_Peer *peer)
122{
123 h = GNUNET_PEERSTORE_connect (cfg);
124 GNUNET_assert (NULL != h);
125 memset (&p1, 1, sizeof(p1));
126 memset (&p2, 2, sizeof(p2));
127 GNUNET_PEERSTORE_store (h,
128 ss,
129 &p1,
130 k1,
131 val,
132 strlen (val) + 1,
133 GNUNET_TIME_UNIT_FOREVER_ABS,
134 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
135 NULL,
136 NULL);
137 GNUNET_PEERSTORE_store (h,
138 ss,
139 &p1,
140 k2,
141 val,
142 strlen (val) + 1,
143 GNUNET_TIME_UNIT_FOREVER_ABS,
144 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
145 NULL,
146 NULL);
147 GNUNET_PEERSTORE_store (h,
148 ss,
149 &p2,
150 k3,
151 val,
152 strlen (val) + 1,
153 GNUNET_TIME_UNIT_FOREVER_ABS,
154 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
155 NULL,
156 NULL);
157 ic = GNUNET_PEERSTORE_iterate (h,
158 ss,
159 &p1,
160 k1,
161 &iter1_cb, NULL);
162}
163
164
165int
166main (int argc, char *argv[])
167{
168 if (0 !=
169 GNUNET_TESTING_service_run ("test-gnunet-peerstore", "peerstore",
170 "test_peerstore_api_data.conf", &run, NULL))
171 return 1;
172 return ok;
173}
174
175
176/* end of test_peerstore_api_iterate.c */
diff --git a/src/peerstore/test_peerstore_api_store.c b/src/peerstore/test_peerstore_api_store.c
deleted file mode 100644
index 77e8a17c1..000000000
--- a/src/peerstore/test_peerstore_api_store.c
+++ /dev/null
@@ -1,233 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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 peerstore/test_peerstore_api_store.c
22 * @brief testcase for peerstore store operation
23 */
24#include "platform.h"
25#include "gnunet_peerstore_service.h"
26#include "gnunet_testing_lib.h"
27
28
29static int ok = 1;
30
31static struct GNUNET_PEERSTORE_Handle *h;
32
33static char *subsystem = "test_peerstore_api_store";
34static struct GNUNET_PeerIdentity pid;
35static char *key = "test_peerstore_api_store_key";
36static char *val1 = "test_peerstore_api_store_val1";
37static char *val2 = "test_peerstore_api_store_val2-";
38static char *val3 = "test_peerstore_api_store_val3--";
39
40static int count = 0;
41
42
43static void
44test3_cont2 (void *cls,
45 const struct GNUNET_PEERSTORE_Record *record,
46 const char *emsg)
47{
48 if (NULL != emsg)
49 return;
50 if (NULL != record)
51 {
52 GNUNET_assert ((strlen (val3) + 1) == record->value_size);
53 GNUNET_assert (0 == strcmp ((char *) val3,
54 (char *) record->value));
55 count++;
56 return;
57 }
58 GNUNET_assert (count == 1);
59 ok = 0;
60 GNUNET_PEERSTORE_disconnect (h, GNUNET_YES);
61 GNUNET_SCHEDULER_shutdown ();
62}
63
64
65static void
66test3_cont (void *cls,
67 int success)
68{
69 if (GNUNET_YES != success)
70 return;
71 count = 0;
72 GNUNET_PEERSTORE_iterate (h,
73 subsystem,
74 &pid,
75 key,
76 &test3_cont2,
77 NULL);
78}
79
80
81/**
82 * Replace the previous 2 records
83 */
84static void
85test3 ()
86{
87 GNUNET_PEERSTORE_store (h,
88 subsystem,
89 &pid,
90 key,
91 val3,
92 strlen (val3) + 1,
93 GNUNET_TIME_UNIT_FOREVER_ABS,
94 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
95 &test3_cont,
96 NULL);
97}
98
99
100static void
101test2_cont2 (void *cls,
102 const struct GNUNET_PEERSTORE_Record *record,
103 const char *emsg)
104{
105 if (NULL != emsg)
106 return;
107 if (NULL != record)
108 {
109 GNUNET_assert (((strlen (val1) + 1) == record->value_size) ||
110 ((strlen (val2) + 1) == record->value_size));
111 GNUNET_assert ((0 == strcmp ((char *) val1, (char *) record->value)) ||
112 (0 == strcmp ((char *) val2, (char *) record->value)));
113 count++;
114 return;
115 }
116 GNUNET_assert (count == 2);
117 count = 0;
118 test3 ();
119}
120
121
122static void
123test2_cont (void *cls, int success)
124{
125 if (GNUNET_YES != success)
126 return;
127 count = 0;
128 GNUNET_PEERSTORE_iterate (h,
129 subsystem,
130 &pid, key,
131 &test2_cont2,
132 NULL);
133}
134
135
136/**
137 * Test storing a second value with the same key
138 */
139void
140test2 ()
141{
142 GNUNET_PEERSTORE_store (h,
143 subsystem,
144 &pid,
145 key,
146 val2,
147 strlen (val2) + 1,
148 GNUNET_TIME_UNIT_FOREVER_ABS,
149 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
150 &test2_cont,
151 NULL);
152}
153
154
155static void
156test1_cont2 (void *cls,
157 const struct GNUNET_PEERSTORE_Record *record,
158 const char *emsg)
159{
160 if (NULL != emsg)
161 return;
162 if (NULL != record)
163 {
164 GNUNET_assert ((strlen (val1) + 1) == record->value_size);
165 GNUNET_assert (0 == strcmp ((char *) val1, (char *) record->value));
166 count++;
167 return;
168 }
169 GNUNET_assert (count == 1);
170 count = 0;
171 test2 ();
172}
173
174
175static void
176test1_cont (void *cls, int success)
177{
178 if (GNUNET_YES != success)
179 return;
180 count = 0;
181 GNUNET_PEERSTORE_iterate (h,
182 subsystem,
183 &pid,
184 key,
185 &test1_cont2,
186 NULL);
187}
188
189
190/**
191 * Store a single record
192 */
193static void
194test1 ()
195{
196 GNUNET_PEERSTORE_store (h,
197 subsystem,
198 &pid,
199 key,
200 val1,
201 strlen (val1) + 1,
202 GNUNET_TIME_UNIT_FOREVER_ABS,
203 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
204 &test1_cont,
205 NULL);
206}
207
208
209static void
210run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
211 struct GNUNET_TESTING_Peer *peer)
212{
213 h = GNUNET_PEERSTORE_connect (cfg);
214 GNUNET_assert (NULL != h);
215 memset (&pid, 1, sizeof(pid));
216 test1 ();
217}
218
219
220int
221main (int argc, char *argv[])
222{
223 if (0 !=
224 GNUNET_TESTING_service_run ("test-gnunet-peerstore",
225 "peerstore",
226 "test_peerstore_api_data.conf",
227 &run, NULL))
228 return 1;
229 return ok;
230}
231
232
233/* end of test_peerstore_api_store.c */
diff --git a/src/peerstore/test_peerstore_api_sync.c b/src/peerstore/test_peerstore_api_sync.c
deleted file mode 100644
index 5057c98b5..000000000
--- a/src/peerstore/test_peerstore_api_sync.c
+++ /dev/null
@@ -1,253 +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 peerstore/test_peerstore_api_sync.c
22 * @brief testcase for peerstore sync-on-disconnect feature. Stores
23 * a value just before disconnecting, and then checks that
24 * this value is actually stored.
25 * @author Omar Tarabai
26 * @author Christian Grothoff (minor fix, comments)
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_peerstore_service.h"
32
33/**
34 * Overall result, 0 for success.
35 */
36static int ok = 404;
37
38/**
39 * Configuration we use.
40 */
41static const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43/**
44 * handle to talk to the peerstore.
45 */
46static struct GNUNET_PEERSTORE_Handle *h;
47
48/**
49 * Subsystem we store the value for.
50 */
51static const char *subsystem = "test_peerstore_api_sync";
52
53/**
54 * Fake PID under which we store the value.
55 */
56static struct GNUNET_PeerIdentity pid;
57
58/**
59 * Test key we're storing the test value under.
60 */
61static const char *key = "test_peerstore_api_store_key";
62
63/**
64 * Test value we are storing.
65 */
66static const char *val = "test_peerstore_api_store_val";
67
68
69/**
70 * Timeout
71 */
72#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
73
74/**
75 * Timeout task
76 */
77static struct GNUNET_SCHEDULER_Task *to;
78
79/**
80 * Iterate handle
81 */
82static struct GNUNET_PEERSTORE_IterateContext *it;
83
84static void
85test_cont (void *cls);
86
87/**
88 * Function that should be called with the result of the
89 * lookup, and finally once with NULL to signal the end
90 * of the iteration.
91 *
92 * Upon the first call, we set "ok" to success. On the
93 * second call (end of iteration) we terminate the test.
94 *
95 * @param cls NULL
96 * @param record the information stored in the peerstore
97 * @param emsg any error message
98 * @return #GNUNET_YES (all good, continue)
99 */
100static void
101iterate_cb (void *cls,
102 const struct GNUNET_PEERSTORE_Record *record,
103 const char *emsg)
104{
105 const char *rec_val;
106
107 GNUNET_break (NULL == emsg);
108 if (NULL == record)
109 {
110 it = NULL;
111 if (0 == ok)
112 {
113 GNUNET_PEERSTORE_disconnect (h,
114 GNUNET_NO);
115 if (NULL != to)
116 {
117 GNUNET_SCHEDULER_cancel (to);
118 to = NULL;
119 }
120 GNUNET_SCHEDULER_shutdown ();
121 return;
122 }
123 /**
124 * Try again
125 */
126 GNUNET_SCHEDULER_add_now (&test_cont,
127 NULL);
128 return;
129 }
130 rec_val = record->value;
131 GNUNET_break (0 == strcmp (rec_val, val));
132 ok = 0;
133}
134
135
136static void
137timeout_task (void *cls)
138{
139 to = NULL;
140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
141 "Timeout reached\n");
142 if (NULL != it)
143 GNUNET_PEERSTORE_iterate_cancel (it);
144 it = NULL;
145 GNUNET_PEERSTORE_disconnect (h,
146 GNUNET_NO);
147 GNUNET_SCHEDULER_shutdown ();
148 return;
149}
150
151
152/**
153 * Run the 2nd stage of the test where we fetch the
154 * data that should have been stored.
155 *
156 * @param cls NULL
157 */
158static void
159test_cont (void *cls)
160{
161 it = GNUNET_PEERSTORE_iterate (h,
162 subsystem,
163 &pid, key,
164 &iterate_cb,
165 NULL);
166}
167
168
169static void
170disc_cont (void *cls)
171{
172 GNUNET_PEERSTORE_disconnect (h, GNUNET_YES);
173 h = GNUNET_PEERSTORE_connect (cfg);
174 GNUNET_SCHEDULER_add_now (&test_cont,
175 NULL);
176}
177
178
179static void
180store_cont (void *cls, int success)
181{
182 ok = success;
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184 "Success: %s\n",
185 (GNUNET_SYSERR == ok) ? "no" : "yes");
186 /* We need to wait a little bit to give the disconnect
187 a chance to actually finish the operation; otherwise,
188 the test may fail non-deterministically if the new
189 connection is faster than the cleanup routine of the
190 old one. */
191 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
192 &disc_cont,
193 NULL);
194}
195
196
197/**
198 * Actually run the test.
199 */
200static void
201test1 ()
202{
203 h = GNUNET_PEERSTORE_connect (cfg);
204 GNUNET_PEERSTORE_store (h,
205 subsystem,
206 &pid,
207 key,
208 val, strlen (val) + 1,
209 GNUNET_TIME_UNIT_FOREVER_ABS,
210 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
211 &store_cont, NULL);
212}
213
214
215/**
216 * Initialize globals and launch the test.
217 *
218 * @param cls NULL
219 * @param c configuration to use
220 * @param peer handle to our peer (unused)
221 */
222static void
223run (void *cls,
224 const struct GNUNET_CONFIGURATION_Handle *c,
225 struct GNUNET_TESTING_Peer *peer)
226{
227 cfg = c;
228 memset (&pid, 1, sizeof(pid));
229 to = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
230 &timeout_task,
231 NULL);
232 GNUNET_SCHEDULER_add_now (&test1, NULL);
233}
234
235
236int
237main (int argc, char *argv[])
238{
239 if (0 !=
240 GNUNET_TESTING_service_run ("test-gnunet-peerstore-sync",
241 "peerstore",
242 "peerstore.conf",
243 &run, NULL))
244 return 1;
245 if (0 != ok)
246 fprintf (stderr,
247 "Test failed: %d\n",
248 ok);
249 return ok;
250}
251
252
253/* end of test_peerstore_api_sync.c */
diff --git a/src/peerstore/test_peerstore_api_watch.c b/src/peerstore/test_peerstore_api_watch.c
deleted file mode 100644
index 126b321df..000000000
--- a/src/peerstore/test_peerstore_api_watch.c
+++ /dev/null
@@ -1,102 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013-2016 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 peerstore/test_peerstore_api_watch.c
22 * @brief testcase for peerstore watch functionality
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_testing_lib.h"
27#include "gnunet_peerstore_service.h"
28
29
30static int ok = 1;
31
32static struct GNUNET_PEERSTORE_Handle *h;
33
34static char *ss = "test_peerstore_api_watch";
35
36static char *k = "test_peerstore_api_watch_key";
37
38static char *val = "test_peerstore_api_watch_val";
39
40
41static void
42watch_cb (void *cls,
43 const struct GNUNET_PEERSTORE_Record *record,
44 const char *emsg)
45{
46 GNUNET_assert (NULL == emsg);
47 GNUNET_assert (0 == strcmp (val,
48 (char *) record->value));
49 ok = 0;
50 GNUNET_PEERSTORE_disconnect (h,
51 GNUNET_NO);
52 GNUNET_SCHEDULER_shutdown ();
53}
54
55
56static void
57run (void *cls,
58 const struct GNUNET_CONFIGURATION_Handle *cfg,
59 struct GNUNET_TESTING_Peer *peer)
60{
61 struct GNUNET_PeerIdentity p;
62
63 h = GNUNET_PEERSTORE_connect (cfg);
64 GNUNET_assert (NULL != h);
65 memset (&p,
66 4,
67 sizeof(p));
68 GNUNET_PEERSTORE_watch (h,
69 ss,
70 &p,
71 k,
72 &watch_cb,
73 NULL);
74 GNUNET_PEERSTORE_store (h,
75 ss,
76 &p,
77 k,
78 val,
79 strlen (val) + 1,
80 GNUNET_TIME_UNIT_FOREVER_ABS,
81 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
82 NULL,
83 NULL);
84}
85
86
87int
88main (int argc,
89 char *argv[])
90{
91 if (0 !=
92 GNUNET_TESTING_service_run ("test-gnunet-peerstore",
93 "peerstore",
94 "test_peerstore_api_data.conf",
95 &run,
96 NULL))
97 return 1;
98 return ok;
99}
100
101
102/* end of test_peerstore_api_watch.c */
diff --git a/src/peerstore/test_plugin_peerstore.c b/src/peerstore/test_plugin_peerstore.c
deleted file mode 100644
index a4221ea63..000000000
--- a/src/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_TESTING_get_testname_from_underscore (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/peerstore/test_plugin_peerstore_flat.conf b/src/peerstore/test_plugin_peerstore_flat.conf
deleted file mode 100644
index c55b1e9d6..000000000
--- a/src/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/peerstore/test_plugin_peerstore_sqlite.conf b/src/peerstore/test_plugin_peerstore_sqlite.conf
deleted file mode 100644
index dcf1fc1a4..000000000
--- a/src/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