GNUnet  0.10.x
plugin_peerstore_flat.c
Go to the documentation of this file.
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 
27 #include "platform.h"
30 #include "peerstore.h"
31 
35 struct Plugin {
39  const struct GNUNET_CONFIGURATION_Handle *cfg;
40 
45 
50 
54  void *iter_cls;
55 
59  const char *iter_key;
60 
65 
69  const char *iter_sub_system;
70 
75 
79  uint64_t deleted_entries;
80 
84  uint64_t exp_changes;
85 
89  char *fn;
90 
95 };
96 
97 
98 static int
99 delete_entries(void *cls,
100  const struct GNUNET_HashCode *key,
101  void *value)
102 {
103  struct Plugin *plugin = cls;
104  struct GNUNET_PEERSTORE_Record *entry = value;
105 
106  if (0 != strcmp(plugin->iter_key, entry->key))
107  return GNUNET_YES;
108  if (0 != memcmp(plugin->iter_peer,
109  &entry->peer,
110  sizeof(struct GNUNET_PeerIdentity)))
111  return GNUNET_YES;
112  if (0 != strcmp(plugin->iter_sub_system, entry->sub_system))
113  return GNUNET_YES;
114 
115  GNUNET_CONTAINER_multihashmap_remove(plugin->hm, key, value);
116  plugin->deleted_entries++;
117  return GNUNET_YES;
118 }
119 
120 
130 static int
132  const struct GNUNET_PeerIdentity *peer,
133  const char *key)
134 {
135  struct Plugin *plugin = cls;
136 
137  plugin->iter_sub_system = sub_system;
138  plugin->iter_peer = peer;
139  plugin->iter_key = key;
140  plugin->deleted_entries = 0;
141 
144  plugin);
145  return plugin->deleted_entries;
146 }
147 
148 static int
149 expire_entries(void *cls,
150  const struct GNUNET_HashCode *key,
151  void *value)
152 {
153  struct Plugin *plugin = cls;
154  struct GNUNET_PEERSTORE_Record *entry = value;
155 
156  if (entry->expiry.abs_value_us < plugin->iter_now.abs_value_us)
157  {
158  GNUNET_CONTAINER_multihashmap_remove(plugin->hm, key, value);
159  plugin->exp_changes++;
160  }
161  return GNUNET_YES;
162 }
163 
164 
165 
176 static int
179  void *cont_cls)
180 {
181  struct Plugin *plugin = cls;
182 
183  plugin->exp_changes = 0;
184  plugin->iter_now = now;
185 
188  plugin);
189  if (NULL != cont)
190  {
191  cont(cont_cls, plugin->exp_changes);
192  }
193  return GNUNET_OK;
194 }
195 
196 
197 static int
198 iterate_entries(void *cls,
199  const struct GNUNET_HashCode *key,
200  void *value)
201 {
202  struct Plugin *plugin = cls;
203  struct GNUNET_PEERSTORE_Record *entry = value;
204 
205  if ((NULL != plugin->iter_peer) &&
206  (0 != memcmp(plugin->iter_peer,
207  &entry->peer,
208  sizeof(struct GNUNET_PeerIdentity))))
209  {
210  return GNUNET_YES;
211  }
212  if ((NULL != plugin->iter_key) &&
213  (0 != strcmp(plugin->iter_key,
214  entry->key)))
215  {
216  return GNUNET_YES;
217  }
218  if (NULL != plugin->iter)
219  plugin->iter(plugin->iter_cls, entry, NULL);
220  plugin->iter_result_found = GNUNET_YES;
221  return GNUNET_YES;
222 }
223 
238 static int
240  const struct GNUNET_PeerIdentity *peer,
241  const char *key,
243  void *iter_cls)
244 {
245  struct Plugin *plugin = cls;
246 
247  plugin->iter = iter;
248  plugin->iter_cls = iter_cls;
249  plugin->iter_peer = peer;
250  plugin->iter_sub_system = sub_system;
251  plugin->iter_key = key;
252 
255  plugin);
256  if (NULL != iter)
257  iter(iter_cls, NULL, NULL);
258  return GNUNET_OK;
259 }
260 
261 
279 static int
280 peerstore_flat_store_record(void *cls, const char *sub_system,
281  const struct GNUNET_PeerIdentity *peer,
282  const char *key, const void *value, size_t size,
283  struct GNUNET_TIME_Absolute expiry,
286  void *cont_cls)
287 {
288  struct Plugin *plugin = cls;
289  struct GNUNET_HashCode hkey;
290  struct GNUNET_PEERSTORE_Record *entry;
291  const char *peer_id;
292 
293 
294  entry = GNUNET_new(struct GNUNET_PEERSTORE_Record);
295  entry->sub_system = GNUNET_strdup(sub_system);
296  entry->key = GNUNET_strdup(key);
297  entry->value = GNUNET_malloc(size);
298  GNUNET_memcpy(entry->value, value, size);
299  entry->value_size = size;
300  entry->peer = *peer;
301  entry->expiry = expiry;
302 
303  peer_id = GNUNET_i2s(peer);
304  GNUNET_CRYPTO_hash(peer_id,
305  strlen(peer_id),
306  &hkey);
307 
309  {
310  peerstore_flat_delete_records(cls, sub_system, peer, key);
311  }
312 
314  &hkey,
315  entry,
317  if (NULL != cont)
318  {
319  cont(cont_cls, GNUNET_OK);
320  }
321  return GNUNET_OK;
322 }
323 
324 
333 static int
335 {
336  char *afsdir;
337  char *key;
338  char *sub_system;
339  const char *peer_id;
340  char *peer;
341  char *value;
342  char *expiry;
343  struct GNUNET_DISK_FileHandle *fh;
344  struct GNUNET_PEERSTORE_Record *entry;
345  struct GNUNET_HashCode hkey;
346  size_t size;
347  char *buffer;
348  char *line;
349 
350  if (GNUNET_OK !=
351  GNUNET_CONFIGURATION_get_value_filename(plugin->cfg, "peerstore-flat",
352  "FILENAME", &afsdir))
353  {
355  "FILENAME");
356  return GNUNET_SYSERR;
357  }
358  if (GNUNET_OK != GNUNET_DISK_file_test(afsdir))
359  {
361  {
362  GNUNET_break(0);
363  GNUNET_free(afsdir);
364  return GNUNET_SYSERR;
365  }
366  }
367  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
368  plugin->fn = afsdir;
369 
370  fh = GNUNET_DISK_file_open(afsdir,
375  if (NULL == fh)
376  {
378  _("Unable to initialize file: %s.\n"),
379  afsdir);
380  return GNUNET_SYSERR;
381  }
382 
383  /* Load data from file into hashmap */
385  GNUNET_NO);
386 
387  if (GNUNET_SYSERR == GNUNET_DISK_file_size(afsdir,
388  &size,
389  GNUNET_YES,
390  GNUNET_YES))
391  {
393  _("Unable to get filesize: %s.\n"),
394  afsdir);
395  return GNUNET_SYSERR;
396  }
397 
398  buffer = GNUNET_malloc(size + 1);
399 
401  buffer,
402  size))
403  {
405  _("Unable to read file: %s.\n"),
406  afsdir);
408  GNUNET_free(buffer);
409  return GNUNET_SYSERR;
410  }
411 
412  buffer[size] = '\0';
414  if (0 < size)
415  {
416  line = strtok(buffer, "\n");
417  while (line != NULL)
418  {
419  sub_system = strtok(line, ",");
420  if (NULL == sub_system)
421  break;
422  peer = strtok(NULL, ",");
423  if (NULL == peer)
424  break;
425  key = strtok(NULL, ",");
426  if (NULL == key)
427  break;
428  value = strtok(NULL, ",");
429  if (NULL == value)
430  break;
431  expiry = strtok(NULL, ",");
432  if (NULL == expiry)
433  break;
434  entry = GNUNET_new(struct GNUNET_PEERSTORE_Record);
435  entry->sub_system = GNUNET_strdup(sub_system);
436  entry->key = GNUNET_strdup(key);
437  {
438  size_t s;
439  char *o;
440 
441  o = NULL;
443  strlen(peer),
444  (void**)&o);
445  if (sizeof(struct GNUNET_PeerIdentity) == s)
446  GNUNET_memcpy(&entry->peer,
447  o,
448  s);
449  else
450  GNUNET_break(0);
452  }
454  strlen(value),
455  (void**)&entry->value);
456  if (GNUNET_SYSERR ==
458  &entry->expiry))
459  {
460  GNUNET_free(entry->sub_system);
461  GNUNET_free(entry->key);
462  GNUNET_free(entry);
463  break;
464  }
465  peer_id = GNUNET_i2s(&entry->peer);
466  GNUNET_CRYPTO_hash(peer_id,
467  strlen(peer_id),
468  &hkey);
469 
471  &hkey,
472  entry,
474  }
475  }
476  GNUNET_free(buffer);
477  return GNUNET_OK;
478 }
479 
480 static int
482  const struct GNUNET_HashCode *key,
483  void *value)
484 {
485  struct GNUNET_DISK_FileHandle *fh = cls;
486  struct GNUNET_PEERSTORE_Record *entry = value;
487  char *line;
488  char *peer;
489  const char *expiry;
490  char *val;
491 
493  entry->value_size,
494  &val);
496  GNUNET_STRINGS_base64_encode((char*)&entry->peer,
497  sizeof(struct GNUNET_PeerIdentity),
498  &peer);
499  GNUNET_asprintf(&line,
500  "%s,%s,%s,%s,%s",
501  entry->sub_system,
502  peer,
503  entry->key,
504  val,
505  expiry);
506  GNUNET_free(val);
507  GNUNET_free(peer);
509  line,
510  strlen(line));
511  GNUNET_free(entry->sub_system);
512  GNUNET_free(entry->key);
513  GNUNET_free(entry->value);
514  GNUNET_free(entry);
515  GNUNET_free(line);
516  return GNUNET_YES;
517 }
518 
524 static void
526 {
527  struct GNUNET_DISK_FileHandle *fh;
528 
529  fh = GNUNET_DISK_file_open(plugin->fn,
535  if (NULL == fh)
536  {
538  _("Unable to initialize file: %s.\n"),
539  plugin->fn);
540  return;
541  }
544  fh);
547 }
548 
549 
556 void *
558 {
559  static struct Plugin plugin;
560  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
562 
563  if (NULL != plugin.cfg)
564  return NULL; /* can only initialize once! */
565  memset(&plugin, 0, sizeof(struct Plugin));
566  plugin.cfg = cfg;
567  if (GNUNET_OK != database_setup(&plugin))
568  {
569  database_shutdown(&plugin);
570  return NULL;
571  }
573  api->cls = &plugin;
577  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Flat plugin is running\n");
578  return api;
579 }
580 
581 
588 void *
590 {
592  struct Plugin *plugin = api->cls;
593 
594  database_shutdown(plugin);
595  plugin->cfg = NULL;
596  GNUNET_free(api);
597  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Flat plugin is finished\n");
598  return NULL;
599 }
600 
601 /* end of plugin_peerstore_sqlite.c */
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:541
Create file if it doesn&#39;t exist.
void(* GNUNET_PEERSTORE_Processor)(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1339
struct GNUNET_PeerIdentity peer
Peer Identity.
void * libgnunet_plugin_peerstore_flat_done(void *cls)
Exit point from the plugin.
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:729
Delete any previous values for the given key before storing the given value.
size_t value_size
Size of value BLOB.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_TIME_Absolute iter_now
Iterator time.
uint32_t options
Options for addresses.
char * key
TLS key.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
int GNUNET_STRINGS_fancy_time_to_absolute(const char *fancy_time, struct GNUNET_TIME_Absolute *atime)
Convert a given fancy human-readable time to our internal representation.
Definition: strings.c:401
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int(* store_record)(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a record in the peerstore.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static void database_shutdown(struct Plugin *plugin)
Shutdown database connection and associate data structures.
uint64_t abs_value_us
The actual value.
void * cls
Closure to pass to all plugin functions.
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:46
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
IPC messages.
static int iterate_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
char * key
Record key string.
int(* expire_records)(void *cls, struct GNUNET_TIME_Absolute now, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Delete expired records (expiry < now)
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
uint64_t deleted_entries
Deleted entries.
void * value
Record value BLOB.
static char * line
Desired phone line (string to be converted to a hash).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
static int store_and_free_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
static int peerstore_flat_expire_records(void *cls, struct GNUNET_TIME_Absolute now, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Delete expired records (expiry < now)
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
Truncate file if it exists.
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:817
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
static int delete_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
const struct GNUNET_PeerIdentity * iter_peer
Iterator peer.
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
GNUNET_PEERSTORE_StoreOption
Options for storing values in PEERSTORE.
static int fh
Handle to the unique file.
void * libgnunet_plugin_peerstore_flat_init(void *cls)
Entry point for the plugin.
static int expire_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
struct returned by the initialization function of the plugin
A 512-bit hashcode.
static int peerstore_flat_delete_records(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key)
Delete records with the given key.
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1920
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1856
static int peerstore_flat_store_record(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a record in the peerstore.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
void(* GNUNET_PEERSTORE_Continuation)(void *cls, int success)
Continuation called with a status result.
struct GNUNET_CONTAINER_MultiHashMap * hm
HashMap.
void * iter_cls
Iterator cls.
int(* iterate_records)(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor iter, void *iter_cls)
Iterate over the records given an optional peer id and/or key.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:254
char * fn
Filename used for the DB.
Allow multiple values with the same key.
uint64_t exp_changes
Expired entries.
The identity of the host (wraps the signing key of the peer).
unsigned long long size
Size of all values we&#39;re storing.
configuration data
Definition: configuration.c:83
struct GNUNET_TIME_Absolute expiry
Expiry time of entry.
char * sub_system
Responsible sub system string.
Handle for a plugin.
Definition: block.c:37
Single PEERSTORE record.
#define GNUNET_log(kind,...)
static int peerstore_flat_iterate_records(void *cls, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor iter, void *iter_cls)
Iterate over the records given an optional peer id and/or key.
Open the file for both reading and writing.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
static int database_setup(struct Plugin *plugin)
Initialize the database connections and associated data structures (create tables and indices as need...
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
const char * iter_sub_system
Iterator subsystem.
int iter_result_found
Result found bool.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
const char * iter_key
iterator key
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:741
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1262
GNUNET_PEERSTORE_Processor iter
Iterator.
Handle used to access files (and pipes).
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.