aboutsummaryrefslogtreecommitdiff
path: root/src/namecache/plugin_namecache_flat.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-19 09:16:49 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-19 09:16:49 +0200
commit54a37c4239d34fc3b681df78a5a8b4d6a7bde902 (patch)
tree8eff6cc8c4fcba2c6c296a9ee40928f5096de964 /src/namecache/plugin_namecache_flat.c
parent7f72b05249f6ac663cee7a033f3cac5d9400ede7 (diff)
downloadgnunet-54a37c4239d34fc3b681df78a5a8b4d6a7bde902.tar.gz
gnunet-54a37c4239d34fc3b681df78a5a8b4d6a7bde902.zip
BUILD: Move namecache to service
Diffstat (limited to 'src/namecache/plugin_namecache_flat.c')
-rw-r--r--src/namecache/plugin_namecache_flat.c430
1 files changed, 0 insertions, 430 deletions
diff --git a/src/namecache/plugin_namecache_flat.c b/src/namecache/plugin_namecache_flat.c
deleted file mode 100644
index eb7800051..000000000
--- a/src/namecache/plugin_namecache_flat.c
+++ /dev/null
@@ -1,430 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-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/**
22 * @file namecache/plugin_namecache_flat.c
23 * @brief flat file-based namecache backend
24 * @author Martin Schanzenbach
25 */
26
27#include "platform.h"
28#include "gnunet_namecache_plugin.h"
29#include "gnunet_namecache_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "namecache.h"
32
33/**
34 * Context for all functions in this plugin.
35 */
36struct Plugin
37{
38 const struct GNUNET_CONFIGURATION_Handle *cfg;
39
40 /**
41 * Database filename.
42 */
43 char *fn;
44
45 /**
46 * HashMap
47 */
48 struct GNUNET_CONTAINER_MultiHashMap *hm;
49};
50
51struct FlatFileEntry
52{
53 /**
54 * Block
55 */
56 struct GNUNET_GNSRECORD_Block *block;
57
58 /**
59 * query
60 */
61 struct GNUNET_HashCode query;
62};
63
64/**
65 * Initialize the database connections and associated
66 * data structures (create tables and indices
67 * as needed as well).
68 *
69 * @param plugin the plugin context (state for this module)
70 * @return #GNUNET_OK on success
71 */
72static int
73database_setup (struct Plugin *plugin)
74{
75 char *afsdir;
76 char*block_buffer;
77 char*buffer;
78 char*line;
79 char*query;
80 char*block;
81 uint64_t size;
82 struct FlatFileEntry *entry;
83 struct GNUNET_DISK_FileHandle *fh;
84
85 if (GNUNET_OK !=
86 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
87 "namecache-flat",
88 "FILENAME",
89 &afsdir))
90 {
91 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
92 "namecache-flat", "FILENAME");
93 return GNUNET_SYSERR;
94 }
95 if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
96 {
97 if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir))
98 {
99 GNUNET_break (0);
100 GNUNET_free (afsdir);
101 return GNUNET_SYSERR;
102 }
103 }
104 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
105 plugin->fn = afsdir;
106
107 /* Load data from file into hashmap */
108 plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
109 GNUNET_NO);
110 fh = GNUNET_DISK_file_open (afsdir,
111 GNUNET_DISK_OPEN_CREATE
112 | GNUNET_DISK_OPEN_READWRITE,
113 GNUNET_DISK_PERM_USER_WRITE
114 | GNUNET_DISK_PERM_USER_READ);
115 if (NULL == fh)
116 {
117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118 _ ("Unable to initialize file: %s.\n"),
119 afsdir);
120 return GNUNET_SYSERR;
121 }
122
123 if (GNUNET_SYSERR == GNUNET_DISK_file_size (afsdir,
124 &size,
125 GNUNET_YES,
126 GNUNET_YES))
127 {
128 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
129 _ ("Unable to get filesize: %s.\n"),
130 afsdir);
131 GNUNET_DISK_file_close (fh);
132 return GNUNET_SYSERR;
133 }
134
135 if (0 == size)
136 {
137 GNUNET_DISK_file_close (fh);
138 return GNUNET_OK;
139 }
140
141 buffer = GNUNET_malloc (size + 1);
142
143 if (GNUNET_SYSERR == GNUNET_DISK_file_read (fh,
144 buffer,
145 size))
146 {
147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
148 _ ("Unable to read file: %s.\n"),
149 afsdir);
150 GNUNET_free (buffer);
151 GNUNET_DISK_file_close (fh);
152 return GNUNET_SYSERR;
153 }
154 buffer[size] = '\0';
155
156 GNUNET_DISK_file_close (fh);
157 if (0 < size)
158 {
159 line = strtok (buffer, "\n");
160 while (line != NULL)
161 {
162 query = strtok (line, ",");
163 if (NULL == query)
164 break;
165 block = strtok (NULL, ",");
166 if (NULL == block)
167 break;
168 line = strtok (NULL, "\n");
169 entry = GNUNET_malloc (sizeof(struct FlatFileEntry));
170 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_hash_from_string (query,
171 &entry->query));
172 GNUNET_STRINGS_base64_decode (block,
173 strlen (block),
174 (void **) &block_buffer);
175 entry->block = (struct GNUNET_GNSRECORD_Block *) block_buffer;
176 if (GNUNET_OK !=
177 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
178 &entry->query,
179 entry,
180 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
181 {
182 GNUNET_free (entry);
183 GNUNET_break (0);
184 }
185 }
186 }
187 GNUNET_free (buffer);
188 return GNUNET_OK;
189}
190
191
192/**
193 * Store values in hashmap in file and free data
194 *
195 * @param plugin the plugin context
196 */
197static int
198store_and_free_entries (void *cls,
199 const struct GNUNET_HashCode *key,
200 void *value)
201{
202 struct GNUNET_DISK_FileHandle *fh = cls;
203 struct FlatFileEntry *entry = value;
204
205 char *line;
206 char *block_b64;
207 struct GNUNET_CRYPTO_HashAsciiEncoded query;
208 size_t block_size;
209
210 block_size = GNUNET_GNSRECORD_block_get_size (entry->block);
211 GNUNET_STRINGS_base64_encode ((char *) entry->block,
212 block_size,
213 &block_b64);
214 GNUNET_CRYPTO_hash_to_enc (&entry->query,
215 &query);
216 GNUNET_asprintf (&line,
217 "%s,%s\n",
218 (char *) &query,
219 block_b64);
220
221 GNUNET_free (block_b64);
222
223 GNUNET_DISK_file_write (fh,
224 line,
225 strlen (line));
226
227 GNUNET_free (entry->block);
228 GNUNET_free (entry);
229 GNUNET_free (line);
230 return GNUNET_YES;
231}
232
233
234/**
235 * Shutdown database connection and associate data
236 * structures.
237 * @param plugin the plugin context (state for this module)
238 */
239static void
240database_shutdown (struct Plugin *plugin)
241{
242 struct GNUNET_DISK_FileHandle *fh;
243
244 fh = GNUNET_DISK_file_open (plugin->fn,
245 GNUNET_DISK_OPEN_CREATE
246 | GNUNET_DISK_OPEN_TRUNCATE
247 | GNUNET_DISK_OPEN_READWRITE,
248 GNUNET_DISK_PERM_USER_WRITE
249 | GNUNET_DISK_PERM_USER_READ);
250 if (NULL == fh)
251 {
252 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
253 _ ("Unable to initialize file: %s.\n"),
254 plugin->fn);
255 return;
256 }
257
258 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
259 &store_and_free_entries,
260 fh);
261 GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
262 GNUNET_DISK_file_close (fh);
263}
264
265
266static int
267expire_blocks (void *cls,
268 const struct GNUNET_HashCode *key,
269 void *value)
270{
271 struct Plugin *plugin = cls;
272 struct FlatFileEntry *entry = value;
273 struct GNUNET_TIME_Absolute now;
274 struct GNUNET_TIME_Absolute expiration;
275
276 now = GNUNET_TIME_absolute_get ();
277 expiration = GNUNET_GNSRECORD_block_get_expiration (entry->block);
278
279 if (0 == GNUNET_TIME_absolute_get_difference (now,
280 expiration).rel_value_us)
281 {
282 GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm, key);
283 }
284 return GNUNET_YES;
285}
286
287
288/**
289 * Removes any expired block.
290 *
291 * @param plugin the plugin
292 */
293static void
294namecache_expire_blocks (struct Plugin *plugin)
295{
296 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
297 &expire_blocks,
298 plugin);
299}
300
301
302/**
303 * Cache a block in the datastore.
304 *
305 * @param cls closure (internal context for the plugin)
306 * @param block block to cache
307 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
308 */
309static int
310namecache_cache_block (void *cls,
311 const struct GNUNET_GNSRECORD_Block *block)
312{
313 struct Plugin *plugin = cls;
314 struct GNUNET_HashCode query;
315 struct FlatFileEntry *entry;
316 size_t block_size;
317
318 namecache_expire_blocks (plugin);
319 GNUNET_GNSRECORD_query_from_block (block,
320 &query);
321 block_size = GNUNET_GNSRECORD_block_get_size (block);
322 if (block_size > 64 * 65536)
323 {
324 GNUNET_break (0);
325 return GNUNET_SYSERR;
326 }
327 entry = GNUNET_malloc (sizeof(struct FlatFileEntry));
328 entry->block = GNUNET_malloc (block_size);
329 GNUNET_memcpy (entry->block, block, block_size);
330 GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm, &query);
331 if (GNUNET_OK !=
332 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
333 &query,
334 entry,
335 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
336 {
337 GNUNET_free (entry);
338 GNUNET_break (0);
339 return GNUNET_SYSERR;
340 }
341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
342 "Caching block under derived key `%s'\n",
343 GNUNET_h2s_full (&query));
344 return GNUNET_OK;
345}
346
347
348/**
349 * Get the block for a particular zone and label in the
350 * datastore. Will return at most one result to the iterator.
351 *
352 * @param cls closure (internal context for the plugin)
353 * @param query hash of public key derived from the zone and the label
354 * @param iter function to call with the result
355 * @param iter_cls closure for @a iter
356 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
357 */
358static int
359namecache_lookup_block (void *cls,
360 const struct GNUNET_HashCode *query,
361 GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls)
362{
363 struct Plugin *plugin = cls;
364 const struct GNUNET_GNSRECORD_Block *block;
365
366 block = GNUNET_CONTAINER_multihashmap_get (plugin->hm, query);
367 if (NULL == block)
368 return GNUNET_NO;
369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
370 "Found block under derived key `%s'\n",
371 GNUNET_h2s_full (query));
372 iter (iter_cls, block);
373 return GNUNET_YES;
374}
375
376
377/**
378 * Entry point for the plugin.
379 *
380 * @param cls the "struct GNUNET_NAMECACHE_PluginEnvironment*"
381 * @return NULL on error, otherwise the plugin context
382 */
383void *
384libgnunet_plugin_namecache_flat_init (void *cls)
385{
386 static struct Plugin plugin;
387 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
388 struct GNUNET_NAMECACHE_PluginFunctions *api;
389
390 if (NULL != plugin.cfg)
391 return NULL; /* can only initialize once! */
392 memset (&plugin, 0, sizeof(struct Plugin));
393 plugin.cfg = cfg;
394 if (GNUNET_OK != database_setup (&plugin))
395 {
396 database_shutdown (&plugin);
397 return NULL;
398 }
399 api = GNUNET_new (struct GNUNET_NAMECACHE_PluginFunctions);
400 api->cls = &plugin;
401 api->cache_block = &namecache_cache_block;
402 api->lookup_block = &namecache_lookup_block;
403 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
404 _ ("flat plugin running\n"));
405 return api;
406}
407
408
409/**
410 * Exit point from the plugin.
411 *
412 * @param cls the plugin context (as returned by "init")
413 * @return always NULL
414 */
415void *
416libgnunet_plugin_namecache_flat_done (void *cls)
417{
418 struct GNUNET_NAMECACHE_PluginFunctions *api = cls;
419 struct Plugin *plugin = api->cls;
420
421 database_shutdown (plugin);
422 plugin->cfg = NULL;
423 GNUNET_free (api);
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
425 "flat plugin is finished\n");
426 return NULL;
427}
428
429
430/* end of plugin_namecache_sqlite.c */