aboutsummaryrefslogtreecommitdiff
path: root/src/service/datacache
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/datacache')
-rw-r--r--src/service/datacache/.gitignore6
-rw-r--r--src/service/datacache/Makefile.am104
-rw-r--r--src/service/datacache/datacache.c361
-rw-r--r--src/service/datacache/datacache.conf6
-rw-r--r--src/service/datacache/meson.build109
-rw-r--r--src/service/datacache/test_datacache.c210
-rw-r--r--src/service/datacache/test_datacache_data_heap.conf4
-rw-r--r--src/service/datacache/test_datacache_data_postgres.conf7
-rw-r--r--src/service/datacache/test_datacache_data_sqlite.conf5
-rw-r--r--src/service/datacache/test_datacache_quota.c199
10 files changed, 1011 insertions, 0 deletions
diff --git a/src/service/datacache/.gitignore b/src/service/datacache/.gitignore
new file mode 100644
index 000000000..8e42aa103
--- /dev/null
+++ b/src/service/datacache/.gitignore
@@ -0,0 +1,6 @@
1test_datacache_heap
2test_datacache_postgres
3test_datacache_quota_heap
4test_datacache_quota_postgres
5test_datacache_quota_sqlite
6test_datacache_sqlite
diff --git a/src/service/datacache/Makefile.am b/src/service/datacache/Makefile.am
new file mode 100644
index 000000000..022b45253
--- /dev/null
+++ b/src/service/datacache/Makefile.am
@@ -0,0 +1,104 @@
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
8dist_pkgcfg_DATA = \
9 datacache.conf
10
11if USE_COVERAGE
12 AM_CFLAGS = --coverage -O0
13 XLIBS = -lgcov
14endif
15
16lib_LTLIBRARIES = \
17 libgnunetdatacache.la
18
19libgnunetdatacache_la_SOURCES = \
20 datacache.c
21libgnunetdatacache_la_LIBADD = \
22 $(top_builddir)/src/service/statistics/libgnunetstatistics.la \
23 $(top_builddir)/src/lib/util/libgnunetutil.la \
24 $(GN_LIBINTL)
25libgnunetdatacache_la_LDFLAGS = \
26 $(GN_LIB_LDFLAGS) \
27 -version-info 0:1:0
28
29
30if HAVE_SQLITE
31SQLITE_TESTS = \
32 test_datacache_sqlite \
33 test_datacache_quota_sqlite \
34 $(SQLITE_BENCHMARKS)
35endif
36
37HEAP_TESTS = \
38 test_datacache_heap \
39 test_datacache_quota_heap \
40 $(HEAP_BENCHMARKS)
41
42if HAVE_POSTGRESQL
43POSTGRES_TESTS = \
44 test_datacache_postgres \
45 test_datacache_quota_postgres \
46 $(POSTGRES_BENCHMARKS)
47endif
48
49check_PROGRAMS = \
50 $(SQLITE_TESTS) \
51 $(HEAP_TESTS) \
52 $(POSTGRES_TESTS)
53
54if ENABLE_TEST_RUN
55AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
56TESTS = $(check_PROGRAMS)
57endif
58
59test_datacache_sqlite_SOURCES = \
60 test_datacache.c
61test_datacache_sqlite_LDADD = \
62 $(top_builddir)/src/service/testing/libgnunettesting.la \
63 libgnunetdatacache.la \
64 $(top_builddir)/src/lib/util/libgnunetutil.la
65
66test_datacache_quota_sqlite_SOURCES = \
67 test_datacache_quota.c
68test_datacache_quota_sqlite_LDADD = \
69 $(top_builddir)/src/service/testing/libgnunettesting.la \
70 libgnunetdatacache.la \
71 $(top_builddir)/src/lib/util/libgnunetutil.la
72
73test_datacache_heap_SOURCES = \
74 test_datacache.c
75test_datacache_heap_LDADD = \
76 $(top_builddir)/src/service/testing/libgnunettesting.la \
77 libgnunetdatacache.la \
78 $(top_builddir)/src/lib/util/libgnunetutil.la
79
80test_datacache_quota_heap_SOURCES = \
81 test_datacache_quota.c
82test_datacache_quota_heap_LDADD = \
83 $(top_builddir)/src/service/testing/libgnunettesting.la \
84 libgnunetdatacache.la \
85 $(top_builddir)/src/lib/util/libgnunetutil.la
86
87test_datacache_postgres_SOURCES = \
88 test_datacache.c
89test_datacache_postgres_LDADD = \
90 $(top_builddir)/src/service/testing/libgnunettesting.la \
91 libgnunetdatacache.la \
92 $(top_builddir)/src/lib/util/libgnunetutil.la
93
94test_datacache_quota_postgres_SOURCES = \
95 test_datacache_quota.c
96test_datacache_quota_postgres_LDADD = \
97 $(top_builddir)/src/service/testing/libgnunettesting.la \
98 libgnunetdatacache.la \
99 $(top_builddir)/src/lib/util/libgnunetutil.la
100
101EXTRA_DIST = \
102 test_datacache_data_sqlite.conf \
103 test_datacache_data_heap.conf \
104 test_datacache_data_postgres.conf
diff --git a/src/service/datacache/datacache.c b/src/service/datacache/datacache.c
new file mode 100644
index 000000000..c93ed58d6
--- /dev/null
+++ b/src/service/datacache/datacache.c
@@ -0,0 +1,361 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2004-2010, 2015, 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file datacache/datacache.c
22 * @brief datacache API implementation
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_datacache_lib.h"
28#include "gnunet_statistics_service.h"
29#include "gnunet_datacache_plugin.h"
30
31
32#define LOG(kind, ...) GNUNET_log_from (kind, "datacache", __VA_ARGS__)
33
34#define LOG_STRERROR_FILE(kind, op, fn) \
35 GNUNET_log_from_strerror_file (kind, "datacache", op, fn)
36
37/**
38 * Internal state of the datacache library.
39 */
40struct GNUNET_DATACACHE_Handle
41{
42 /**
43 * Bloomfilter to quickly tell if we don't have the content.
44 */
45 struct GNUNET_CONTAINER_BloomFilter *filter;
46
47 /**
48 * Our configuration.
49 */
50 const struct GNUNET_CONFIGURATION_Handle *cfg;
51
52 /**
53 * Opaque handle for the statistics service.
54 */
55 struct GNUNET_STATISTICS_Handle *stats;
56
57 /**
58 * Configuration section to use.
59 */
60 char *section;
61
62 /**
63 * API of the transport as returned by the plugin's
64 * initialization function.
65 */
66 struct GNUNET_DATACACHE_PluginFunctions *api;
67
68 /**
69 * Short name for the plugin (e.g. "sqlite").
70 */
71 char *short_name;
72
73 /**
74 * Name of the library (e.g. "gnunet_plugin_datacache_sqlite").
75 */
76 char *lib_name;
77
78 /**
79 * Name for the bloom filter file.
80 */
81 char *bloom_name;
82
83 /**
84 * Environment provided to our plugin.
85 */
86 struct GNUNET_DATACACHE_PluginEnvironment env;
87
88 /**
89 * How much space is in use right now?
90 */
91 unsigned long long utilization;
92};
93
94
95/**
96 * Function called by plugins to notify the datacache
97 * about content deletions.
98 *
99 * @param cls closure
100 * @param key key of the content that was deleted
101 * @param size number of bytes that were made available
102 */
103static void
104env_delete_notify (void *cls,
105 const struct GNUNET_HashCode *key,
106 size_t size)
107{
108 struct GNUNET_DATACACHE_Handle *h = cls;
109
110 LOG (GNUNET_ERROR_TYPE_DEBUG,
111 "Content under key `%s' discarded\n",
112 GNUNET_h2s (key));
113 GNUNET_assert (h->utilization >= size);
114 h->utilization -= size;
115 GNUNET_CONTAINER_bloomfilter_remove (h->filter, key);
116 GNUNET_STATISTICS_update (h->stats,
117 "# bytes stored",
118 -(long long) size,
119 GNUNET_NO);
120 GNUNET_STATISTICS_update (h->stats,
121 "# items stored",
122 -1,
123 GNUNET_NO);
124}
125
126
127struct GNUNET_DATACACHE_Handle *
128GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
129 const char *section)
130{
131 unsigned int bf_size;
132 unsigned long long quota;
133 struct GNUNET_DATACACHE_Handle *ret;
134 char *libname;
135 char *name;
136 const struct GNUNET_OS_ProjectData *pd;
137
138 if (GNUNET_OK !=
139 GNUNET_CONFIGURATION_get_value_size (cfg,
140 section,
141 "QUOTA",
142 &quota))
143 {
144 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
145 section,
146 "QUOTA");
147 return NULL;
148 }
149 if (GNUNET_OK !=
150 GNUNET_CONFIGURATION_get_value_string (cfg,
151 section,
152 "DATABASE",
153 &name))
154 {
155 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
156 section,
157 "DATABASE");
158 return NULL;
159 }
160 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */
161
162 ret = GNUNET_new (struct GNUNET_DATACACHE_Handle);
163
164 if (GNUNET_YES !=
165 GNUNET_CONFIGURATION_get_value_yesno (cfg,
166 section,
167 "DISABLE_BF"))
168 {
169 if (GNUNET_YES !=
170 GNUNET_CONFIGURATION_get_value_yesno (cfg,
171 section,
172 "DISABLE_BF_RC"))
173 {
174 ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom");
175 }
176 if (NULL != ret->bloom_name)
177 {
178 ret->filter = GNUNET_CONTAINER_bloomfilter_load (
179 ret->bloom_name,
180 quota / 1024, /* 8 bit per entry in DB, expect 1k entries */
181 5);
182 }
183 if (NULL == ret->filter)
184 {
185 ret->filter =
186 GNUNET_CONTAINER_bloomfilter_init (NULL,
187 bf_size,
188 5); /* approx. 3% false positives at max use */
189 }
190 }
191 ret->stats = GNUNET_STATISTICS_create ("datacache",
192 cfg);
193 ret->section = GNUNET_strdup (section);
194 ret->env.cfg = cfg;
195 ret->env.delete_notify = &env_delete_notify;
196 ret->env.section = ret->section;
197 ret->env.cls = ret;
198 ret->env.delete_notify = &env_delete_notify;
199 ret->env.quota = quota;
200 LOG (GNUNET_ERROR_TYPE_INFO,
201 "Loading `%s' datacache plugin\n",
202 name);
203 GNUNET_asprintf (&libname,
204 "libgnunet_plugin_datacache_%s",
205 name);
206 ret->short_name = name;
207 ret->lib_name = libname;
208 /* Load the plugin within GNUnet's default context */
209 pd = GNUNET_OS_project_data_get ();
210 GNUNET_OS_init (GNUNET_OS_project_data_default ());
211 ret->api = GNUNET_PLUGIN_load (libname,
212 &ret->env);
213 GNUNET_OS_init (pd);
214 if (NULL == ret->api)
215 {
216 /* Try to load the plugin within the application's context
217 This normally happens when the application is not GNUnet itself but a
218 third party; inside GNUnet this is effectively a double failure. */
219 ret->api = GNUNET_PLUGIN_load (libname,
220 &ret->env);
221 if (NULL == ret->api)
222 {
223 LOG (GNUNET_ERROR_TYPE_ERROR,
224 "Failed to load datacache plugin for `%s'\n",
225 name);
226 GNUNET_DATACACHE_destroy (ret);
227 return NULL;
228 }
229 }
230 return ret;
231}
232
233
234void
235GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
236{
237 if (NULL != h->filter)
238 GNUNET_CONTAINER_bloomfilter_free (h->filter);
239 if (NULL != h->api)
240 GNUNET_break (NULL ==
241 GNUNET_PLUGIN_unload (h->lib_name,
242 h->api));
243 GNUNET_free (h->lib_name);
244 GNUNET_free (h->short_name);
245 GNUNET_free (h->section);
246 if (NULL != h->bloom_name)
247 {
248 if (0 != unlink (h->bloom_name))
249 GNUNET_log_from_strerror_file (GNUNET_ERROR_TYPE_WARNING,
250 "datacache",
251 "unlink",
252 h->bloom_name);
253 GNUNET_free (h->bloom_name);
254 }
255 GNUNET_STATISTICS_destroy (h->stats, GNUNET_NO);
256 GNUNET_free (h);
257}
258
259
260enum GNUNET_GenericReturnValue
261GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
262 uint32_t xor_distance,
263 const struct GNUNET_DATACACHE_Block *block)
264{
265 ssize_t used;
266
267 used = h->api->put (h->api->cls,
268 xor_distance,
269 block);
270 if (-1 == used)
271 {
272 GNUNET_break (0);
273 return GNUNET_SYSERR;
274 }
275 if (0 == used)
276 {
277 /* duplicate */
278 return GNUNET_NO;
279 }
280 LOG (GNUNET_ERROR_TYPE_DEBUG,
281 "Stored data under key `%s' in cache\n",
282 GNUNET_h2s (&block->key));
283 if (NULL != h->filter)
284 GNUNET_CONTAINER_bloomfilter_add (h->filter,
285 &block->key);
286 GNUNET_STATISTICS_update (h->stats,
287 "# bytes stored",
288 used,
289 GNUNET_NO);
290 GNUNET_STATISTICS_update (h->stats,
291 "# items stored",
292 1,
293 GNUNET_NO);
294 while (h->utilization + used > h->env.quota)
295 GNUNET_assert (GNUNET_OK ==
296 h->api->del (h->api->cls));
297 h->utilization += used;
298 return GNUNET_OK;
299}
300
301
302unsigned int
303GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
304 const struct GNUNET_HashCode *key,
305 enum GNUNET_BLOCK_Type type,
306 GNUNET_DATACACHE_Iterator iter,
307 void *iter_cls)
308{
309 GNUNET_STATISTICS_update (h->stats,
310 "# requests received",
311 1,
312 GNUNET_NO);
313 LOG (GNUNET_ERROR_TYPE_DEBUG,
314 "Processing request for key `%s'\n",
315 GNUNET_h2s (key));
316 if ( (NULL != h->filter) &&
317 (GNUNET_OK !=
318 GNUNET_CONTAINER_bloomfilter_test (h->filter,
319 key)) )
320 {
321 GNUNET_STATISTICS_update (h->stats,
322 "# requests filtered by bloom filter",
323 1,
324 GNUNET_NO);
325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Bloomfilter filters request for key `%s'\n",
327 GNUNET_h2s (key));
328 return 0; /* can not be present */
329 }
330 return h->api->get (h->api->cls,
331 key,
332 type,
333 iter, iter_cls);
334}
335
336
337unsigned int
338GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
339 const struct GNUNET_HashCode *key,
340 enum GNUNET_BLOCK_Type type,
341 unsigned int num_results,
342 GNUNET_DATACACHE_Iterator iter,
343 void *iter_cls)
344{
345 GNUNET_STATISTICS_update (h->stats,
346 "# proximity search requests received",
347 1,
348 GNUNET_NO);
349 LOG (GNUNET_ERROR_TYPE_DEBUG,
350 "Processing proximity search at `%s'\n",
351 GNUNET_h2s (key));
352 return h->api->get_closest (h->api->cls,
353 key,
354 type,
355 num_results,
356 iter,
357 iter_cls);
358}
359
360
361/* end of datacache.c */
diff --git a/src/service/datacache/datacache.conf b/src/service/datacache/datacache.conf
new file mode 100644
index 000000000..ed5c3da06
--- /dev/null
+++ b/src/service/datacache/datacache.conf
@@ -0,0 +1,6 @@
1[datacache-postgres]
2CONFIG = postgres:///gnunet
3
4# Where are the SQL files to setup our tables?
5# Important: this MUST end with a "/"!
6SQL_DIR = $DATADIR/sql/ \ No newline at end of file
diff --git a/src/service/datacache/meson.build b/src/service/datacache/meson.build
new file mode 100644
index 000000000..f50036c03
--- /dev/null
+++ b/src/service/datacache/meson.build
@@ -0,0 +1,109 @@
1libgnunetdatacache_src = ['datacache.c']
2
3configure_file(input : 'datacache.conf',
4 output : 'datacache.conf',
5 configuration : cdata,
6 install: true,
7 install_dir: pkgcfgdir)
8
9if get_option('monolith')
10 foreach p : libgnunetdatacache_src
11 gnunet_src += 'datacache/' + p
12 endforeach
13endif
14
15libgnunetdatacache = library('gnunetdatacache',
16 libgnunetdatacache_src,
17 soversion: '0',
18 version: '0.0.1',
19 dependencies: [libgnunetutil_dep, libgnunetstatistics_dep],
20 include_directories: [incdir, configuration_inc],
21 install: true,
22 install_dir: get_option('libdir'))
23libgnunetdatacache_dep = declare_dependency(link_with : libgnunetdatacache)
24pkg.generate(libgnunetdatacache, url: 'https://www.gnunet.org',
25 description : 'Provides datacache API for temporary storage to disk')
26
27testdc_sqlite = executable ('test_datacache_sqlite',
28 ['test_datacache.c'],
29 dependencies: [
30 libgnunetdatacache_dep,
31 libgnunetutil_dep,
32 libgnunettesting_dep
33 ],
34 include_directories: [incdir, configuration_inc],
35 install: false)
36
37testdc_quota_sqlite = executable ('test_datacache_quota_sqlite',
38 ['test_datacache_quota.c'],
39 dependencies: [
40 libgnunetdatacache_dep,
41 libgnunetutil_dep,
42 libgnunettesting_dep
43 ],
44 include_directories: [incdir, configuration_inc],
45 install: false)
46
47testdc_heap = executable ('test_datacache_heap',
48 ['test_datacache.c'],
49 dependencies: [
50 libgnunetdatacache_dep,
51 libgnunetutil_dep,
52 libgnunettesting_dep
53 ],
54 include_directories: [incdir, configuration_inc],
55 install: false)
56
57testdc_quota_heap = executable ('test_datacache_quota_heap',
58 ['test_datacache_quota.c'],
59 dependencies: [
60 libgnunetdatacache_dep,
61 libgnunetutil_dep,
62 libgnunettesting_dep
63 ],
64 include_directories: [incdir, configuration_inc],
65 install: false)
66
67
68testdc_pq = executable ('test_datacache_postgres',
69 ['test_datacache.c'],
70 dependencies: [
71 libgnunetdatacache_dep,
72 libgnunetutil_dep,
73 libgnunettesting_dep
74 ],
75 include_directories: [incdir, configuration_inc],
76 install: false)
77
78testdc_quota_pq = executable ('test_datacache_quota_postgres',
79 ['test_datacache_quota.c'],
80 dependencies: [
81 libgnunetdatacache_dep,
82 libgnunetutil_dep,
83 libgnunettesting_dep
84 ],
85 include_directories: [incdir, configuration_inc],
86 install: false)
87
88configure_file(input : 'test_datacache_data_sqlite.conf',
89 output : 'test_datacache_data_sqlite.conf',
90 copy: true)
91configure_file(input : 'test_datacache_data_heap.conf',
92 output : 'test_datacache_data_heap.conf',
93 copy: true)
94configure_file(input : 'test_datacache_data_postgres.conf',
95 output : 'test_datacache_data_postgres.conf',
96 copy: true)
97
98test('test_datacache_sqlite', testdc_sqlite,
99 suite: 'datacache', workdir: meson.current_build_dir())
100test('test_datacache_quota_sqlite', testdc_quota_sqlite,
101 suite: 'datacache', workdir: meson.current_build_dir())
102test('test_datacache_heap', testdc_heap,
103 suite: 'datacache', workdir: meson.current_build_dir())
104test('test_datacache_quota_heap', testdc_quota_heap,
105 suite: 'datacache', workdir: meson.current_build_dir())
106test('test_datacache_postgres', testdc_pq,
107 suite: 'datacache', workdir: meson.current_build_dir())
108test('test_datacache_quota_postgres', testdc_quota_pq,
109 suite: 'datacache', workdir: meson.current_build_dir())
diff --git a/src/service/datacache/test_datacache.c b/src/service/datacache/test_datacache.c
new file mode 100644
index 000000000..f06d4ceab
--- /dev/null
+++ b/src/service/datacache/test_datacache.c
@@ -0,0 +1,210 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2010, 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @file datacache/test_datacache.c
22 * @brief Test for the datacache implementations.
23 * @author Nils Durner
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_datacache_lib.h"
28#include "gnunet_testing_lib.h"
29
30#define ASSERT(x) do { if (! (x)) { printf ("Error at %s:%d\n", __FILE__, \
31 __LINE__); goto FAILURE; \
32 } } while (0)
33
34static int ok;
35
36/**
37 * Name of plugin under test.
38 */
39static char *plugin_name;
40
41
42static enum GNUNET_GenericReturnValue
43checkIt (void *cls,
44 const struct GNUNET_DATACACHE_Block *block)
45{
46 if (block->data_size != sizeof(struct GNUNET_HashCode))
47 {
48 GNUNET_break (0);
49 ok = 2;
50 }
51 if (0 != memcmp (block->data,
52 cls,
53 block->data_size))
54 {
55 GNUNET_break (0);
56 ok = 3;
57 }
58 return GNUNET_OK;
59}
60
61
62static void
63run (void *cls,
64 char *const *args,
65 const char *cfgfile,
66 const struct GNUNET_CONFIGURATION_Handle *cfg)
67{
68 struct GNUNET_DATACACHE_Handle *h;
69 struct GNUNET_DATACACHE_Block block;
70 struct GNUNET_HashCode k;
71 struct GNUNET_HashCode n;
72
73 (void) cls;
74 (void) args;
75 (void) cfgfile;
76 ok = 0;
77 h = GNUNET_DATACACHE_create (cfg,
78 "testcache");
79 if (NULL == h)
80 {
81 fprintf (stderr,
82 "%s",
83 "Failed to initialize datacache. Database likely not setup, skipping test.\n");
84 ok = 77; /* mark test as skipped */
85 return;
86 }
87 block.expiration_time = GNUNET_TIME_absolute_get ();
88 block.expiration_time.abs_value_us += 5 * 60 * 1000 * 1000LL;
89 memset (&k,
90 0,
91 sizeof(struct GNUNET_HashCode));
92 for (unsigned int i = 0; i < 100; i++)
93 {
94 GNUNET_CRYPTO_hash (&k,
95 sizeof(struct GNUNET_HashCode),
96 &n);
97 block.key = k;
98 block.data = &n;
99 block.data_size = sizeof (n);
100 memset (&block.trunc_peer,
101 43,
102 sizeof (block.trunc_peer));
103 block.ro = 42;
104 block.type = (enum GNUNET_BLOCK_Type) (1 + i % 16);
105 block.put_path = NULL;
106 block.put_path_length = 0;
107 block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
108 ASSERT (GNUNET_OK ==
109 GNUNET_DATACACHE_put (h,
110 42,
111 &block));
112 k = n;
113 }
114 memset (&k,
115 0,
116 sizeof(struct GNUNET_HashCode));
117 for (unsigned int i = 0; i < 100; i++)
118 {
119 GNUNET_CRYPTO_hash (&k,
120 sizeof(struct GNUNET_HashCode),
121 &n);
122 ASSERT (1 == GNUNET_DATACACHE_get (h,
123 &k,
124 (enum GNUNET_BLOCK_Type) (1 + i % 16),
125 &checkIt,
126 &n));
127 k = n;
128 }
129
130 memset (&k,
131 42,
132 sizeof(struct GNUNET_HashCode));
133 GNUNET_CRYPTO_hash (&k,
134 sizeof(struct GNUNET_HashCode),
135 &n);
136 block.key = k;
137 block.data = &n;
138 block.data_size = sizeof (n);
139 block.ro = 42;
140 memset (&block.trunc_peer,
141 44,
142 sizeof (block.trunc_peer));
143 block.type = (enum GNUNET_BLOCK_Type) 792;
144 block.put_path = NULL;
145 block.put_path_length = 0;
146 block.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS;
147 block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
148 ASSERT (GNUNET_OK ==
149 GNUNET_DATACACHE_put (h,
150 42,
151 &block));
152 ASSERT (0 != GNUNET_DATACACHE_get (h,
153 &k,
154 792,
155 &checkIt,
156 &n));
157 GNUNET_DATACACHE_destroy (h);
158 ASSERT (ok == 0);
159 return;
160FAILURE:
161 if (h != NULL)
162 GNUNET_DATACACHE_destroy (h);
163 ok = GNUNET_SYSERR;
164}
165
166
167int
168main (int argc, char *argv[])
169{
170 char cfg_name[PATH_MAX];
171 char *const xargv[] = {
172 "test-datacache",
173 "-c",
174 cfg_name,
175 NULL
176 };
177 struct GNUNET_GETOPT_CommandLineOption options[] = {
178 GNUNET_GETOPT_OPTION_END
179 };
180
181 (void) argc;
182 GNUNET_log_setup ("test-datacache",
183 "WARNING",
184 NULL);
185 plugin_name = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]);
186 GNUNET_snprintf (cfg_name,
187 sizeof(cfg_name),
188 "test_datacache_data_%s.conf",
189 plugin_name);
190 if (GNUNET_OK != GNUNET_PROGRAM_run ((sizeof(xargv) / sizeof(char *)) - 1,
191 xargv,
192 "test-datacache",
193 "nohelp",
194 options,
195 &run,
196 NULL))
197 {
198 GNUNET_free (plugin_name);
199 return 1;
200 }
201 if ((0 != ok) && (77 != ok))
202 fprintf (stderr,
203 "Missed some testcases: %d\n",
204 ok);
205 GNUNET_free (plugin_name);
206 return ok;
207}
208
209
210/* end of test_datacache.c */
diff --git a/src/service/datacache/test_datacache_data_heap.conf b/src/service/datacache/test_datacache_data_heap.conf
new file mode 100644
index 000000000..082cf48f4
--- /dev/null
+++ b/src/service/datacache/test_datacache_data_heap.conf
@@ -0,0 +1,4 @@
1[testcache]
2QUOTA = 1 MB
3DATABASE = heap
4
diff --git a/src/service/datacache/test_datacache_data_postgres.conf b/src/service/datacache/test_datacache_data_postgres.conf
new file mode 100644
index 000000000..92313157c
--- /dev/null
+++ b/src/service/datacache/test_datacache_data_postgres.conf
@@ -0,0 +1,7 @@
1
2[testcache]
3QUOTA = 1 MB
4DATABASE = postgres
5
6[datacache-postgres]
7CONFIG = postgres:///gnunetcheck
diff --git a/src/service/datacache/test_datacache_data_sqlite.conf b/src/service/datacache/test_datacache_data_sqlite.conf
new file mode 100644
index 000000000..bf6ce1b2b
--- /dev/null
+++ b/src/service/datacache/test_datacache_data_sqlite.conf
@@ -0,0 +1,5 @@
1[testcache]
2QUOTA = 1 MB
3DATABASE = sqlite
4
5
diff --git a/src/service/datacache/test_datacache_quota.c b/src/service/datacache/test_datacache_quota.c
new file mode 100644
index 000000000..6067b79fa
--- /dev/null
+++ b/src/service/datacache/test_datacache_quota.c
@@ -0,0 +1,199 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2010, 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @file datacache/test_datacache_quota.c
22 * @brief Test for the quota code of the datacache implementations.
23 * @author Nils Durner
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_datacache_lib.h"
28#include "gnunet_testing_lib.h"
29
30#define ASSERT(x) do { if (! (x)) { printf ("Error at %s:%d\n", __FILE__, \
31 __LINE__); goto FAILURE; \
32 } } while (0)
33
34static int ok;
35
36/**
37 * Name of plugin under test.
38 */
39static char *plugin_name;
40
41/**
42 * Quota is 1 MB. Each iteration of the test puts in about 1 MB of
43 * data. We do 10 iterations. Afterwards we check that the data from
44 * the first 5 iterations has all been discarded and that at least
45 * some of the data from the last iteration is still there.
46 */
47static void
48run (void *cls,
49 char *const *args,
50 const char *cfgfile,
51 const struct GNUNET_CONFIGURATION_Handle *cfg)
52{
53 struct GNUNET_DATACACHE_Handle *h;
54 struct GNUNET_HashCode k;
55 struct GNUNET_HashCode n;
56 struct GNUNET_DATACACHE_Block block;
57 char buf[3200];
58
59 (void) cls;
60 (void) args;
61 (void) cfgfile;
62 ok = 0;
63 h = GNUNET_DATACACHE_create (cfg,
64 "testcache");
65
66 if (h == NULL)
67 {
68 fprintf (stderr,
69 "%s",
70 "Failed to initialize datacache. Database likely not setup, skipping test.\n");
71 ok = 77;
72 return;
73 }
74 block.expiration_time = GNUNET_TIME_relative_to_absolute (
75 GNUNET_TIME_UNIT_HOURS);
76 memset (buf,
77 1,
78 sizeof(buf));
79 memset (&k,
80 0,
81 sizeof(struct GNUNET_HashCode));
82 for (unsigned int i = 0; i < 10; i++)
83 {
84 fprintf (stderr,
85 "%s",
86 ".");
87 GNUNET_CRYPTO_hash (&k,
88 sizeof(struct GNUNET_HashCode),
89 &n);
90 for (unsigned int j = i; j < sizeof(buf); j += 10)
91 {
92 buf[j] = i;
93 block.key = k;
94 block.data = buf;
95 block.data_size = j;
96 memset (&block.trunc_peer,
97 43,
98 sizeof (block.trunc_peer));
99 block.ro = 42;
100 block.type = (enum GNUNET_BLOCK_Type) (1 + i);
101 block.put_path = NULL;
102 block.put_path_length = 0;
103 block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
104 block.expiration_time.abs_value_us++;
105 ASSERT (GNUNET_OK ==
106 GNUNET_DATACACHE_put (h,
107 42,
108 &block));
109 ASSERT (0 < GNUNET_DATACACHE_get (h,
110 &k,
111 1 + i,
112 NULL,
113 NULL));
114 }
115 k = n;
116 }
117 fprintf (stderr, "%s", "\n");
118 memset (&k,
119 0,
120 sizeof(struct GNUNET_HashCode));
121 for (unsigned int i = 0; i < 10; i++)
122 {
123 fprintf (stderr, "%s", ".");
124 GNUNET_CRYPTO_hash (&k,
125 sizeof(struct GNUNET_HashCode),
126 &n);
127 if (i < 2)
128 ASSERT (0 ==
129 GNUNET_DATACACHE_get (h,
130 &k,
131 1 + i,
132 NULL,
133 NULL));
134 if (i == 9)
135 ASSERT (0 < GNUNET_DATACACHE_get (h,
136 &k,
137 1 + i,
138 NULL,
139 NULL));
140 k = n;
141 }
142 fprintf (stderr,
143 "%s",
144 "\n");
145 GNUNET_DATACACHE_destroy (h);
146 return;
147FAILURE:
148 if (h != NULL)
149 GNUNET_DATACACHE_destroy (h);
150 ok = GNUNET_SYSERR;
151}
152
153
154int
155main (int argc,
156 char *argv[])
157{
158 char cfg_name[PATH_MAX];
159 char *const xargv[] = {
160 "test-datacache-quota",
161 "-c",
162 cfg_name,
163 NULL
164 };
165 struct GNUNET_GETOPT_CommandLineOption options[] = {
166 GNUNET_GETOPT_OPTION_END
167 };
168
169 (void) argc;
170 GNUNET_log_setup ("test-datacache-quota",
171 "WARNING",
172 NULL);
173
174 plugin_name = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]);
175 GNUNET_snprintf (cfg_name,
176 sizeof(cfg_name),
177 "test_datacache_data_%s.conf",
178 plugin_name);
179 if (GNUNET_OK != GNUNET_PROGRAM_run ((sizeof(xargv) / sizeof(char *)) - 1,
180 xargv,
181 "test-datacache-quota",
182 "nohelp",
183 options,
184 &run,
185 NULL))
186 {
187 GNUNET_free (plugin_name);
188 return 1;
189 }
190 if (0 != ok)
191 fprintf (stderr,
192 "Missed some testcases: %d\n",
193 ok);
194 GNUNET_free (plugin_name);
195 return ok;
196}
197
198
199/* end of test_datacache_quota.c */