aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_flat.c
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2018-10-15 19:05:11 +0900
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2018-10-15 19:05:11 +0900
commit116171c281ff6f301198ff9499d158995abaae51 (patch)
tree47831fe94dbf9de42ad9552784eedfc8a2f29ac2 /src/namestore/plugin_namestore_flat.c
parent4a5c38e78760886f5ad53259481487e03c61e372 (diff)
downloadgnunet-116171c281ff6f301198ff9499d158995abaae51.tar.gz
gnunet-116171c281ff6f301198ff9499d158995abaae51.zip
NAMESTORE: rename flat plugin to heap
Diffstat (limited to 'src/namestore/plugin_namestore_flat.c')
-rw-r--r--src/namestore/plugin_namestore_flat.c801
1 files changed, 0 insertions, 801 deletions
diff --git a/src/namestore/plugin_namestore_flat.c b/src/namestore/plugin_namestore_flat.c
deleted file mode 100644
index 4873f6e51..000000000
--- a/src/namestore/plugin_namestore_flat.c
+++ /dev/null
@@ -1,801 +0,0 @@
1 /*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2015, 2018 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
19/**
20 * @file namestore/plugin_namestore_flat.c
21 * @brief file-based namestore backend
22 * @author Martin Schanzenbach
23 * @author Christian Grothoff
24 */
25
26#include "platform.h"
27#include "gnunet_namestore_plugin.h"
28#include "gnunet_namestore_service.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "namestore.h"
31
32/**
33 * Context for all functions in this plugin.
34 */
35struct Plugin
36{
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};
51
52
53struct FlatFileEntry
54{
55 /**
56 * Entry zone
57 */
58 struct GNUNET_CRYPTO_EcdsaPrivateKey private_key;
59
60 /**
61 * Record cound
62 */
63 uint32_t record_count;
64
65 /**
66 * Rvalue
67 */
68 uint64_t rvalue;
69
70 /**
71 * Record data
72 */
73 struct GNUNET_GNSRECORD_Data *record_data;
74
75 /**
76 * Label
77 */
78 char *label;
79
80
81};
82
83
84/**
85 * Initialize the database connections and associated
86 * data structures (create tables and indices
87 * as needed as well).
88 *
89 * @param plugin the plugin context (state for this module)
90 * @return #GNUNET_OK on success
91 */
92static int
93database_setup (struct Plugin *plugin)
94{
95 char *afsdir;
96 char *record_data;
97 char *zone_private_key;
98 char *record_data_b64;
99 char *buffer;
100 char *line;
101 char *label;
102 char *rvalue;
103 char *record_count;
104 size_t record_data_size;
105 uint64_t size;
106 struct GNUNET_HashCode hkey;
107 struct GNUNET_DISK_FileHandle *fh;
108 struct FlatFileEntry *entry;
109
110 if (GNUNET_OK !=
111 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
112 "namestore-flat",
113 "FILENAME",
114 &afsdir))
115 {
116 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
117 "namestore-flat",
118 "FILENAME");
119 return GNUNET_SYSERR;
120 }
121 if (GNUNET_OK !=
122 GNUNET_DISK_file_test (afsdir))
123 {
124 if (GNUNET_OK !=
125 GNUNET_DISK_directory_create_for_file (afsdir))
126 {
127 GNUNET_break (0);
128 GNUNET_free (afsdir);
129 return GNUNET_SYSERR;
130 }
131 }
132 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
133 plugin->fn = afsdir;
134
135 /* Load data from file into hashmap */
136 plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
137 GNUNET_NO);
138 fh = GNUNET_DISK_file_open (afsdir,
139 GNUNET_DISK_OPEN_CREATE |
140 GNUNET_DISK_OPEN_READWRITE,
141 GNUNET_DISK_PERM_USER_WRITE |
142 GNUNET_DISK_PERM_USER_READ);
143 if (NULL == fh)
144 {
145 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
146 _("Unable to initialize file: %s.\n"),
147 afsdir);
148 return GNUNET_SYSERR;
149 }
150 if (GNUNET_SYSERR ==
151 GNUNET_DISK_file_size (afsdir,
152 &size,
153 GNUNET_YES,
154 GNUNET_YES))
155 {
156 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
157 _("Unable to get filesize: %s.\n"),
158 afsdir);
159 GNUNET_DISK_file_close (fh);
160 return GNUNET_SYSERR;
161 }
162
163 buffer = GNUNET_malloc (size + 1);
164 if (GNUNET_SYSERR ==
165 GNUNET_DISK_file_read (fh,
166 buffer,
167 size))
168 {
169 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
170 _("Unable to read file: %s.\n"),
171 afsdir);
172 GNUNET_free (buffer);
173 GNUNET_DISK_file_close (fh);
174 return GNUNET_SYSERR;
175 }
176 buffer[size] = '\0';
177 GNUNET_DISK_file_close (fh);
178
179 if (0 < size)
180 {
181 line = strtok (buffer, "\n");
182 while (line != NULL)
183 {
184 zone_private_key = strtok (line, ",");
185 if (NULL == zone_private_key)
186 break;
187 rvalue = strtok (NULL, ",");
188 if (NULL == rvalue)
189 break;
190 record_count = strtok (NULL, ",");
191 if (NULL == record_count)
192 break;
193 record_data_b64 = strtok (NULL, ",");
194 if (NULL == record_data_b64)
195 break;
196 label = strtok (NULL, ",");
197 if (NULL == label)
198 break;
199 line = strtok (NULL, "\n");
200 entry = GNUNET_new (struct FlatFileEntry);
201 {
202 unsigned long long ll;
203
204 if (1 != sscanf (rvalue,
205 "%llu",
206 &ll))
207 {
208 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
209 "Error parsing entry\n");
210 GNUNET_free (entry);
211 break;
212 }
213 entry->rvalue = (uint64_t) ll;
214 }
215 {
216 unsigned int ui;
217
218 if (1 != sscanf (record_count,
219 "%u",
220 &ui))
221 {
222 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
223 "Error parsing entry\n");
224 GNUNET_free (entry);
225 break;
226 }
227 entry->record_count = (uint32_t) ui;
228 }
229 entry->label = GNUNET_strdup (label);
230 record_data_size
231 = GNUNET_STRINGS_base64_decode (record_data_b64,
232 strlen (record_data_b64),
233 (void **) &record_data);
234 entry->record_data =
235 GNUNET_new_array (entry->record_count,
236 struct GNUNET_GNSRECORD_Data);
237 if (GNUNET_OK !=
238 GNUNET_GNSRECORD_records_deserialize (record_data_size,
239 record_data,
240 entry->record_count,
241 entry->record_data))
242 {
243 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
244 "Unable to deserialize record %s\n",
245 label);
246 GNUNET_free (entry->label);
247 GNUNET_free (entry);
248 GNUNET_free (record_data);
249 break;
250 }
251 GNUNET_free (record_data);
252
253 {
254 struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key;
255
256 GNUNET_STRINGS_base64_decode (zone_private_key,
257 strlen (zone_private_key),
258 (void**)&private_key);
259 entry->private_key = *private_key;
260 GNUNET_free (private_key);
261 }
262
263 {
264 char *key;
265 size_t key_len;
266
267 key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
268 key = GNUNET_malloc (strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
269 GNUNET_memcpy (key,
270 label,
271 strlen (label));
272 GNUNET_memcpy (key+strlen(label),
273 &entry->private_key,
274 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
275 GNUNET_CRYPTO_hash (key,
276 key_len,
277 &hkey);
278 GNUNET_free (key);
279 }
280 if (GNUNET_OK !=
281 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
282 &hkey,
283 entry,
284 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
285 {
286 GNUNET_free (entry);
287 GNUNET_break (0);
288 }
289 }
290 }
291 GNUNET_free (buffer);
292 return GNUNET_OK;
293}
294
295
296/**
297 * Store values in hashmap in file and free data
298 *
299 * @param plugin the plugin context
300 * @param key key in the map
301 * @param value a `struct FlatFileEntry`
302 */
303static int
304store_and_free_entries (void *cls,
305 const struct GNUNET_HashCode *key,
306 void *value)
307{
308 struct GNUNET_DISK_FileHandle *fh = cls;
309 struct FlatFileEntry *entry = value;
310 char *line;
311 char *zone_private_key;
312 char *record_data_b64;
313 ssize_t data_size;
314
315 (void) key;
316 GNUNET_STRINGS_base64_encode (&entry->private_key,
317 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
318 &zone_private_key);
319 data_size = GNUNET_GNSRECORD_records_get_size (entry->record_count,
320 entry->record_data);
321 if (data_size < 0)
322 {
323 GNUNET_break (0);
324 GNUNET_free (zone_private_key);
325 return GNUNET_SYSERR;
326 }
327 if (data_size >= UINT16_MAX)
328 {
329 GNUNET_break (0);
330 GNUNET_free (zone_private_key);
331 return GNUNET_SYSERR;
332 }
333 {
334 char data[data_size];
335 ssize_t ret;
336
337 ret = GNUNET_GNSRECORD_records_serialize (entry->record_count,
338 entry->record_data,
339 data_size,
340 data);
341 if ( (ret < 0) ||
342 (data_size != ret) )
343 {
344 GNUNET_break (0);
345 GNUNET_free (zone_private_key);
346 return GNUNET_SYSERR;
347 }
348 GNUNET_STRINGS_base64_encode (data,
349 data_size,
350 &record_data_b64);
351 }
352 GNUNET_asprintf (&line,
353 "%s,%llu,%u,%s,%s\n",
354 zone_private_key,
355 (unsigned long long) entry->rvalue,
356 (unsigned int) entry->record_count,
357 record_data_b64,
358 entry->label);
359 GNUNET_free (record_data_b64);
360 GNUNET_free (zone_private_key);
361
362 GNUNET_DISK_file_write (fh,
363 line,
364 strlen (line));
365
366 GNUNET_free (line);
367 GNUNET_free (entry->label);
368 GNUNET_free (entry->record_data);
369 GNUNET_free (entry);
370 return GNUNET_YES;
371}
372
373
374/**
375 * Shutdown database connection and associate data
376 * structures.
377 * @param plugin the plugin context (state for this module)
378 */
379static void
380database_shutdown (struct Plugin *plugin)
381{
382 struct GNUNET_DISK_FileHandle *fh;
383
384 fh = GNUNET_DISK_file_open (plugin->fn,
385 GNUNET_DISK_OPEN_CREATE |
386 GNUNET_DISK_OPEN_TRUNCATE |
387 GNUNET_DISK_OPEN_READWRITE,
388 GNUNET_DISK_PERM_USER_WRITE |
389 GNUNET_DISK_PERM_USER_READ);
390 if (NULL == fh)
391 {
392 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
393 _("Unable to initialize file: %s.\n"),
394 plugin->fn);
395 return;
396 }
397
398 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
399 &store_and_free_entries,
400 fh);
401 GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
402 GNUNET_DISK_file_close (fh);
403}
404
405
406/**
407 * Store a record in the datastore. Removes any existing record in the
408 * same zone with the same name.
409 *
410 * @param cls closure (internal context for the plugin)
411 * @param zone_key private key of the zone
412 * @param label name that is being mapped (at most 255 characters long)
413 * @param rd_count number of entries in @a rd array
414 * @param rd array of records with data to store
415 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
416 */
417static int
418namestore_flat_store_records (void *cls,
419 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
420 const char *label,
421 unsigned int rd_count,
422 const struct GNUNET_GNSRECORD_Data *rd)
423{
424 struct Plugin *plugin = cls;
425 uint64_t rvalue;
426 size_t key_len;
427 char *key;
428 struct GNUNET_HashCode hkey;
429 struct FlatFileEntry *entry;
430
431 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
432 UINT64_MAX);
433 key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
434 key = GNUNET_malloc (key_len);
435 GNUNET_memcpy (key,
436 label,
437 strlen (label));
438 GNUNET_memcpy (key + strlen(label),
439 zone_key,
440 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
441 GNUNET_CRYPTO_hash (key,
442 key_len,
443 &hkey);
444 GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm,
445 &hkey);
446 if (0 == rd_count)
447 {
448 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
449 "sqlite",
450 "Record deleted\n");
451 return GNUNET_OK;
452 }
453 entry = GNUNET_new (struct FlatFileEntry);
454 GNUNET_asprintf (&entry->label,
455 label,
456 strlen (label));
457 GNUNET_memcpy (&entry->private_key,
458 zone_key,
459 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
460 entry->rvalue = rvalue;
461 entry->record_count = rd_count;
462 entry->record_data = GNUNET_new_array (rd_count,
463 struct GNUNET_GNSRECORD_Data);
464 for (unsigned int i = 0; i < rd_count; i++)
465 {
466 entry->record_data[i].expiration_time = rd[i].expiration_time;
467 entry->record_data[i].record_type = rd[i].record_type;
468 entry->record_data[i].flags = rd[i].flags;
469 entry->record_data[i].data_size = rd[i].data_size;
470 entry->record_data[i].data = GNUNET_malloc (rd[i].data_size);
471 GNUNET_memcpy ((char*)entry->record_data[i].data,
472 rd[i].data,
473 rd[i].data_size);
474 }
475 return GNUNET_CONTAINER_multihashmap_put (plugin->hm,
476 &hkey,
477 entry,
478 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
479}
480
481
482/**
483 * Lookup records in the datastore for which we are the authority.
484 *
485 * @param cls closure (internal context for the plugin)
486 * @param zone private key of the zone
487 * @param label name of the record in the zone
488 * @param iter function to call with the result
489 * @param iter_cls closure for @a iter
490 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
491 */
492static int
493namestore_flat_lookup_records (void *cls,
494 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
495 const char *label,
496 GNUNET_NAMESTORE_RecordIterator iter,
497 void *iter_cls)
498{
499 struct Plugin *plugin = cls;
500 struct FlatFileEntry *entry;
501 struct GNUNET_HashCode hkey;
502 char *key;
503 size_t key_len;
504
505 if (NULL == zone)
506 {
507 GNUNET_break (0);
508 return GNUNET_SYSERR;
509 }
510 key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
511 key = GNUNET_malloc (key_len);
512 GNUNET_memcpy (key,
513 label,
514 strlen (label));
515 GNUNET_memcpy (key+strlen(label),
516 zone,
517 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
518 GNUNET_CRYPTO_hash (key,
519 key_len,
520 &hkey);
521 GNUNET_free (key);
522
523 entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm,
524 &hkey);
525
526 if (NULL == entry)
527 return GNUNET_NO;
528 if (NULL != iter)
529 iter (iter_cls,
530 0,
531 &entry->private_key,
532 entry->label,
533 entry->record_count,
534 entry->record_data);
535 return GNUNET_YES;
536}
537
538
539/**
540 * Closure for #iterate_zones.
541 */
542struct IterateContext
543{
544 /**
545 * How many more records should we skip before returning results?
546 */
547 uint64_t offset;
548
549 /**
550 * How many more records should we return?
551 */
552 uint64_t limit;
553
554 /**
555 * What is the position of the current entry, counting
556 * starts from 1.
557 */
558 uint64_t pos;
559
560 /**
561 * Target zone.
562 */
563 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone;
564
565 /**
566 * Function to call on each record.
567 */
568 GNUNET_NAMESTORE_RecordIterator iter;
569
570 /**
571 * Closure for @e iter.
572 */
573 void *iter_cls;
574
575};
576
577
578/**
579 * Helper function for #namestore_flat_iterate_records().
580 *
581 * @param cls a `struct IterateContext`
582 * @param key unused
583 * @param value a `struct FlatFileEntry`
584 * @return #GNUNET_YES to continue the iteration
585 */
586static int
587iterate_zones (void *cls,
588 const struct GNUNET_HashCode *key,
589 void *value)
590{
591 struct IterateContext *ic = cls;
592 struct FlatFileEntry *entry = value;
593
594 (void) key;
595 if (0 == ic->limit)
596 return GNUNET_NO;
597 if ( (NULL != ic->zone) &&
598 (0 != memcmp (&entry->private_key,
599 ic->zone,
600 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
601 return GNUNET_YES;
602 ic->pos++;
603 if (ic->offset > 0)
604 {
605 ic->offset--;
606 return GNUNET_YES;
607 }
608 ic->iter (ic->iter_cls,
609 ic->pos,
610 (NULL == ic->zone)
611 ? &entry->private_key
612 : ic->zone,
613 entry->label,
614 entry->record_count,
615 entry->record_data);
616 ic->limit--;
617 if (0 == ic->limit)
618 return GNUNET_NO;
619 return GNUNET_YES;
620}
621
622
623/**
624 * Iterate over the results for a particular key and zone in the
625 * datastore. Will return at most one result to the iterator.
626 *
627 * @param cls closure (internal context for the plugin)
628 * @param zone hash of public key of the zone, NULL to iterate over all zones
629 * @param serial serial number to exclude in the list of all matching records
630 * @param limit maximum number of results to return to @a iter
631 * @param iter function to call with the result
632 * @param iter_cls closure for @a iter
633 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
634 */
635static int
636namestore_flat_iterate_records (void *cls,
637 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
638 uint64_t serial,
639 uint64_t limit,
640 GNUNET_NAMESTORE_RecordIterator iter,
641 void *iter_cls)
642{
643 struct Plugin *plugin = cls;
644 struct IterateContext ic;
645
646 ic.offset = serial;
647 ic.pos = 0;
648 ic.limit = limit;
649 ic.iter = iter;
650 ic.iter_cls = iter_cls;
651 ic.zone = zone;
652 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
653 &iterate_zones,
654 &ic);
655 return (0 == ic.limit) ? GNUNET_OK : GNUNET_NO;
656}
657
658
659/**
660 * Closure for #zone_to_name.
661 */
662struct ZoneToNameContext
663{
664 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone;
665 const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone;
666 GNUNET_NAMESTORE_RecordIterator iter;
667 void *iter_cls;
668
669 int result_found;
670};
671
672
673static int
674zone_to_name (void *cls,
675 const struct GNUNET_HashCode *key,
676 void *value)
677{
678 struct ZoneToNameContext *ztn = cls;
679 struct FlatFileEntry *entry = value;
680
681 (void) key;
682 if (0 != memcmp (&entry->private_key,
683 ztn->zone,
684 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
685 return GNUNET_YES;
686
687 for (unsigned int i = 0; i < entry->record_count; i++)
688 {
689 if (GNUNET_GNSRECORD_TYPE_PKEY != entry->record_data[i].record_type)
690 continue;
691 if (0 == memcmp (ztn->value_zone,
692 entry->record_data[i].data,
693 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
694 {
695 ztn->iter (ztn->iter_cls,
696 0,
697 &entry->private_key,
698 entry->label,
699 entry->record_count,
700 entry->record_data);
701 ztn->result_found = GNUNET_YES;
702 }
703 }
704 return GNUNET_YES;
705}
706
707
708/**
709 * Look for an existing PKEY delegation record for a given public key.
710 * Returns at most one result to the iterator.
711 *
712 * @param cls closure (internal context for the plugin)
713 * @param zone private key of the zone to look up in, never NULL
714 * @param value_zone public key of the target zone (value), never NULL
715 * @param iter function to call with the result
716 * @param iter_cls closure for @a iter
717 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
718 */
719static int
720namestore_flat_zone_to_name (void *cls,
721 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
722 const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
723 GNUNET_NAMESTORE_RecordIterator iter,
724 void *iter_cls)
725{
726 struct Plugin *plugin = cls;
727 struct ZoneToNameContext ztn = {
728 .iter = iter,
729 .iter_cls = iter_cls,
730 .zone = zone,
731 .value_zone = value_zone,
732 .result_found = GNUNET_NO
733 };
734
735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
736 "Performing reverse lookup for `%s'\n",
737 GNUNET_GNSRECORD_z2s (value_zone));
738 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
739 &zone_to_name,
740 &ztn);
741 return ztn.result_found;
742}
743
744
745/**
746 * Entry point for the plugin.
747 *
748 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
749 * @return NULL on error, otherwise the plugin context
750 */
751void *
752libgnunet_plugin_namestore_flat_init (void *cls)
753{
754 static struct Plugin plugin;
755 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
756 struct GNUNET_NAMESTORE_PluginFunctions *api;
757
758 if (NULL != plugin.cfg)
759 return NULL; /* can only initialize once! */
760 memset (&plugin,
761 0,
762 sizeof (struct Plugin));
763 plugin.cfg = cfg;
764 if (GNUNET_OK != database_setup (&plugin))
765 {
766 database_shutdown (&plugin);
767 return NULL;
768 }
769 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
770 api->cls = &plugin;
771 api->store_records = &namestore_flat_store_records;
772 api->iterate_records = &namestore_flat_iterate_records;
773 api->zone_to_name = &namestore_flat_zone_to_name;
774 api->lookup_records = &namestore_flat_lookup_records;
775 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
776 _("flat file database running\n"));
777 return api;
778}
779
780
781/**
782 * Exit point from the plugin.
783 *
784 * @param cls the plugin context (as returned by "init")
785 * @return always NULL
786 */
787void *
788libgnunet_plugin_namestore_flat_done (void *cls)
789{
790 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
791 struct Plugin *plugin = api->cls;
792
793 database_shutdown (plugin);
794 plugin->cfg = NULL;
795 GNUNET_free (api);
796 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
797 "flat file plugin is finished\n");
798 return NULL;
799}
800
801/* end of plugin_namestore_flat.c */