GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
gnunet-service-messenger_message_store.c File Reference
#include "gnunet-service-messenger_message_store.h"
#include "gnunet-service-messenger_list_messages.h"
#include "gnunet_common.h"
#include "gnunet_network_lib.h"
#include "gnunet_scheduler_lib.h"
#include "gnunet_util_lib.h"
#include "messenger_api_message.h"
#include <stdint.h>
#include <string.h>
Include dependency graph for gnunet-service-messenger_message_store.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_MESSENGER_MessageEntryStorage
 
struct  GNUNET_MESSENGER_MessageLinkStorage
 
struct  GNUNET_MESSENGER_ClosureMessageSave
 
struct  GNUNET_MESSENGER_CleanupDiscourseMessages
 

Macros

#define load_message_store_attribute_failed(file, attribute, size)
 
#define save_message_store_attribute_failed(file, attribute)
 

Functions

void init_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
 Initializes a message store as fully empty using a specific directory.
 
static enum GNUNET_GenericReturnValue iterate_destroy_entries (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static enum GNUNET_GenericReturnValue iterate_destroy_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static enum GNUNET_GenericReturnValue iterate_destroy_hashs (void *cls, const struct GNUNET_HashCode *key, void *value)
 
void clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
 Clears a message store, wipes its content and deallocates its memory.
 
void move_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
 Moves all storage from a message store from its current directory to a given directory.
 
static int load_message_store_attribute (const struct GNUNET_DISK_FileHandle *file, void *attribute, size_t attribute_len, uint64_t *size)
 
static void load_message_store_entries (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
 
static void load_message_store_links (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
 
static void load_message_store_epochs (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
 
void load_message_store (struct GNUNET_MESSENGER_MessageStore *store)
 Loads messages from its directory into a message store.
 
static enum GNUNET_GenericReturnValue iterate_save_epochs (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static enum GNUNET_GenericReturnValue iterate_save_links (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static enum GNUNET_GenericReturnValue iterate_save_entries (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static enum GNUNET_GenericReturnValue iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
 
void save_message_store (struct GNUNET_MESSENGER_MessageStore *store)
 Saves messages from a message store into its directory.
 
enum GNUNET_GenericReturnValue contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
 Checks if a message matching a given hash is stored in a message store.
 
const struct GNUNET_MESSENGER_Messageget_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
 Returns the message from a message store matching a given hash.
 
const struct GNUNET_MESSENGER_MessageLinkget_store_message_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, enum GNUNET_GenericReturnValue deleted_only)
 Returns the message link from a message store matching a given hash.
 
const struct GNUNET_HashCodeget_store_message_epoch (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
 Returns the epoch hash of a message from a message store matching a given hash.
 
static void add_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Message *message)
 
static void put_store_message_epoch (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, const struct GNUNET_HashCode *epoch)
 
static void task_save_messages (void *cls)
 
enum GNUNET_GenericReturnValue put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, struct GNUNET_MESSENGER_Message *message)
 Stores a message into the message store.
 
enum GNUNET_GenericReturnValue delete_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
 Deletes a message in the message store.
 
static enum GNUNET_GenericReturnValue iterate_flag_for_cleanup_discourse_message (void *cls, const struct GNUNET_HashCode *key, void *value)
 
void cleanup_store_discourse_messages_before (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_ShortHashCode *discourse, const struct GNUNET_TIME_Absolute timestamp)
 Cleans up and deletes all discourse messages existing in the message store memory before a certain timestamp.
 

Macro Definition Documentation

◆ load_message_store_attribute_failed

#define load_message_store_attribute_failed (   file,
  attribute,
  size 
)
Value:
load_message_store_attribute (file, &(attribute), sizeof(attribute), \
&(size))
static int load_message_store_attribute(const struct GNUNET_DISK_FileHandle *file, void *attribute, size_t attribute_len, uint64_t *size)
static unsigned int size
Size of the "table".
Definition peer.c:68

Definition at line 207 of file gnunet-service-messenger_message_store.c.

217{
218 enum GNUNET_DISK_AccessPermissions permission;
219 struct GNUNET_DISK_FileHandle *entries;
221 struct GNUNET_MESSENGER_MessageEntry *entry;
222 uint64_t entry_size, size;
223
226 return;
227
228 entry_size = sizeof(storage.hash) + sizeof(storage.entry.offset) + sizeof(
229 storage.entry.length);
230
231 if (size < entry_size)
232 return;
233
234 permission = (GNUNET_DISK_PERM_USER_READ);
236 permission);
237
238 if (! entries)
239 return;
240
241 memset (&storage, 0, sizeof(storage));
242 entry = NULL;
243
244 while (size >= entry_size)
245 {
246 if ((load_message_store_attribute_failed (entries, storage.hash, size)) ||
247 (load_message_store_attribute_failed (entries, storage.entry.offset,
248 size)) ||
249 (load_message_store_attribute_failed (entries, storage.entry.length,
250 size)))
251 {
252 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading message entry failed!\n");
253 break;
254 }
255
257
258 if (! entry)
259 break;
260
261 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
262
264 store->entries, &(storage.hash))) ||
266 store->entries, &(storage.hash), entry,
268 {
270 "Loading message entry twice: %s\n",
271 GNUNET_h2s (&(storage.hash)));
272 store->rewrite_entries = GNUNET_YES;
273 break;
274 }
275
277 "Loading message entry with hash: %s\n",
278 GNUNET_h2s (&(storage.hash)));
279
280 entry = NULL;
281 }
282
283 if (entry)
284 GNUNET_free (entry);
285
286 GNUNET_DISK_file_close (entries);
287}
288
289
291{
292 struct GNUNET_HashCode hash;
294};
295
296static void
298 const char *filename)
299{
300 enum GNUNET_DISK_AccessPermissions permission;
303 struct GNUNET_MESSENGER_MessageLink *link;
304 uint64_t link_size, size;
305
308 return;
309
310 link_size = sizeof(storage.hash) + sizeof(storage.link.multiple) + sizeof(
311 storage.link.first);
312
313 if (size < link_size)
314 return;
315
316 permission = (GNUNET_DISK_PERM_USER_READ);
317
319 permission);
320
321 if (! links)
322 return;
323
324 memset (&storage, 0, sizeof(storage));
325 link = NULL;
326
327 while (size >= link_size)
328 {
329 if ((load_message_store_attribute_failed (links, storage.hash, size)) ||
331 storage.link.multiple, size)) ||
332 (load_message_store_attribute_failed (links, storage.link.first, size))
333 ||
334 ((GNUNET_YES == storage.link.multiple) &&
335 (load_message_store_attribute_failed (links, storage.link.second, size)
336 )))
337 break;
338
340
341 if (! link)
342 break;
343
344 GNUNET_memcpy (link, &(storage.link), sizeof(*link));
345
347 store->links, &(storage.hash))) ||
349 store->links, &(storage.hash), link,
351 break;
352
353 link = NULL;
354 }
355
356 if (link)
357 GNUNET_free (link);
358
360}
361
362
363static void
365 const char *filename)
366{
367 enum GNUNET_DISK_AccessPermissions permission;
369 struct GNUNET_HashCode storage[2];
370 struct GNUNET_HashCode *epoch;
371 uint64_t epoch_size, size;
372
375 return;
376
377 epoch_size = sizeof(storage[0]) + sizeof(storage[1]);
378
379 if (size < epoch_size)
380 return;
381
382 permission = (GNUNET_DISK_PERM_USER_READ);
383
385 permission);
386
387 if (! epochs)
388 return;
389
390 epoch = NULL;
391
392 while (size >= epoch_size)
393 {
394 if ((load_message_store_attribute_failed (epochs, storage[0], size)) ||
396 break;
397
398 epoch = GNUNET_new (struct GNUNET_HashCode);
399
400 if (! epoch)
401 break;
402
403 GNUNET_memcpy (epoch, &(storage[1]), sizeof(*epoch));
404
406 store->epochs, &(storage[0]))) ||
408 store->epochs, &(storage[0]), epoch,
410 break;
411
412 epoch = NULL;
413 }
414
415 if (epoch)
416 GNUNET_free (epoch);
417
419}
420
421
422void
424{
425 enum GNUNET_DISK_AccessPermissions permission;
426 char *filename;
427
428 GNUNET_assert (store);
429
430 if (! store->directory)
431 return;
432
434
435 if (store->storage_messages)
437
439 "%s%s", store->directory, "messages.store");
440
444 permission);
445 else
446 store->storage_messages = NULL;
447
449
450 if (! store->storage_messages)
451 return;
452
454 "%s%s", store->directory, "entries.store");
455
458
460
462 "%s%s", store->directory, "links.store");
463
466
468 "%s%s", store->directory, "epochs.store");
469
472
474}
475
476
478{
480
482};
483
484
486iterate_save_epochs (void *cls,
487 const struct GNUNET_HashCode *key,
488 void *value)
489{
491 struct GNUNET_HashCode *epoch;
492
493 GNUNET_assert ((cls) && (key) && (value));
494
495 save = cls;
496 epoch = value;
497
498 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
499 (save_message_store_attribute_failed (save->storage, (*epoch))))
500 return GNUNET_NO;
501
502 return GNUNET_YES;
503}
504
505
507iterate_save_links (void *cls,
508 const struct GNUNET_HashCode *key,
509 void *value)
510{
512 struct GNUNET_MESSENGER_MessageLink *link;
513
514 GNUNET_assert ((cls) && (key) && (value));
515
516 save = cls;
517 link = value;
518
519 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
522 return GNUNET_NO;
523
524 if ((GNUNET_YES == link->multiple) &&
526 return GNUNET_NO;
527
528 return GNUNET_YES;
529}
530
531
533iterate_save_entries (void *cls,
534 const struct GNUNET_HashCode *key,
535 void *value)
536{
538 struct GNUNET_MESSENGER_MessageEntry *entry;
539
540 GNUNET_assert ((cls) && (key) && (value));
541
542 save = cls;
543 entry = value;
544
545 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
546 (save_message_store_attribute_failed (save->storage, entry->offset)) ||
548 return GNUNET_NO;
549
550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message entry with hash: %s\n",
551 GNUNET_h2s (key));
552
553 return GNUNET_YES;
554}
555
556
558iterate_save_messages (void *cls,
559 const struct GNUNET_HashCode *key,
560 void *value)
561{
564 struct GNUNET_MESSENGER_Message *message;
565
566 GNUNET_assert ((cls) && (key) && (value));
567
568 save = cls;
569
571 save->store->entries, key))
572 {
574 "Skipping storage of message: %s\n", GNUNET_h2s (key));
575 return GNUNET_YES;
576 }
577
578 message = value;
579
580 GNUNET_memcpy (&(storage.hash), key, sizeof(storage.hash));
581
582 storage.entry.length = get_message_size (message, GNUNET_YES);
583 storage.entry.offset = GNUNET_DISK_file_seek (
584 save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
585
586 if ((GNUNET_SYSERR == storage.entry.offset) ||
587 (save_message_store_attribute_failed (save->storage, storage.hash)) ||
589 storage.entry.offset)) ||
591 storage.entry.length)))
592 {
594 "Storing entry of message failed: %s\n", GNUNET_h2s (key));
595 return GNUNET_NO;
596 }
597
598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message with hash: %s\n",
599 GNUNET_h2s (&(storage.hash)));
600
601 {
602 char *buffer;
603 buffer = GNUNET_malloc (storage.entry.length);
604
605 if (! buffer)
606 return GNUNET_NO;
607
608 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
609
610 GNUNET_DISK_file_write (save->store->storage_messages, buffer,
611 storage.entry.length);
612
613 GNUNET_free (buffer);
614 }
615
616 {
617 struct GNUNET_MESSENGER_MessageEntry *entry;
619
620 if (! entry)
621 return GNUNET_NO;
622
623 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
624
626 save->store->entries, &(storage.hash), entry,
628 {
630 "Message entry might get stored twice: %s\n",
631 GNUNET_h2s (&(storage.hash)));
632 GNUNET_free (entry);
633 return GNUNET_NO;
634 }
635 }
636
637 return GNUNET_YES;
638}
639
640
641void
643{
645 enum GNUNET_DISK_AccessPermissions permission;
646 char *filename;
647
649
650 if (! store->directory)
651 return;
652
654
656 "%s%s", store->directory, "epochs.store");
657
658 save.store = store;
660 | GNUNET_DISK_OPEN_CREATE, permission);
661
663
664 if (! save.storage)
665 {
667 "No access to local storage of message epochs!\n");
668 goto save_links;
669 }
670
671 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
673 goto close_epochs;
674
676 &save);
677
678close_epochs:
680
681save_links:
683 goto save_entries;
684
686 "%s%s", store->directory, "links.store");
687
688 save.store = store;
690 | GNUNET_DISK_OPEN_CREATE, permission);
691
693
694 if (! save.storage)
695 {
697 "No access to local storage of message links!\n");
698 goto save_entries;
699 }
700
701 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
703 goto close_links;
704
706 &save);
708
709close_links:
711
712save_entries:
714 "%s%s", store->directory, "entries.store");
715
716 save.store = store;
718 | GNUNET_DISK_OPEN_CREATE, permission);
719
721
722 if (! save.storage)
723 {
725 "No access to local storage of message entries!\n");
726 return;
727 }
728
730 {
731 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
733 goto close_entries;
734
736 &save);
738 }
739 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
741 goto close_entries;
742
745
747 "%s%s", store->directory, "messages.store");
748
752 permission);
753
755
757 {
760
762 GNUNET_DISK_file_sync (save.storage);
763 }
764
765close_entries:
767 save.storage = NULL;
768}
769
770
773 const struct GNUNET_HashCode *hash)
774{
775 GNUNET_assert ((store) && (hash));
776
778 hash))
779 return GNUNET_YES;
780
782 hash))
783 return GNUNET_YES;
784
786}
787
788
789const struct GNUNET_MESSENGER_Message*
791 const struct GNUNET_HashCode *hash)
792{
793 struct GNUNET_MESSENGER_Message *message;
794 const struct GNUNET_MESSENGER_MessageEntry *entry;
795 enum GNUNET_GenericReturnValue decoding;
796 struct GNUNET_HashCode check;
797 char *buffer;
798
799 GNUNET_assert ((store) && (hash));
800
801 if (GNUNET_is_zero (hash))
802 return NULL;
803
804 message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
805
806 if (message)
807 return message;
808
809 message = GNUNET_CONTAINER_multihashmap_get (store->discourses, hash);
810
811 if (message)
812 return message;
813
814 if (! store->storage_messages)
815 {
817 "Local storage of messages is unavailable: %s\n",
818 GNUNET_h2s (hash));
819 return NULL;
820 }
821
822 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
823
824 if (! entry)
825 {
827 "No entry in storage for message found: %s\n",
828 GNUNET_h2s (hash));
829 return NULL;
830 }
831
832 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
833 entry->offset,
835 {
837 "Offset for message in local storage invalid: %s\n",
838 GNUNET_h2s (hash));
839 return NULL;
840 }
841
842 buffer = GNUNET_malloc (entry->length);
843
844 if (! buffer)
845 {
847 "Allocation for message data buffer failed: %s\n",
848 GNUNET_h2s (hash));
849 return NULL;
850 }
851
852 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) !=
853 entry->length) ||
855 GNUNET_YES)))
856 {
858 "Reading message from local storage failed: %s\n",
859 GNUNET_h2s (hash));
860 goto free_buffer;
861 }
862
864 decoding = decode_message (message, entry->length, buffer,
865 GNUNET_YES, NULL);
866
867 hash_message (message, entry->length, buffer, &check);
868
869 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
870 {
872 "Decoding message failed or checksum mismatched: %s\n",
873 GNUNET_h2s (hash));
874
876 hash, entry))
878 "Corrupted entry could not be removed from store: %s\n",
879 GNUNET_h2s (hash));
880
882 goto free_message;
883 }
884
886 store->messages, hash, message,
888 goto free_buffer;
889
890free_message:
891 destroy_message (message);
892 message = NULL;
893
894free_buffer:
895 GNUNET_free (buffer);
896 return message;
897}
898
899
902 const struct GNUNET_HashCode *hash,
903 enum GNUNET_GenericReturnValue deleted_only)
904{
905 const struct GNUNET_MESSENGER_Message *message;
906
907 if (GNUNET_is_zero (hash))
908 return NULL;
909
910 if (GNUNET_YES == deleted_only)
911 goto get_link;
912
913 message = get_store_message (store, hash);
914
915 if (message)
916 {
917 static struct GNUNET_MESSENGER_MessageLink link;
918
919 GNUNET_memcpy (&(link.first), &(message->header.previous),
920 sizeof(link.first));
921
924
925 if (GNUNET_YES == link.multiple)
926 GNUNET_memcpy (&(link.second), &(message->body.merge.previous),
927 sizeof(link.second));
928 else
929 GNUNET_memcpy (&(link.second), &(message->header.previous),
930 sizeof(link.second));
931
932 return &link;
933 }
934
935get_link:
936 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
937}
938
939
940const struct GNUNET_HashCode*
942 const struct GNUNET_HashCode *hash)
943{
944 struct GNUNET_HashCode *epoch;
945
946 GNUNET_assert ((store) && (hash));
947
948 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
949
950 if (! epoch)
951 return hash;
952
953 return epoch;
954}
955
956
957static void
959 const struct GNUNET_HashCode *hash,
960 const struct GNUNET_MESSENGER_Message *message)
961{
962 struct GNUNET_MESSENGER_MessageLink *link;
963
964 GNUNET_assert ((store) && (hash) && (message));
965
966 if (GNUNET_is_zero (hash))
967 return;
968
970
971 GNUNET_memcpy (&(link->first), &(message->header.previous),
972 sizeof(link->first));
973
976
977 if (GNUNET_YES == link->multiple)
978 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
979 sizeof(link->second));
980 else
981 GNUNET_memcpy (&(link->second), &(message->header.previous),
982 sizeof(link->second));
983
985 store->links, hash, link,
987 GNUNET_free (link);
988 else
989 store->write_links = GNUNET_YES;
990}
991
992
993static void
995 const struct GNUNET_HashCode *hash,
996 const struct GNUNET_HashCode *epoch)
997{
998 struct GNUNET_HashCode *copy;
999
1000 GNUNET_assert ((store) && (hash) && (epoch));
1001
1002 if (GNUNET_is_zero (hash))
1003 return;
1004
1006 store->epochs, hash))
1007 return;
1008
1009 copy = GNUNET_new (struct GNUNET_HashCode);
1010
1011 if (! copy)
1012 return;
1013
1014 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1015
1017 store->epochs, hash, copy,
1019 GNUNET_free (copy);
1020}
1021
1022
1023static void
1024task_save_messages (void *cls)
1025{
1026 struct GNUNET_MESSENGER_MessageStore *store;
1027
1028 GNUNET_assert (cls);
1029
1030 store = cls;
1031 store->writing_task = NULL;
1032
1033 save_message_store (store);
1034}
1035
1036
1039 const struct GNUNET_HashCode *hash,
1040 struct GNUNET_MESSENGER_Message *message)
1041{
1042 struct GNUNET_HashCode *epoch;
1045
1046 GNUNET_assert ((store) && (hash) && (message));
1047
1048 if (GNUNET_is_zero (hash))
1049 return GNUNET_SYSERR;
1050
1051 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
1052
1053 if (epoch)
1054 goto reverse_epoch;
1055
1056 epoch = GNUNET_new (struct GNUNET_HashCode);
1057
1058 if (! epoch)
1059 goto skip_epoch;
1060
1061 switch (message->header.kind)
1062 {
1065 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1066 break;
1068 {
1069 const struct GNUNET_HashCode *epoch0;
1070 const struct GNUNET_HashCode *epoch1;
1071
1072 epoch0 = &(message->body.merge.epochs[0]);
1073 epoch1 = &(message->body.merge.epochs[1]);
1074
1075 if (0 == GNUNET_CRYPTO_hash_cmp (epoch0, epoch1))
1076 GNUNET_memcpy (epoch, epoch0, sizeof (struct GNUNET_HashCode));
1077 else
1078 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1079
1080 break;
1081 }
1082 default:
1084 epoch,
1085 get_store_message_epoch (store, &(message->header.previous)),
1086 sizeof (struct GNUNET_HashCode));
1087 break;
1088 }
1089
1091 store->epochs, hash, epoch,
1093 {
1094 GNUNET_free (epoch);
1095 goto skip_epoch;
1096 }
1097
1098reverse_epoch:
1099 switch (message->header.kind)
1100 {
1103 store,
1104 &(message->header.previous),
1105 &(message->body.join.epoch));
1106 break;
1109 store,
1110 &(message->header.previous),
1111 &(message->body.leave.epoch));
1112 break;
1115 store,
1116 &(message->header.previous),
1117 &(message->body.merge.epochs[0]));
1119 store,
1120 &(message->body.merge.previous),
1121 &(message->body.merge.epochs[1]));
1122 break;
1123 default:
1125 store,
1126 &(message->header.previous),
1127 epoch);
1128 break;
1129 }
1130
1131skip_epoch:
1132 map = store->messages;
1133
1134 if (get_message_discourse (message))
1135 map = store->discourses;
1136
1138 {
1140 "Message has already been stored! (%s)\n",
1141 GNUNET_h2s (hash));
1142 return GNUNET_SYSERR;
1143 }
1144
1146 map, hash, message,
1148
1149 if ((GNUNET_OK != result) || (map == store->discourses))
1150 return result;
1151
1152 if (! store->writing_task)
1156 store);
1157
1158 return result;
1159}
1160
1161
1164 const struct GNUNET_HashCode *hash)
1165{
1166 const struct GNUNET_MESSENGER_MessageEntry *entry;
1167 const struct GNUNET_MESSENGER_Message *message;
1168
1169 GNUNET_assert ((store) && (hash));
1170
1171 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
1172
1173 if (! entry)
1174 goto clear_memory;
1175
1176 message = get_store_message (store, hash);
1177
1178 if (message)
1179 {
1180 if (GNUNET_YES == is_epoch_message (message))
1181 {
1183 "Deletion of message is not allowed! (%s)\n",
1184 GNUNET_h2s (hash));
1185 return GNUNET_SYSERR;
1186 }
1187
1188 add_link (store, hash, message);
1189 }
1190
1191 if (! store->storage_messages)
1192 goto clear_entry;
1193
1194 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
1195 entry->offset,
1197 return GNUNET_SYSERR;
1198
1199 {
1201 char *clear_buffer;
1202
1203 clear_buffer = GNUNET_malloc (entry->length);
1204
1205 if (! clear_buffer)
1206 return GNUNET_SYSERR;
1207
1208 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
1209
1210 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages,
1211 clear_buffer, entry->length))
1212 ||
1215 else
1216 result = GNUNET_OK;
1217
1218 GNUNET_free (clear_buffer);
1219
1220 if (GNUNET_OK != result)
1221 return result;
1222 }
1223
1224clear_entry:
1226 entry))
1227 store->rewrite_entries = GNUNET_YES;
1228
1229clear_memory:
1231 return GNUNET_OK;
1232}
1233
1234
1236{
1240};
1241
1242static enum GNUNET_GenericReturnValue
1244 const struct GNUNET_HashCode *key,
1245 void *value)
1246{
1248 struct GNUNET_MESSENGER_Message *message;
1249 const struct GNUNET_ShortHashCode *discourse;
1250
1251 GNUNET_assert ((cls) && (key) && (value));
1252
1253 cleanup = cls;
1254 message = value;
1255
1256 discourse = get_message_discourse (message);
1257
1258 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1259 return GNUNET_YES;
1260
1261 {
1264
1265 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1266 return GNUNET_YES;
1267 }
1268
1270 destroy_message (message);
1271
1272 return GNUNET_YES;
1273}
1274
1275
1276void
1278 store,
1279 const struct GNUNET_ShortHashCode *
1280 discourse,
1281 const struct GNUNET_TIME_Absolute
1282 timestamp)
1283{
1286
1287 GNUNET_assert ((store) && (discourse));
1288
1290
1291 cleanup.list = &list;
1292 cleanup.timestamp = timestamp;
1293
1294 GNUNET_memcpy (&(cleanup.discourse), discourse,
1295 sizeof (struct GNUNET_ShortHashCode));
1296
1299 &cleanup);
1300
1301 {
1302 struct GNUNET_MESSENGER_ListMessage *element;
1303 for (element = list.head; element; element = element->next)
1305 store->discourses,
1306 &(element->hash));
1307 }
1308
1310}
static int list
Set if we should print a list of currently running services.
Definition gnunet-arm.c:68
static uint64_t timestamp(void)
Get current timestamp.
struct GNUNET_HashCode key
The key used in the DHT.
static char * filename
static char * value
Value of the record to add/remove.
static int result
Global testing status.
static unsigned int epochs
-e option.
void clear_list_messages(struct GNUNET_MESSENGER_ListMessages *messages)
Clears the list of message hashes.
void init_list_messages(struct GNUNET_MESSENGER_ListMessages *messages)
Initializes list of message hashes as empty list.
void add_to_list_messages(struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash)
Adds a specific hash from a message to the end of the list.
static enum GNUNET_GenericReturnValue iterate_save_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
void save_message_store(struct GNUNET_MESSENGER_MessageStore *store)
Saves messages from a message store into its directory.
enum GNUNET_GenericReturnValue contains_store_message(const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Checks if a message matching a given hash is stored in a message store.
static void task_save_messages(void *cls)
const struct GNUNET_HashCode * get_store_message_epoch(const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Returns the epoch hash of a message from a message store matching a given hash.
static enum GNUNET_GenericReturnValue iterate_flag_for_cleanup_discourse_message(void *cls, const struct GNUNET_HashCode *key, void *value)
enum GNUNET_GenericReturnValue put_store_message(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, struct GNUNET_MESSENGER_Message *message)
Stores a message into the message store.
static void load_message_store_entries(struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
enum GNUNET_GenericReturnValue delete_store_message(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Deletes a message in the message store.
static enum GNUNET_GenericReturnValue iterate_save_links(void *cls, const struct GNUNET_HashCode *key, void *value)
void cleanup_store_discourse_messages_before(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_ShortHashCode *discourse, const struct GNUNET_TIME_Absolute timestamp)
Cleans up and deletes all discourse messages existing in the message store memory before a certain ti...
#define save_message_store_attribute_failed(file, attribute)
static void load_message_store_links(struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
void load_message_store(struct GNUNET_MESSENGER_MessageStore *store)
Loads messages from its directory into a message store.
const struct GNUNET_MESSENGER_MessageLink * get_store_message_link(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, enum GNUNET_GenericReturnValue deleted_only)
Returns the message link from a message store matching a given hash.
#define load_message_store_attribute_failed(file, attribute, size)
static enum GNUNET_GenericReturnValue iterate_save_messages(void *cls, const struct GNUNET_HashCode *key, void *value)
static enum GNUNET_GenericReturnValue iterate_save_epochs(void *cls, const struct GNUNET_HashCode *key, void *value)
static void load_message_store_epochs(struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
const struct GNUNET_MESSENGER_Message * get_store_message(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Returns the message from a message store matching a given hash.
static void add_link(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Message *message)
static void put_store_message_epoch(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, const struct GNUNET_HashCode *epoch)
static void cleanup()
Cleanup task.
static void save()
Write persistent statistics to disk.
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
void GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
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:1258
enum GNUNET_GenericReturnValue 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:533
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:710
off_t GNUNET_DISK_file_seek(const struct GNUNET_DISK_FileHandle *h, off_t offset, enum GNUNET_DISK_Seek whence)
Move the read/write pointer in a file.
Definition disk.c:219
enum GNUNET_GenericReturnValue 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:235
GNUNET_DISK_AccessPermissions
File access permissions, UNIX-style.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition disk.c:1451
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1332
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:673
@ GNUNET_DISK_OPEN_READ
Open the file for reading.
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_OPEN_READWRITE
Open the file for both reading and writing.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_DISK_SEEK_SET
Seek an absolute position (from the start of the file).
@ GNUNET_DISK_SEEK_END
Seek an absolute position from the end of the file.
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
int GNUNET_CONTAINER_multihashmap_remove_all(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Remove all entries for the given key from the map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue 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.
enum GNUNET_GenericReturnValue 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_SCHEDULER_PRIORITY_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
@ GNUNET_MESSENGER_KIND_LEAVE
The leave kind.
@ GNUNET_MESSENGER_KIND_UNKNOWN
The unknown kind.
@ GNUNET_MESSENGER_KIND_JOIN
The join kind.
@ GNUNET_MESSENGER_KIND_MERGE
The merge kind.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition scheduler.c:1231
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:741
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
void encode_message(const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, enum GNUNET_GenericReturnValue include_header)
Encodes a given message into a buffer of a maximal length in bytes.
const struct GNUNET_ShortHashCode * get_message_discourse(const struct GNUNET_MESSENGER_Message *message)
Returns the discourse hash of a message depending on its kind.
enum GNUNET_GenericReturnValue is_epoch_message(const struct GNUNET_MESSENGER_Message *message)
Returns whether a certain kind of message from storage contains some specific details that might be r...
void hash_message(const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer, struct GNUNET_HashCode *hash)
Calculates a hash of a given buffer with a length in bytes from a message.
struct GNUNET_MESSENGER_Message * create_message(enum GNUNET_MESSENGER_MessageKind kind)
Creates and allocates a new message with a specific kind.
void destroy_message(struct GNUNET_MESSENGER_Message *message)
Destroys a message and frees its memory fully.
uint16_t get_message_kind_size(enum GNUNET_MESSENGER_MessageKind kind, enum GNUNET_GenericReturnValue include_header)
Returns the minimal size in bytes to encode a message of a specific kind.
uint16_t get_message_size(const struct GNUNET_MESSENGER_Message *message, enum GNUNET_GenericReturnValue include_header)
Returns the exact size in bytes to encode a given message.
enum GNUNET_GenericReturnValue decode_message(struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer, enum GNUNET_GenericReturnValue include_header, uint16_t *padding)
Decodes a message from a given buffer of a maximal length in bytes.
static struct GNUNET_CONTAINER_MultiPeerMap * map
Peermap of PeerIdentities to "struct PeerEntry" (for fast lookup).
Definition peer.c:63
Internal representation of the hash map.
Handle used to access files (and pipes).
A 512-bit hashcode.
struct GNUNET_MESSENGER_ListMessage * next
struct GNUNET_MESSENGER_MessageMerge merge
struct GNUNET_MESSENGER_MessageLeave leave
struct GNUNET_MESSENGER_MessageJoin join
struct GNUNET_HashCode previous
The hash of the previous message from the senders perspective.
enum GNUNET_MESSENGER_MessageKind kind
The kind of the message.
struct GNUNET_TIME_AbsoluteNBO timestamp
The timestamp of the message.
struct GNUNET_HashCode epoch
The previous epoch the message was sent from.
struct GNUNET_HashCode epoch
The previous epoch the message was sent from.
struct GNUNET_HashCode previous
The hash of a second previous message.
struct GNUNET_HashCode epochs[2]
The previous epochs the message was sent from.
struct GNUNET_CONTAINER_MultiHashMap * links
struct GNUNET_CONTAINER_MultiHashMap * messages
struct GNUNET_CONTAINER_MultiHashMap * entries
struct GNUNET_CONTAINER_MultiHashMap * epochs
struct GNUNET_CONTAINER_MultiHashMap * discourses
struct GNUNET_MESSENGER_MessageHeader header
Header.
struct GNUNET_MESSENGER_MessageBody body
Body.
A 256-bit hashcode.
Time for absolute times used by GNUnet, in microseconds.

◆ save_message_store_attribute_failed

#define save_message_store_attribute_failed (   file,
  attribute 
)
Value:
sizeof(attribute) != GNUNET_DISK_file_write (file, &(attribute), \
sizeof(attribute))

Definition at line 211 of file gnunet-service-messenger_message_store.c.

Function Documentation

◆ init_message_store()

void init_message_store ( struct GNUNET_MESSENGER_MessageStore store,
const char *  directory 
)

Initializes a message store as fully empty using a specific directory.

Parameters
[out]storeMessage store
[in]directoryPath to a directory

Definition at line 40 of file gnunet-service-messenger_message_store.c.

42{
43 GNUNET_assert (store);
44
45 store->directory = directory? GNUNET_strdup (directory) : NULL;
46
47 store->storage_messages = NULL;
48 store->writing_task = NULL;
49
55
57 store->write_links = GNUNET_NO;
58}
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.

References GNUNET_MESSENGER_MessageStore::directory, GNUNET_MESSENGER_MessageStore::discourses, GNUNET_MESSENGER_MessageStore::entries, GNUNET_MESSENGER_MessageStore::epochs, GNUNET_assert, GNUNET_CONTAINER_multihashmap_create(), GNUNET_NO, GNUNET_strdup, GNUNET_MESSENGER_MessageStore::links, GNUNET_MESSENGER_MessageStore::messages, GNUNET_MESSENGER_MessageStore::rewrite_entries, GNUNET_MESSENGER_MessageStore::storage_messages, GNUNET_MESSENGER_MessageStore::write_links, and GNUNET_MESSENGER_MessageStore::writing_task.

Referenced by create_srv_room().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate_destroy_entries()

static enum GNUNET_GenericReturnValue iterate_destroy_entries ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 62 of file gnunet-service-messenger_message_store.c.

65{
67
69
70 entry = value;
71
72 GNUNET_free (entry);
73 return GNUNET_YES;
74}

References GNUNET_assert, GNUNET_free, GNUNET_YES, and value.

Referenced by clear_message_store().

Here is the caller graph for this function:

◆ iterate_destroy_messages()

static enum GNUNET_GenericReturnValue iterate_destroy_messages ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 78 of file gnunet-service-messenger_message_store.c.

81{
82 struct GNUNET_MESSENGER_Message *message;
83
85
86 message = value;
87
88 destroy_message (message);
89 return GNUNET_YES;
90}

References destroy_message(), GNUNET_assert, GNUNET_YES, and value.

Referenced by clear_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate_destroy_hashs()

static enum GNUNET_GenericReturnValue iterate_destroy_hashs ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 94 of file gnunet-service-messenger_message_store.c.

97{
98 struct GNUNET_HashCode *hash;
99
101
102 hash = value;
103
104 GNUNET_free (hash);
105 return GNUNET_YES;
106}

References GNUNET_assert, GNUNET_free, GNUNET_YES, and value.

Referenced by clear_message_store().

Here is the caller graph for this function:

◆ clear_message_store()

void clear_message_store ( struct GNUNET_MESSENGER_MessageStore store)

Clears a message store, wipes its content and deallocates its memory.

Parameters
[in,out]storeMessage store

Definition at line 110 of file gnunet-service-messenger_message_store.c.

111{
112 GNUNET_assert (store);
113
114 if (store->storage_messages)
115 {
117 store->storage_messages = NULL;
118 }
119
120 if (store->writing_task)
121 {
123 store->writing_task = NULL;
124 }
125
131 NULL);
135 NULL);
136
142
143 if (store->directory)
144 {
145 GNUNET_free (store->directory);
146 store->directory = NULL;
147 }
148}
static enum GNUNET_GenericReturnValue iterate_destroy_hashs(void *cls, const struct GNUNET_HashCode *key, void *value)
static enum GNUNET_GenericReturnValue iterate_destroy_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
static enum GNUNET_GenericReturnValue iterate_destroy_messages(void *cls, const struct GNUNET_HashCode *key, void *value)
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980

References GNUNET_MESSENGER_MessageStore::directory, GNUNET_MESSENGER_MessageStore::discourses, GNUNET_MESSENGER_MessageStore::entries, GNUNET_MESSENGER_MessageStore::epochs, GNUNET_assert, GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_DISK_file_close(), GNUNET_free, GNUNET_SCHEDULER_cancel(), iterate_destroy_entries(), iterate_destroy_hashs(), iterate_destroy_messages(), GNUNET_MESSENGER_MessageStore::links, GNUNET_MESSENGER_MessageStore::messages, GNUNET_MESSENGER_MessageStore::storage_messages, and GNUNET_MESSENGER_MessageStore::writing_task.

Referenced by destroy_srv_room().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ move_message_store()

void move_message_store ( struct GNUNET_MESSENGER_MessageStore store,
const char *  directory 
)

Moves all storage from a message store from its current directory to a given directory.

Parameters
[in,out]storeMessage store
[in]directoryPath to a directory

Definition at line 152 of file gnunet-service-messenger_message_store.c.

154{
155 GNUNET_assert ((store) && (directory));
156
157 if (store->directory)
158 {
159 if (0 == strcmp (store->directory, directory))
160 return;
161
163 {
165 "Moving message store failed because directory exists already! (%s)\n",
166 directory);
167 return;
168 }
169
170 if (0 != rename (store->directory, directory))
171 {
173 "Moving message store failed! (%s -> %s)\n",
174 store->directory, directory);
175 return;
176 }
177
178 GNUNET_free (store->directory);
179 }
180
181 store->directory = GNUNET_strdup (directory);
182}
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition disk.c:454

References GNUNET_MESSENGER_MessageStore::directory, GNUNET_assert, GNUNET_DISK_directory_test(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_strdup, and GNUNET_YES.

Referenced by load_srv_room(), and save_srv_room().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_message_store_attribute()

static int load_message_store_attribute ( const struct GNUNET_DISK_FileHandle file,
void *  attribute,
size_t  attribute_len,
uint64_t *  size 
)
static

Definition at line 192 of file gnunet-service-messenger_message_store.c.

196{
197 ssize_t result;
198
199 result = GNUNET_DISK_file_read (file, attribute, attribute_len);
200 if (GNUNET_SYSERR != result)
201 *size -= result;
202
203 return attribute_len != result;
204}

References GNUNET_DISK_file_read(), GNUNET_SYSERR, result, and size.

Here is the call graph for this function:

◆ load_message_store_entries()

static void load_message_store_entries ( struct GNUNET_MESSENGER_MessageStore store,
const char *  filename 
)
static

Definition at line 216 of file gnunet-service-messenger_message_store.c.

218{
219 enum GNUNET_DISK_AccessPermissions permission;
220 struct GNUNET_DISK_FileHandle *entries;
222 struct GNUNET_MESSENGER_MessageEntry *entry;
223 uint64_t entry_size, size;
224
227 return;
228
229 entry_size = sizeof(storage.hash) + sizeof(storage.entry.offset) + sizeof(
230 storage.entry.length);
231
232 if (size < entry_size)
233 return;
234
235 permission = (GNUNET_DISK_PERM_USER_READ);
237 permission);
238
239 if (! entries)
240 return;
241
242 memset (&storage, 0, sizeof(storage));
243 entry = NULL;
244
245 while (size >= entry_size)
246 {
247 if ((load_message_store_attribute_failed (entries, storage.hash, size)) ||
248 (load_message_store_attribute_failed (entries, storage.entry.offset,
249 size)) ||
250 (load_message_store_attribute_failed (entries, storage.entry.length,
251 size)))
252 {
253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading message entry failed!\n");
254 break;
255 }
256
258
259 if (! entry)
260 break;
261
262 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
263
265 store->entries, &(storage.hash))) ||
267 store->entries, &(storage.hash), entry,
269 {
271 "Loading message entry twice: %s\n",
272 GNUNET_h2s (&(storage.hash)));
274 break;
275 }
276
278 "Loading message entry with hash: %s\n",
279 GNUNET_h2s (&(storage.hash)));
280
281 entry = NULL;
282 }
283
284 if (entry)
285 GNUNET_free (entry);
286
287 GNUNET_DISK_file_close (entries);
288}

References GNUNET_MESSENGER_MessageStore::entries, GNUNET_MESSENGER_MessageEntryStorage::entry, filename, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_size(), GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_memcpy, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_YES, GNUNET_MESSENGER_MessageEntryStorage::hash, GNUNET_MESSENGER_MessageEntry::length, load_message_store_attribute_failed, GNUNET_MESSENGER_MessageEntry::offset, GNUNET_MESSENGER_MessageStore::rewrite_entries, and size.

Referenced by load_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_message_store_links()

static void load_message_store_links ( struct GNUNET_MESSENGER_MessageStore store,
const char *  filename 
)
static

Definition at line 298 of file gnunet-service-messenger_message_store.c.

300{
301 enum GNUNET_DISK_AccessPermissions permission;
304 struct GNUNET_MESSENGER_MessageLink *link;
305 uint64_t link_size, size;
306
309 return;
310
311 link_size = sizeof(storage.hash) + sizeof(storage.link.multiple) + sizeof(
312 storage.link.first);
313
314 if (size < link_size)
315 return;
316
317 permission = (GNUNET_DISK_PERM_USER_READ);
318
320 permission);
321
322 if (! links)
323 return;
324
325 memset (&storage, 0, sizeof(storage));
326 link = NULL;
327
328 while (size >= link_size)
329 {
330 if ((load_message_store_attribute_failed (links, storage.hash, size)) ||
332 storage.link.multiple, size)) ||
333 (load_message_store_attribute_failed (links, storage.link.first, size))
334 ||
335 ((GNUNET_YES == storage.link.multiple) &&
336 (load_message_store_attribute_failed (links, storage.link.second, size)
337 )))
338 break;
339
341
342 if (! link)
343 break;
344
345 GNUNET_memcpy (link, &(storage.link), sizeof(*link));
346
348 store->links, &(storage.hash))) ||
350 store->links, &(storage.hash), link,
352 break;
353
354 link = NULL;
355 }
356
357 if (link)
358 GNUNET_free (link);
359
361}

References filename, GNUNET_MESSENGER_MessageLink::first, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_size(), GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_free, GNUNET_memcpy, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_YES, GNUNET_MESSENGER_MessageLinkStorage::hash, GNUNET_MESSENGER_MessageLinkStorage::link, GNUNET_MESSENGER_MessageStore::links, links, load_message_store_attribute_failed, GNUNET_MESSENGER_MessageLink::multiple, GNUNET_MESSENGER_MessageLink::second, and size.

Referenced by load_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_message_store_epochs()

static void load_message_store_epochs ( struct GNUNET_MESSENGER_MessageStore store,
const char *  filename 
)
static

Definition at line 365 of file gnunet-service-messenger_message_store.c.

367{
368 enum GNUNET_DISK_AccessPermissions permission;
370 struct GNUNET_HashCode storage[2];
371 struct GNUNET_HashCode *epoch;
372 uint64_t epoch_size, size;
373
376 return;
377
378 epoch_size = sizeof(storage[0]) + sizeof(storage[1]);
379
380 if (size < epoch_size)
381 return;
382
383 permission = (GNUNET_DISK_PERM_USER_READ);
384
386 permission);
387
388 if (! epochs)
389 return;
390
391 epoch = NULL;
392
393 while (size >= epoch_size)
394 {
395 if ((load_message_store_attribute_failed (epochs, storage[0], size)) ||
397 break;
398
399 epoch = GNUNET_new (struct GNUNET_HashCode);
400
401 if (! epoch)
402 break;
403
404 GNUNET_memcpy (epoch, &(storage[1]), sizeof(*epoch));
405
407 store->epochs, &(storage[0]))) ||
409 store->epochs, &(storage[0]), epoch,
411 break;
412
413 epoch = NULL;
414 }
415
416 if (epoch)
417 GNUNET_free (epoch);
418
420}

References epochs, GNUNET_MESSENGER_MessageStore::epochs, filename, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_size(), GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_free, GNUNET_memcpy, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_YES, load_message_store_attribute_failed, and size.

Referenced by load_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_message_store()

void load_message_store ( struct GNUNET_MESSENGER_MessageStore store)

Loads messages from its directory into a message store.

Parameters
[out]storeMessage store

Definition at line 424 of file gnunet-service-messenger_message_store.c.

425{
426 enum GNUNET_DISK_AccessPermissions permission;
427 char *filename;
428
429 GNUNET_assert (store);
430
431 if (! store->directory)
432 return;
433
435
436 if (store->storage_messages)
438
440 "%s%s", store->directory, "messages.store");
441
445 permission);
446 else
447 store->storage_messages = NULL;
448
450
451 if (! store->storage_messages)
452 return;
453
455 "%s%s", store->directory, "entries.store");
456
459
461
463 "%s%s", store->directory, "links.store");
464
467
469 "%s%s", store->directory, "epochs.store");
470
473
475}

References GNUNET_MESSENGER_MessageStore::directory, filename, GNUNET_asprintf(), GNUNET_assert, GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_test(), GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_free, GNUNET_YES, load_message_store_entries(), load_message_store_epochs(), load_message_store_links(), and GNUNET_MESSENGER_MessageStore::storage_messages.

Referenced by load_srv_room().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate_save_epochs()

static enum GNUNET_GenericReturnValue iterate_save_epochs ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 487 of file gnunet-service-messenger_message_store.c.

490{
492 struct GNUNET_HashCode *epoch;
493
494 GNUNET_assert ((cls) && (key) && (value));
495
496 save = cls;
497 epoch = value;
498
499 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
500 (save_message_store_attribute_failed (save->storage, (*epoch))))
501 return GNUNET_NO;
502
503 return GNUNET_YES;
504}

References GNUNET_assert, GNUNET_NO, GNUNET_YES, key, save(), save_message_store_attribute_failed, and value.

Referenced by save_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate_save_links()

static enum GNUNET_GenericReturnValue iterate_save_links ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 508 of file gnunet-service-messenger_message_store.c.

511{
513 struct GNUNET_MESSENGER_MessageLink *link;
514
515 GNUNET_assert ((cls) && (key) && (value));
516
517 save = cls;
518 link = value;
519
520 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
523 return GNUNET_NO;
524
525 if ((GNUNET_YES == link->multiple) &&
527 return GNUNET_NO;
528
529 return GNUNET_YES;
530}

References GNUNET_MESSENGER_MessageLink::first, GNUNET_assert, GNUNET_NO, GNUNET_YES, key, GNUNET_MESSENGER_MessageLink::multiple, save(), save_message_store_attribute_failed, GNUNET_MESSENGER_MessageLink::second, and value.

Referenced by save_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate_save_entries()

static enum GNUNET_GenericReturnValue iterate_save_entries ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 534 of file gnunet-service-messenger_message_store.c.

537{
539 struct GNUNET_MESSENGER_MessageEntry *entry;
540
541 GNUNET_assert ((cls) && (key) && (value));
542
543 save = cls;
544 entry = value;
545
546 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
547 (save_message_store_attribute_failed (save->storage, entry->offset)) ||
549 return GNUNET_NO;
550
551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message entry with hash: %s\n",
552 GNUNET_h2s (key));
553
554 return GNUNET_YES;
555}

References GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_YES, key, GNUNET_MESSENGER_MessageEntry::length, GNUNET_MESSENGER_MessageEntry::offset, save(), save_message_store_attribute_failed, and value.

Referenced by save_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate_save_messages()

static enum GNUNET_GenericReturnValue iterate_save_messages ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 559 of file gnunet-service-messenger_message_store.c.

562{
565 struct GNUNET_MESSENGER_Message *message;
566
567 GNUNET_assert ((cls) && (key) && (value));
568
569 save = cls;
570
572 save->store->entries, key))
573 {
575 "Skipping storage of message: %s\n", GNUNET_h2s (key));
576 return GNUNET_YES;
577 }
578
579 message = value;
580
581 GNUNET_memcpy (&(storage.hash), key, sizeof(storage.hash));
582
583 storage.entry.length = get_message_size (message, GNUNET_YES);
584 storage.entry.offset = GNUNET_DISK_file_seek (
585 save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
586
587 if ((GNUNET_SYSERR == storage.entry.offset) ||
588 (save_message_store_attribute_failed (save->storage, storage.hash)) ||
590 storage.entry.offset)) ||
592 storage.entry.length)))
593 {
595 "Storing entry of message failed: %s\n", GNUNET_h2s (key));
596 return GNUNET_NO;
597 }
598
599 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message with hash: %s\n",
600 GNUNET_h2s (&(storage.hash)));
601
602 {
603 char *buffer;
604 buffer = GNUNET_malloc (storage.entry.length);
605
606 if (! buffer)
607 return GNUNET_NO;
608
609 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
610
611 GNUNET_DISK_file_write (save->store->storage_messages, buffer,
612 storage.entry.length);
613
614 GNUNET_free (buffer);
615 }
616
617 {
618 struct GNUNET_MESSENGER_MessageEntry *entry;
620
621 if (! entry)
622 return GNUNET_NO;
623
624 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
625
627 save->store->entries, &(storage.hash), entry,
629 {
631 "Message entry might get stored twice: %s\n",
632 GNUNET_h2s (&(storage.hash)));
633 GNUNET_free (entry);
634 return GNUNET_NO;
635 }
636 }
637
638 return GNUNET_YES;
639}

References encode_message(), GNUNET_MESSENGER_MessageEntryStorage::entry, get_message_size(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_DISK_file_seek(), GNUNET_DISK_file_write(), GNUNET_DISK_SEEK_END, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, GNUNET_MESSENGER_MessageEntryStorage::hash, key, GNUNET_MESSENGER_MessageEntry::length, GNUNET_MESSENGER_MessageEntry::offset, save(), save_message_store_attribute_failed, and value.

Referenced by save_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ save_message_store()

void save_message_store ( struct GNUNET_MESSENGER_MessageStore store)

Saves messages from a message store into its directory.

Parameters
[in]storeMessage store

Definition at line 643 of file gnunet-service-messenger_message_store.c.

644{
646 enum GNUNET_DISK_AccessPermissions permission;
647 char *filename;
648
650
651 if (! store->directory)
652 return;
653
655
657 "%s%s", store->directory, "epochs.store");
658
659 save.store = store;
661 | GNUNET_DISK_OPEN_CREATE, permission);
662
664
665 if (! save.storage)
666 {
668 "No access to local storage of message epochs!\n");
669 goto save_links;
670 }
671
672 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
674 goto close_epochs;
675
677 &save);
678
679close_epochs:
681
682save_links:
684 goto save_entries;
685
687 "%s%s", store->directory, "links.store");
688
689 save.store = store;
691 | GNUNET_DISK_OPEN_CREATE, permission);
692
694
695 if (! save.storage)
696 {
698 "No access to local storage of message links!\n");
699 goto save_entries;
700 }
701
702 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
704 goto close_links;
705
707 &save);
709
710close_links:
712
713save_entries:
715 "%s%s", store->directory, "entries.store");
716
717 save.store = store;
719 | GNUNET_DISK_OPEN_CREATE, permission);
720
722
723 if (! save.storage)
724 {
726 "No access to local storage of message entries!\n");
727 return;
728 }
729
731 {
732 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
734 goto close_entries;
735
737 &save);
739 }
740 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
742 goto close_entries;
743
746
748 "%s%s", store->directory, "messages.store");
749
753 permission);
754
756
758 {
761
763 GNUNET_DISK_file_sync (save.storage);
764 }
765
766close_entries:
768 save.storage = NULL;
769}

References GNUNET_MESSENGER_MessageStore::directory, GNUNET_MESSENGER_MessageStore::entries, GNUNET_MESSENGER_MessageStore::epochs, filename, GNUNET_asprintf(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_seek(), GNUNET_DISK_file_sync(), GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_DISK_SEEK_END, GNUNET_DISK_SEEK_SET, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_SYSERR, GNUNET_YES, iterate_save_entries(), iterate_save_epochs(), iterate_save_links(), iterate_save_messages(), GNUNET_MESSENGER_MessageStore::links, GNUNET_MESSENGER_MessageStore::messages, GNUNET_MESSENGER_MessageStore::rewrite_entries, save(), GNUNET_MESSENGER_MessageStore::storage_messages, GNUNET_MESSENGER_ClosureMessageSave::store, and GNUNET_MESSENGER_MessageStore::write_links.

Referenced by save_srv_room(), and task_save_messages().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ contains_store_message()

enum GNUNET_GenericReturnValue contains_store_message ( const struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_HashCode hash 
)

Checks if a message matching a given hash is stored in a message store.

The function returns GNUNET_YES if a match is found, GNUNET_NO otherwise.

The message has not to be loaded from disk into memory for this check!

Parameters
[in]storeMessage store
[in]hashHash of message
Returns
GNUNET_YES on match, otherwise GNUNET_NO

Definition at line 773 of file gnunet-service-messenger_message_store.c.

775{
776 GNUNET_assert ((store) && (hash));
777
779 hash))
780 return GNUNET_YES;
781
783 hash))
784 return GNUNET_YES;
785
787}

References GNUNET_MESSENGER_MessageStore::discourses, GNUNET_MESSENGER_MessageStore::entries, GNUNET_assert, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_YES, GNUNET_MESSENGER_MessageStore::messages, and GNUNET_MESSENGER_ClosureMessageSave::store.

Referenced by update_room_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_store_message()

const struct GNUNET_MESSENGER_Message * get_store_message ( struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_HashCode hash 
)

Returns the message from a message store matching a given hash.

If no matching message is found, NULL gets returned.

This function requires the message to be loaded into memory!

See also
contains_store_message()
Parameters
[in,out]storeMessage store
[in]hashHash of message
Returns
Message or NULL

Definition at line 791 of file gnunet-service-messenger_message_store.c.

793{
794 struct GNUNET_MESSENGER_Message *message;
795 const struct GNUNET_MESSENGER_MessageEntry *entry;
796 enum GNUNET_GenericReturnValue decoding;
797 struct GNUNET_HashCode check;
798 char *buffer;
799
800 GNUNET_assert ((store) && (hash));
801
802 if (GNUNET_is_zero (hash))
803 return NULL;
804
805 message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
806
807 if (message)
808 return message;
809
810 message = GNUNET_CONTAINER_multihashmap_get (store->discourses, hash);
811
812 if (message)
813 return message;
814
815 if (! store->storage_messages)
816 {
818 "Local storage of messages is unavailable: %s\n",
819 GNUNET_h2s (hash));
820 return NULL;
821 }
822
823 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
824
825 if (! entry)
826 {
828 "No entry in storage for message found: %s\n",
829 GNUNET_h2s (hash));
830 return NULL;
831 }
832
833 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
834 entry->offset,
836 {
838 "Offset for message in local storage invalid: %s\n",
839 GNUNET_h2s (hash));
840 return NULL;
841 }
842
843 buffer = GNUNET_malloc (entry->length);
844
845 if (! buffer)
846 {
848 "Allocation for message data buffer failed: %s\n",
849 GNUNET_h2s (hash));
850 return NULL;
851 }
852
853 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) !=
854 entry->length) ||
856 GNUNET_YES)))
857 {
859 "Reading message from local storage failed: %s\n",
860 GNUNET_h2s (hash));
861 goto free_buffer;
862 }
863
865 decoding = decode_message (message, entry->length, buffer,
866 GNUNET_YES, NULL);
867
868 hash_message (message, entry->length, buffer, &check);
869
870 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
871 {
873 "Decoding message failed or checksum mismatched: %s\n",
874 GNUNET_h2s (hash));
875
877 hash, entry))
879 "Corrupted entry could not be removed from store: %s\n",
880 GNUNET_h2s (hash));
881
883 goto free_message;
884 }
885
887 store->messages, hash, message,
889 goto free_buffer;
890
891free_message:
892 destroy_message (message);
893 message = NULL;
894
895free_buffer:
896 GNUNET_free (buffer);
897 return message;
898}

References create_message(), decode_message(), destroy_message(), GNUNET_MESSENGER_MessageStore::discourses, GNUNET_MESSENGER_MessageStore::entries, get_message_kind_size(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_CRYPTO_hash_cmp(), GNUNET_DISK_file_read(), GNUNET_DISK_file_seek(), GNUNET_DISK_SEEK_SET, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_h2s(), GNUNET_is_zero, GNUNET_log, GNUNET_malloc, GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_OK, GNUNET_YES, hash_message(), GNUNET_MESSENGER_MessageEntry::length, GNUNET_MESSENGER_MessageStore::messages, GNUNET_MESSENGER_MessageEntry::offset, GNUNET_MESSENGER_MessageStore::rewrite_entries, and GNUNET_MESSENGER_MessageStore::storage_messages.

Referenced by check_srv_room_peer_status(), delete_srv_room_message(), delete_store_message(), forward_about_members(), get_store_message_link(), handle_room_messages(), iterate_epoch_session_members(), notify_about_members(), recv_message_info(), request_room_message_step(), traverse_epoch_message(), update_tunnel_last_message(), and verify_tunnel_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_store_message_link()

const struct GNUNET_MESSENGER_MessageLink * get_store_message_link ( struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_HashCode hash,
enum GNUNET_GenericReturnValue  deleted_only 
)

Returns the message link from a message store matching a given hash.

If the flag is set to GNUNET_YES, only links from deleted messages will be returned or NULL.

Otherwise message links will also returned for messages found in the store under the given hash. The link which will be returned copies link information from the message for temporary usage.

Parameters
[in,out]storeMessage store
[in]hashHash of message
[in]deleted_onlyFlag
Returns
Message link or NULL

Definition at line 902 of file gnunet-service-messenger_message_store.c.

905{
906 const struct GNUNET_MESSENGER_Message *message;
907
908 if (GNUNET_is_zero (hash))
909 return NULL;
910
911 if (GNUNET_YES == deleted_only)
912 goto get_link;
913
914 message = get_store_message (store, hash);
915
916 if (message)
917 {
918 static struct GNUNET_MESSENGER_MessageLink link;
919
920 GNUNET_memcpy (&(link.first), &(message->header.previous),
921 sizeof(link.first));
922
923 link.multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind?
925
926 if (GNUNET_YES == link.multiple)
927 GNUNET_memcpy (&(link.second), &(message->body.merge.previous),
928 sizeof(link.second));
929 else
930 GNUNET_memcpy (&(link.second), &(message->header.previous),
931 sizeof(link.second));
932
933 return &link;
934 }
935
936get_link:
937 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
938}

References GNUNET_MESSENGER_Message::body, GNUNET_MESSENGER_MessageLink::first, get_store_message(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_is_zero, GNUNET_memcpy, GNUNET_MESSENGER_KIND_MERGE, GNUNET_NO, GNUNET_YES, GNUNET_MESSENGER_Message::header, GNUNET_MESSENGER_MessageHeader::kind, GNUNET_MESSENGER_MessageStore::links, GNUNET_MESSENGER_MessageBody::merge, GNUNET_MESSENGER_MessageLink::multiple, GNUNET_MESSENGER_MessageHeader::previous, GNUNET_MESSENGER_MessageMerge::previous, and GNUNET_MESSENGER_MessageLink::second.

Referenced by check_member_session_completion(), and request_room_message_step().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_store_message_epoch()

const struct GNUNET_HashCode * get_store_message_epoch ( const struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_HashCode hash 
)

Returns the epoch hash of a message from a message store matching a given hash.

If no matching message is found, NULL gets returned.

Parameters
[in]storeMessage store
[in]hashHash of message
Returns
Epoch hash or NULL

Definition at line 942 of file gnunet-service-messenger_message_store.c.

944{
945 struct GNUNET_HashCode *epoch;
946
947 GNUNET_assert ((store) && (hash));
948
949 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
950
951 if (! epoch)
952 return hash;
953
954 return epoch;
955}

References GNUNET_MESSENGER_MessageStore::epochs, GNUNET_assert, and GNUNET_CONTAINER_multihashmap_get().

Referenced by callback_found_message(), handle_room_messages(), notify_about_members(), pack_srv_room_message(), put_store_message(), and sync_srv_handle_messages().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_link()

static void add_link ( struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_HashCode hash,
const struct GNUNET_MESSENGER_Message message 
)
static

Definition at line 959 of file gnunet-service-messenger_message_store.c.

962{
963 struct GNUNET_MESSENGER_MessageLink *link;
964
965 GNUNET_assert ((store) && (hash) && (message));
966
967 if (GNUNET_is_zero (hash))
968 return;
969
971
972 GNUNET_memcpy (&(link->first), &(message->header.previous),
973 sizeof(link->first));
974
977
978 if (GNUNET_YES == link->multiple)
979 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
980 sizeof(link->second));
981 else
982 GNUNET_memcpy (&(link->second), &(message->header.previous),
983 sizeof(link->second));
984
986 store->links, hash, link,
988 GNUNET_free (link);
989 else
990 store->write_links = GNUNET_YES;
991}

References GNUNET_MESSENGER_Message::body, GNUNET_MESSENGER_MessageLink::first, GNUNET_assert, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_free, GNUNET_is_zero, GNUNET_memcpy, GNUNET_MESSENGER_KIND_MERGE, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_YES, GNUNET_MESSENGER_Message::header, GNUNET_MESSENGER_MessageHeader::kind, GNUNET_MESSENGER_MessageStore::links, GNUNET_MESSENGER_MessageBody::merge, GNUNET_MESSENGER_MessageLink::multiple, GNUNET_MESSENGER_MessageHeader::previous, GNUNET_MESSENGER_MessageMerge::previous, GNUNET_MESSENGER_MessageLink::second, and GNUNET_MESSENGER_MessageStore::write_links.

Referenced by delete_store_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_store_message_epoch()

static void put_store_message_epoch ( struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_HashCode hash,
const struct GNUNET_HashCode epoch 
)
static

Definition at line 995 of file gnunet-service-messenger_message_store.c.

998{
999 struct GNUNET_HashCode *copy;
1000
1001 GNUNET_assert ((store) && (hash) && (epoch));
1002
1003 if (GNUNET_is_zero (hash))
1004 return;
1005
1007 store->epochs, hash))
1008 return;
1009
1010 copy = GNUNET_new (struct GNUNET_HashCode);
1011
1012 if (! copy)
1013 return;
1014
1015 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1016
1018 store->epochs, hash, copy,
1020 GNUNET_free (copy);
1021}

References GNUNET_MESSENGER_MessageStore::epochs, GNUNET_assert, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_free, GNUNET_is_zero, GNUNET_memcpy, GNUNET_new, GNUNET_OK, and GNUNET_YES.

Referenced by put_store_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_save_messages()

static void task_save_messages ( void *  cls)
static

Definition at line 1025 of file gnunet-service-messenger_message_store.c.

1026{
1027 struct GNUNET_MESSENGER_MessageStore *store;
1028
1029 GNUNET_assert (cls);
1030
1031 store = cls;
1032 store->writing_task = NULL;
1033
1034 save_message_store (store);
1035}

References GNUNET_assert, save_message_store(), and GNUNET_MESSENGER_MessageStore::writing_task.

Referenced by put_store_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_store_message()

enum GNUNET_GenericReturnValue put_store_message ( struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_HashCode hash,
struct GNUNET_MESSENGER_Message message 
)

Stores a message into the message store.

The result indicates if the operation was successful.

Parameters
[in,out]storeMessage store
[in]hashHash of message
[in,out]messageMessage
Returns
GNUNET_OK on success, otherwise GNUNET_NO

Definition at line 1039 of file gnunet-service-messenger_message_store.c.

1042{
1043 struct GNUNET_HashCode *epoch;
1046
1047 GNUNET_assert ((store) && (hash) && (message));
1048
1049 if (GNUNET_is_zero (hash))
1050 return GNUNET_SYSERR;
1051
1052 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
1053
1054 if (epoch)
1055 goto reverse_epoch;
1056
1057 epoch = GNUNET_new (struct GNUNET_HashCode);
1058
1059 if (! epoch)
1060 goto skip_epoch;
1061
1062 switch (message->header.kind)
1063 {
1066 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1067 break;
1069 {
1070 const struct GNUNET_HashCode *epoch0;
1071 const struct GNUNET_HashCode *epoch1;
1072
1073 epoch0 = &(message->body.merge.epochs[0]);
1074 epoch1 = &(message->body.merge.epochs[1]);
1075
1076 if (0 == GNUNET_CRYPTO_hash_cmp (epoch0, epoch1))
1077 GNUNET_memcpy (epoch, epoch0, sizeof (struct GNUNET_HashCode));
1078 else
1079 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1080
1081 break;
1082 }
1083 default:
1085 epoch,
1086 get_store_message_epoch (store, &(message->header.previous)),
1087 sizeof (struct GNUNET_HashCode));
1088 break;
1089 }
1090
1092 store->epochs, hash, epoch,
1094 {
1095 GNUNET_free (epoch);
1096 goto skip_epoch;
1097 }
1098
1099reverse_epoch:
1100 switch (message->header.kind)
1101 {
1104 store,
1105 &(message->header.previous),
1106 &(message->body.join.epoch));
1107 break;
1110 store,
1111 &(message->header.previous),
1112 &(message->body.leave.epoch));
1113 break;
1116 store,
1117 &(message->header.previous),
1118 &(message->body.merge.epochs[0]));
1120 store,
1121 &(message->body.merge.previous),
1122 &(message->body.merge.epochs[1]));
1123 break;
1124 default:
1126 store,
1127 &(message->header.previous),
1128 epoch);
1129 break;
1130 }
1131
1132skip_epoch:
1133 map = store->messages;
1134
1135 if (get_message_discourse (message))
1136 map = store->discourses;
1137
1139 {
1141 "Message has already been stored! (%s)\n",
1142 GNUNET_h2s (hash));
1143 return GNUNET_SYSERR;
1144 }
1145
1147 map, hash, message,
1149
1150 if ((GNUNET_OK != result) || (map == store->discourses))
1151 return result;
1152
1153 if (! store->writing_task)
1157 store);
1158
1159 return result;
1160}

References GNUNET_MESSENGER_Message::body, GNUNET_MESSENGER_MessageStore::discourses, GNUNET_MESSENGER_MessageJoin::epoch, GNUNET_MESSENGER_MessageLeave::epoch, GNUNET_MESSENGER_MessageMerge::epochs, GNUNET_MESSENGER_MessageStore::epochs, get_message_discourse(), get_store_message_epoch(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_CRYPTO_hash_cmp(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_h2s(), GNUNET_is_zero, GNUNET_log, GNUNET_memcpy, GNUNET_MESSENGER_KIND_JOIN, GNUNET_MESSENGER_KIND_LEAVE, GNUNET_MESSENGER_KIND_MERGE, GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_with_priority(), GNUNET_SCHEDULER_PRIORITY_BACKGROUND, GNUNET_SYSERR, GNUNET_YES, GNUNET_MESSENGER_Message::header, GNUNET_MESSENGER_MessageBody::join, GNUNET_MESSENGER_MessageHeader::kind, GNUNET_MESSENGER_MessageBody::leave, map, GNUNET_MESSENGER_MessageBody::merge, GNUNET_MESSENGER_MessageStore::messages, GNUNET_MESSENGER_MessageHeader::previous, GNUNET_MESSENGER_MessageMerge::previous, put_store_message_epoch(), result, task_save_messages(), and GNUNET_MESSENGER_MessageStore::writing_task.

Referenced by update_room_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_store_message()

enum GNUNET_GenericReturnValue delete_store_message ( struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_HashCode hash 
)

Deletes a message in the message store.

It will be removed from disk space and memory. The result indicates if the operation was successful.

Parameters
[in,out]storeMessage store
[in]hashHash of message
Returns
GNUNET_OK on success, GNUNET_SYSERR on failure

Definition at line 1164 of file gnunet-service-messenger_message_store.c.

1166{
1167 const struct GNUNET_MESSENGER_MessageEntry *entry;
1168 const struct GNUNET_MESSENGER_Message *message;
1169
1170 GNUNET_assert ((store) && (hash));
1171
1172 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
1173
1174 if (! entry)
1175 goto clear_memory;
1176
1177 message = get_store_message (store, hash);
1178
1179 if (message)
1180 {
1181 if (GNUNET_YES == is_epoch_message (message))
1182 {
1184 "Deletion of message is not allowed! (%s)\n",
1185 GNUNET_h2s (hash));
1186 return GNUNET_SYSERR;
1187 }
1188
1189 add_link (store, hash, message);
1190 }
1191
1192 if (! store->storage_messages)
1193 goto clear_entry;
1194
1195 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
1196 entry->offset,
1198 return GNUNET_SYSERR;
1199
1200 {
1202 char *clear_buffer;
1203
1204 clear_buffer = GNUNET_malloc (entry->length);
1205
1206 if (! clear_buffer)
1207 return GNUNET_SYSERR;
1208
1209 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
1210
1211 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages,
1212 clear_buffer, entry->length))
1213 ||
1216 else
1217 result = GNUNET_OK;
1218
1219 GNUNET_free (clear_buffer);
1220
1221 if (GNUNET_OK != result)
1222 return result;
1223 }
1224
1225clear_entry:
1227 entry))
1228 store->rewrite_entries = GNUNET_YES;
1229
1230clear_memory:
1232 return GNUNET_OK;
1233}

References add_link(), GNUNET_MESSENGER_MessageStore::entries, get_store_message(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_multihashmap_remove_all(), GNUNET_CRYPTO_zero_keys(), GNUNET_DISK_file_seek(), GNUNET_DISK_file_sync(), GNUNET_DISK_file_write(), GNUNET_DISK_SEEK_SET, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_malloc, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, is_epoch_message(), GNUNET_MESSENGER_MessageEntry::length, GNUNET_MESSENGER_MessageStore::messages, GNUNET_MESSENGER_MessageEntry::offset, result, GNUNET_MESSENGER_MessageStore::rewrite_entries, and GNUNET_MESSENGER_MessageStore::storage_messages.

Referenced by callback_operation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate_flag_for_cleanup_discourse_message()

static enum GNUNET_GenericReturnValue iterate_flag_for_cleanup_discourse_message ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 1244 of file gnunet-service-messenger_message_store.c.

1247{
1249 struct GNUNET_MESSENGER_Message *message;
1250 const struct GNUNET_ShortHashCode *discourse;
1251
1252 GNUNET_assert ((cls) && (key) && (value));
1253
1254 cleanup = cls;
1255 message = value;
1256
1257 discourse = get_message_discourse (message);
1258
1259 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1260 return GNUNET_YES;
1261
1262 {
1265
1266 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1267 return GNUNET_YES;
1268 }
1269
1271 destroy_message (message);
1272
1273 return GNUNET_YES;
1274}

References add_to_list_messages(), cleanup(), destroy_message(), get_message_discourse(), GNUNET_assert, GNUNET_memcmp, GNUNET_TIME_absolute_cmp, GNUNET_TIME_absolute_ntoh(), GNUNET_YES, GNUNET_MESSENGER_Message::header, key, GNUNET_MESSENGER_MessageHeader::timestamp, timestamp(), and value.

Referenced by cleanup_store_discourse_messages_before().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup_store_discourse_messages_before()

void cleanup_store_discourse_messages_before ( struct GNUNET_MESSENGER_MessageStore store,
const struct GNUNET_ShortHashCode discourse,
const struct GNUNET_TIME_Absolute  timestamp 
)

Cleans up and deletes all discourse messages existing in the message store memory before a certain timestamp.

Parameters
[in,out]storeMessage store
[in]discourseHash of discourse
[in]timestampTimestamp

Definition at line 1278 of file gnunet-service-messenger_message_store.c.

1284{
1287
1288 GNUNET_assert ((store) && (discourse));
1289
1291
1292 cleanup.list = &list;
1293 cleanup.timestamp = timestamp;
1294
1295 GNUNET_memcpy (&(cleanup.discourse), discourse,
1296 sizeof (struct GNUNET_ShortHashCode));
1297
1300 &cleanup);
1301
1302 {
1303 struct GNUNET_MESSENGER_ListMessage *element;
1304 for (element = list.head; element; element = element->next)
1306 store->discourses,
1307 &(element->hash));
1308 }
1309
1311}

References cleanup(), clear_list_messages(), GNUNET_MESSENGER_CleanupDiscourseMessages::discourse, GNUNET_MESSENGER_MessageStore::discourses, GNUNET_assert, GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_remove_all(), GNUNET_memcpy, GNUNET_MESSENGER_ListMessage::hash, init_list_messages(), iterate_flag_for_cleanup_discourse_message(), list, GNUNET_MESSENGER_ListMessage::next, and timestamp().

Referenced by cleanup_srv_room_discourse_messages().

Here is the call graph for this function:
Here is the caller graph for this function: