GNUnet 0.28.0-dev.3-20-gf1136b0b8
 
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 213 of file gnunet-service-messenger_message_store.c.

223{
224 enum GNUNET_DISK_AccessPermissions permission;
225 struct GNUNET_DISK_FileHandle *entries;
227 struct GNUNET_MESSENGER_MessageEntry *entry;
228 uint64_t entry_size, size;
229
232 return;
233
234 entry_size = sizeof(storage.hash) + sizeof(storage.entry.offset) + sizeof(
235 storage.entry.length);
236
237 if (size < entry_size)
238 return;
239
240 permission = (GNUNET_DISK_PERM_USER_READ);
242 permission);
243
244 if (! entries)
245 return;
246
247 memset (&storage, 0, sizeof(storage));
248 entry = NULL;
249
250 while (size >= entry_size)
251 {
252 if ((load_message_store_attribute_failed (entries, storage.hash, size)) ||
253 (load_message_store_attribute_failed (entries, storage.entry.offset,
254 size)) ||
255 (load_message_store_attribute_failed (entries, storage.entry.length,
256 size)))
257 {
258 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading message entry failed!\n");
259 break;
260 }
261
263
264 if (! entry)
265 break;
266
267 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
268
270 store->entries, &(storage.hash))) ||
272 store->entries, &(storage.hash), entry,
274 {
276 "Loading message entry twice: %s\n",
277 GNUNET_h2s (&(storage.hash)));
278 store->rewrite_entries = GNUNET_YES;
279 break;
280 }
281
283 "Loading message entry with hash: %s\n",
284 GNUNET_h2s (&(storage.hash)));
285
286 entry = NULL;
287 }
288
289 if (entry)
290 GNUNET_free (entry);
291
292 GNUNET_DISK_file_close (entries);
293}
294
295
297{
298 struct GNUNET_HashCode hash;
300};
301
302static void
304 const char *filename)
305{
306 enum GNUNET_DISK_AccessPermissions permission;
309 struct GNUNET_MESSENGER_MessageLink *link;
310 uint64_t link_size, size;
311
314 return;
315
316 link_size = sizeof(storage.hash) + sizeof(storage.link.multiple) + sizeof(
317 storage.link.first);
318
319 if (size < link_size)
320 return;
321
322 permission = (GNUNET_DISK_PERM_USER_READ);
323
325 permission);
326
327 if (! links)
328 return;
329
330 memset (&storage, 0, sizeof(storage));
331 link = NULL;
332
333 while (size >= link_size)
334 {
335 if ((load_message_store_attribute_failed (links, storage.hash, size)) ||
337 storage.link.multiple, size)) ||
338 (load_message_store_attribute_failed (links, storage.link.first, size))
339 ||
340 ((GNUNET_YES == storage.link.multiple) &&
341 (load_message_store_attribute_failed (links, storage.link.second, size)
342 )))
343 break;
344
346
347 if (! link)
348 break;
349
350 GNUNET_memcpy (link, &(storage.link), sizeof(*link));
351
353 store->links, &(storage.hash))) ||
355 store->links, &(storage.hash), link,
357 break;
358
359 link = NULL;
360 }
361
362 if (link)
363 GNUNET_free (link);
364
366}
367
368
369static void
371 const char *filename)
372{
373 enum GNUNET_DISK_AccessPermissions permission;
375 struct GNUNET_HashCode storage[2];
376 struct GNUNET_HashCode *epoch;
377 uint64_t epoch_size, size;
378
381 return;
382
383 epoch_size = sizeof(storage[0]) + sizeof(storage[1]);
384
385 if (size < epoch_size)
386 return;
387
388 permission = (GNUNET_DISK_PERM_USER_READ);
389
391 permission);
392
393 if (! epochs)
394 return;
395
396 epoch = NULL;
397
398 while (size >= epoch_size)
399 {
400 if ((load_message_store_attribute_failed (epochs, storage[0], size)) ||
402 break;
403
404 epoch = GNUNET_new (struct GNUNET_HashCode);
405
406 if (! epoch)
407 break;
408
409 GNUNET_memcpy (epoch, &(storage[1]), sizeof(*epoch));
410
412 store->epochs, &(storage[0]))) ||
414 store->epochs, &(storage[0]), epoch,
416 break;
417
418 epoch = NULL;
419 }
420
421 if (epoch)
422 GNUNET_free (epoch);
423
425}
426
427
428void
430{
431 enum GNUNET_DISK_AccessPermissions permission;
432 char *filename;
433
434 GNUNET_assert (store);
435
436 if (! store->directory)
437 return;
438
440
441 if (store->storage_messages)
443
445 "%s%s", store->directory, "messages.store");
446
450 permission);
451 else
452 store->storage_messages = NULL;
453
455
456 if (! store->storage_messages)
457 return;
458
460 "%s%s", store->directory, "entries.store");
461
464
467 "%s%s", store->directory, "links.store");
468
471
474 "%s%s", store->directory, "epochs.store");
475
478
480}
481
482
484{
486
488};
489
490
492iterate_save_epochs (void *cls,
493 const struct GNUNET_HashCode *key,
494 void *value)
495{
497 struct GNUNET_HashCode *epoch;
498
499 GNUNET_assert ((cls) && (key) && (value));
500
501 save = cls;
502 epoch = value;
503
504 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
505 (save_message_store_attribute_failed (save->storage, (*epoch))))
506 return GNUNET_NO;
507
508 return GNUNET_YES;
509}
510
511
513iterate_save_links (void *cls,
514 const struct GNUNET_HashCode *key,
515 void *value)
516{
518 struct GNUNET_MESSENGER_MessageLink *link;
519
520 GNUNET_assert ((cls) && (key) && (value));
521
522 save = cls;
523 link = value;
524
525 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
528 return GNUNET_NO;
529
530 if ((GNUNET_YES == link->multiple) &&
532 return GNUNET_NO;
533
534 return GNUNET_YES;
535}
536
537
539iterate_save_entries (void *cls,
540 const struct GNUNET_HashCode *key,
541 void *value)
542{
544 struct GNUNET_MESSENGER_MessageEntry *entry;
545
546 GNUNET_assert ((cls) && (key) && (value));
547
548 save = cls;
549 entry = value;
550
551 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
552 (save_message_store_attribute_failed (save->storage, entry->offset)) ||
554 return GNUNET_NO;
555
556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message entry with hash: %s\n",
557 GNUNET_h2s (key));
558
559 return GNUNET_YES;
560}
561
562
564iterate_save_messages (void *cls,
565 const struct GNUNET_HashCode *key,
566 void *value)
567{
570 struct GNUNET_MESSENGER_Message *message;
571
572 GNUNET_assert ((cls) && (key) && (value));
573
574 save = cls;
575
577 save->store->entries, key))
578 {
580 "Skipping storage of message: %s\n", GNUNET_h2s (key));
581 return GNUNET_YES;
582 }
583
584 message = value;
585
586 GNUNET_memcpy (&(storage.hash), key, sizeof(storage.hash));
587
588 storage.entry.length = get_message_size (message, GNUNET_YES);
589 storage.entry.offset = GNUNET_DISK_file_seek (
590 save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
591
592 if ((GNUNET_SYSERR == storage.entry.offset) ||
593 (save_message_store_attribute_failed (save->storage, storage.hash)) ||
595 storage.entry.offset)) ||
597 storage.entry.length)))
598 {
600 "Storing entry of message failed: %s\n", GNUNET_h2s (key));
601 return GNUNET_NO;
602 }
603
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message with hash: %s\n",
605 GNUNET_h2s (&(storage.hash)));
606
607 {
608 char *buffer;
609 buffer = GNUNET_malloc (storage.entry.length);
610
611 if (! buffer)
612 return GNUNET_NO;
613
614 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
615
616 GNUNET_DISK_file_write (save->store->storage_messages, buffer,
617 storage.entry.length);
618
619 GNUNET_free (buffer);
620 }
621
622 {
623 struct GNUNET_MESSENGER_MessageEntry *entry;
625
626 if (! entry)
627 return GNUNET_NO;
628
629 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
630
632 save->store->entries, &(storage.hash), entry,
634 {
636 "Message entry might get stored twice: %s\n",
637 GNUNET_h2s (&(storage.hash)));
638 GNUNET_free (entry);
639 return GNUNET_NO;
640 }
641 }
642
643 return GNUNET_YES;
644}
645
646
647void
649{
651 enum GNUNET_DISK_AccessPermissions permission;
652 char *filename;
653
655
656 if (! store->directory)
657 return;
658
660
662 "%s%s", store->directory, "epochs.store");
663
664 save.store = store;
666 | GNUNET_DISK_OPEN_CREATE, permission);
667
669
670 if (! save.storage)
671 {
673 "No access to local storage of message epochs!\n");
674 goto save_links;
675 }
676
677 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
679 goto close_epochs;
680
682 &save);
683
684close_epochs:
686
687save_links:
689 goto save_entries;
690
692 "%s%s", store->directory, "links.store");
693
694 save.store = store;
696 | GNUNET_DISK_OPEN_CREATE, permission);
697
699
700 if (! save.storage)
701 {
703 "No access to local storage of message links!\n");
704 goto save_entries;
705 }
706
707 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
709 goto close_links;
710
712 &save);
714
715close_links:
717
718save_entries:
720 "%s%s", store->directory, "entries.store");
721
722 save.store = store;
724 | GNUNET_DISK_OPEN_CREATE, permission);
725
727
728 if (! save.storage)
729 {
731 "No access to local storage of message entries!\n");
732 return;
733 }
734
736 {
737 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
739 goto close_entries;
740
742 &save);
744 }
745 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
747 goto close_entries;
748
751
753 "%s%s", store->directory, "messages.store");
754
758 permission);
759
761
763 {
766
768 GNUNET_DISK_file_sync (save.storage);
769 }
770
771close_entries:
773 save.storage = NULL;
774}
775
776
779 const struct GNUNET_HashCode *hash)
780{
781 GNUNET_assert ((store) && (hash));
782
784 hash))
785 return GNUNET_YES;
786
788 hash))
789 return GNUNET_YES;
790
792}
793
794
795const struct GNUNET_MESSENGER_Message*
797 const struct GNUNET_HashCode *hash)
798{
799 struct GNUNET_MESSENGER_Message *message;
800 const struct GNUNET_MESSENGER_MessageEntry *entry;
801 enum GNUNET_GenericReturnValue decoding;
802 struct GNUNET_HashCode check;
803 char *buffer;
804
805 GNUNET_assert ((store) && (hash));
806
807 if (GNUNET_is_zero (hash))
808 return NULL;
809
810 message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
811
812 if (message)
813 return message;
814
815 message = GNUNET_CONTAINER_multihashmap_get (store->discourses, hash);
816
817 if (message)
818 return message;
819
820 if (! store->storage_messages)
821 {
823 "Local storage of messages is unavailable: %s\n",
824 GNUNET_h2s (hash));
825 return NULL;
826 }
827
828 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
829
830 if (! entry)
831 {
833 "No entry in storage for message found: %s\n",
834 GNUNET_h2s (hash));
835 return NULL;
836 }
837
838 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
839 entry->offset,
841 {
843 "Offset for message in local storage invalid: %s\n",
844 GNUNET_h2s (hash));
845 return NULL;
846 }
847
848 buffer = GNUNET_malloc (entry->length);
849
850 if (! buffer)
851 {
853 "Allocation for message data buffer failed: %s\n",
854 GNUNET_h2s (hash));
855 return NULL;
856 }
857
858 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) !=
859 entry->length) ||
861 GNUNET_YES)))
862 {
864 "Reading message from local storage failed: %s\n",
865 GNUNET_h2s (hash));
866 goto free_buffer;
867 }
868
870 decoding = decode_message (message, entry->length, buffer,
871 GNUNET_YES, NULL);
872
873 hash_message (message, entry->length, buffer, &check);
874
875 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
876 {
878 "Decoding message failed or checksum mismatched: %s\n",
879 GNUNET_h2s (hash));
880
882 hash, entry))
884 "Corrupted entry could not be removed from store: %s\n",
885 GNUNET_h2s (hash));
886
888 goto free_message;
889 }
890
892 store->messages, hash, message,
894 goto free_buffer;
895
896free_message:
897 destroy_message (message);
898 message = NULL;
899
900free_buffer:
901 GNUNET_free (buffer);
902 return message;
903}
904
905
908 const struct GNUNET_HashCode *hash,
909 enum GNUNET_GenericReturnValue deleted_only)
910{
911 const struct GNUNET_MESSENGER_Message *message;
912
913 if (GNUNET_is_zero (hash))
914 return NULL;
915
916 if (GNUNET_YES == deleted_only)
917 goto get_link;
918
919 message = get_store_message (store, hash);
920
921 if (message)
922 {
923 static struct GNUNET_MESSENGER_MessageLink link;
924
925 GNUNET_memcpy (&(link.first), &(message->header.previous),
926 sizeof(link.first));
927
930
931 if (GNUNET_YES == link.multiple)
932 GNUNET_memcpy (&(link.second), &(message->body.merge.previous),
933 sizeof(link.second));
934 else
935 GNUNET_memcpy (&(link.second), &(message->header.previous),
936 sizeof(link.second));
937
938 return &link;
939 }
940
941get_link:
942 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
943}
944
945
946const struct GNUNET_HashCode*
948 const struct GNUNET_HashCode *hash)
949{
950 struct GNUNET_HashCode *epoch;
951
952 GNUNET_assert ((store) && (hash));
953
954 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
955
956 if (! epoch)
957 return hash;
958
959 return epoch;
960}
961
962
963static void
965 const struct GNUNET_HashCode *hash,
966 const struct GNUNET_MESSENGER_Message *message)
967{
968 struct GNUNET_MESSENGER_MessageLink *link;
969
970 GNUNET_assert ((store) && (hash) && (message));
971
972 if (GNUNET_is_zero (hash))
973 return;
974
976
977 GNUNET_memcpy (&(link->first), &(message->header.previous),
978 sizeof(link->first));
979
982
983 if (GNUNET_YES == link->multiple)
984 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
985 sizeof(link->second));
986 else
987 GNUNET_memcpy (&(link->second), &(message->header.previous),
988 sizeof(link->second));
989
991 store->links, hash, link,
993 GNUNET_free (link);
994 else
995 store->write_links = GNUNET_YES;
996}
997
998
999static void
1001 const struct GNUNET_HashCode *hash,
1002 const struct GNUNET_HashCode *epoch)
1003{
1004 struct GNUNET_HashCode *copy;
1005
1006 GNUNET_assert ((store) && (hash) && (epoch));
1007
1008 if (GNUNET_is_zero (hash))
1009 return;
1010
1012 store->epochs, hash))
1013 return;
1014
1015 copy = GNUNET_new (struct GNUNET_HashCode);
1016
1017 if (! copy)
1018 return;
1019
1020 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1021
1023 store->epochs, hash, copy,
1025 GNUNET_free (copy);
1026}
1027
1028
1029static void
1030task_save_messages (void *cls)
1031{
1032 struct GNUNET_MESSENGER_MessageStore *store;
1033
1034 GNUNET_assert (cls);
1035
1036 store = cls;
1037 store->writing_task = NULL;
1038
1039 save_message_store (store);
1040}
1041
1042
1045 const struct GNUNET_HashCode *hash,
1046 struct GNUNET_MESSENGER_Message *message)
1047{
1048 struct GNUNET_HashCode *epoch;
1051
1052 GNUNET_assert ((store) && (hash) && (message));
1053
1054 if (GNUNET_is_zero (hash))
1055 return GNUNET_SYSERR;
1056
1057 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
1058
1059 if (epoch)
1060 goto reverse_epoch;
1061
1062 epoch = GNUNET_new (struct GNUNET_HashCode);
1063
1064 if (! epoch)
1065 goto skip_epoch;
1066
1067 switch (message->header.kind)
1068 {
1071 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1072 break;
1074 {
1075 const struct GNUNET_HashCode *epoch0;
1076 const struct GNUNET_HashCode *epoch1;
1077
1078 epoch0 = &(message->body.merge.epochs[0]);
1079 epoch1 = &(message->body.merge.epochs[1]);
1080
1081 if (0 == GNUNET_CRYPTO_hash_cmp (epoch0, epoch1))
1082 GNUNET_memcpy (epoch, epoch0, sizeof (struct GNUNET_HashCode));
1083 else
1084 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1085
1086 break;
1087 }
1088 default:
1090 epoch,
1091 get_store_message_epoch (store, &(message->header.previous)),
1092 sizeof (struct GNUNET_HashCode));
1093 break;
1094 }
1095
1097 store->epochs, hash, epoch,
1099 {
1100 GNUNET_free (epoch);
1101 goto skip_epoch;
1102 }
1103
1104reverse_epoch:
1105 switch (message->header.kind)
1106 {
1109 store,
1110 &(message->header.previous),
1111 &(message->body.join.epoch));
1112 break;
1115 store,
1116 &(message->header.previous),
1117 &(message->body.leave.epoch));
1118 break;
1121 store,
1122 &(message->header.previous),
1123 &(message->body.merge.epochs[0]));
1125 store,
1126 &(message->body.merge.previous),
1127 &(message->body.merge.epochs[1]));
1128 break;
1129 default:
1131 store,
1132 &(message->header.previous),
1133 epoch);
1134 break;
1135 }
1136
1137skip_epoch:
1138 map = store->messages;
1139
1140 if (get_message_discourse (message))
1141 map = store->discourses;
1142
1144 {
1146 "Message has already been stored! (%s)\n",
1147 GNUNET_h2s (hash));
1148 return GNUNET_SYSERR;
1149 }
1150
1152 map, hash, message,
1154
1155 if ((GNUNET_OK != result) || (map == store->discourses))
1156 return result;
1157
1158 if (! store->writing_task)
1162 store);
1163
1164 return result;
1165}
1166
1167
1170 const struct GNUNET_HashCode *hash)
1171{
1172 const struct GNUNET_MESSENGER_MessageEntry *entry;
1173 const struct GNUNET_MESSENGER_Message *message;
1174
1175 GNUNET_assert ((store) && (hash));
1176
1177 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
1178
1179 if (! entry)
1180 goto clear_memory;
1181
1182 message = get_store_message (store, hash);
1183
1184 if (message)
1185 {
1186 if (GNUNET_YES == is_epoch_message (message))
1187 {
1189 "Deletion of message is not allowed! (%s)\n",
1190 GNUNET_h2s (hash));
1191 return GNUNET_SYSERR;
1192 }
1193
1194 add_link (store, hash, message);
1195 }
1196
1197 if (! store->storage_messages)
1198 goto clear_entry;
1199
1200 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
1201 entry->offset,
1203 return GNUNET_SYSERR;
1204
1205 {
1207 char *clear_buffer;
1208
1209 clear_buffer = GNUNET_malloc (entry->length);
1210
1211 if (! clear_buffer)
1212 return GNUNET_SYSERR;
1213
1214 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
1215
1216 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages,
1217 clear_buffer, entry->length))
1218 ||
1221 else
1222 result = GNUNET_OK;
1223
1224 GNUNET_free (clear_buffer);
1225
1226 if (GNUNET_OK != result)
1227 return result;
1228 }
1229
1230clear_entry:
1232 entry))
1233 store->rewrite_entries = GNUNET_YES;
1234
1235clear_memory:
1239 return GNUNET_OK;
1240}
1241
1242
1244{
1248};
1249
1250static enum GNUNET_GenericReturnValue
1252 const struct GNUNET_HashCode *key,
1253 void *value)
1254{
1256 struct GNUNET_MESSENGER_Message *message;
1257 const struct GNUNET_ShortHashCode *discourse;
1258
1259 GNUNET_assert ((cls) && (key) && (value));
1260
1261 cleanup = cls;
1262 message = value;
1263
1264 discourse = get_message_discourse (message);
1265
1266 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1267 return GNUNET_YES;
1268
1269 {
1272
1273 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1274 return GNUNET_YES;
1275 }
1276
1278 destroy_message (message);
1279
1280 return GNUNET_YES;
1281}
1282
1283
1284void
1286 store,
1287 const struct GNUNET_ShortHashCode *
1288 discourse,
1289 const struct GNUNET_TIME_Absolute
1290 timestamp)
1291{
1294
1295 GNUNET_assert ((store) && (discourse));
1296
1298
1299 cleanup.list = &list;
1300 cleanup.timestamp = timestamp;
1301
1302 GNUNET_memcpy (&(cleanup.discourse), discourse,
1303 sizeof (struct GNUNET_ShortHashCode));
1304
1307 &cleanup);
1308
1309 {
1310 struct GNUNET_MESSENGER_ListMessage *element;
1311 for (element = list.head; element; element = element->next)
1313 store->discourses,
1314 &(element->hash));
1315 }
1316
1318}
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)
static enum GNUNET_GenericReturnValue iterate_destroy_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.
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:1308
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:557
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:745
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:1507
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1386
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:704
@ 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.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
@ 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_BULK
@ 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:1237
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
#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 maximum 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 maximum 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 217 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(), and delete_store_message().

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 store->entries = NULL;
144 store->messages = NULL;
145 store->links = NULL;
146 store->discourses = NULL;
147 store->epochs = NULL;
148
149 if (store->directory)
150 {
151 GNUNET_free (store->directory);
152 store->directory = NULL;
153 }
154}
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)
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:986

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 158 of file gnunet-service-messenger_message_store.c.

160{
161 GNUNET_assert ((store) && (directory));
162
163 if (store->directory)
164 {
165 if (0 == strcmp (store->directory, directory))
166 return;
167
169 {
171 "Moving message store failed because directory exists already! (%s)\n",
172 directory);
173 return;
174 }
175
176 if (0 != rename (store->directory, directory))
177 {
179 "Moving message store failed! (%s -> %s)\n",
180 store->directory, directory);
181 return;
182 }
183
184 GNUNET_free (store->directory);
185 }
186
187 store->directory = GNUNET_strdup (directory);
188}
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition disk.c:466

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 198 of file gnunet-service-messenger_message_store.c.

202{
203 ssize_t result;
204
205 result = GNUNET_DISK_file_read (file, attribute, attribute_len);
206 if (GNUNET_SYSERR != result)
207 *size -= result;
208
209 return attribute_len != result;
210}

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 222 of file gnunet-service-messenger_message_store.c.

224{
225 enum GNUNET_DISK_AccessPermissions permission;
226 struct GNUNET_DISK_FileHandle *entries;
228 struct GNUNET_MESSENGER_MessageEntry *entry;
229 uint64_t entry_size, size;
230
233 return;
234
235 entry_size = sizeof(storage.hash) + sizeof(storage.entry.offset) + sizeof(
236 storage.entry.length);
237
238 if (size < entry_size)
239 return;
240
241 permission = (GNUNET_DISK_PERM_USER_READ);
243 permission);
244
245 if (! entries)
246 return;
247
248 memset (&storage, 0, sizeof(storage));
249 entry = NULL;
250
251 while (size >= entry_size)
252 {
253 if ((load_message_store_attribute_failed (entries, storage.hash, size)) ||
254 (load_message_store_attribute_failed (entries, storage.entry.offset,
255 size)) ||
256 (load_message_store_attribute_failed (entries, storage.entry.length,
257 size)))
258 {
259 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading message entry failed!\n");
260 break;
261 }
262
264
265 if (! entry)
266 break;
267
268 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
269
271 store->entries, &(storage.hash))) ||
273 store->entries, &(storage.hash), entry,
275 {
277 "Loading message entry twice: %s\n",
278 GNUNET_h2s (&(storage.hash)));
280 break;
281 }
282
284 "Loading message entry with hash: %s\n",
285 GNUNET_h2s (&(storage.hash)));
286
287 entry = NULL;
288 }
289
290 if (entry)
291 GNUNET_free (entry);
292
293 GNUNET_DISK_file_close (entries);
294}

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 304 of file gnunet-service-messenger_message_store.c.

306{
307 enum GNUNET_DISK_AccessPermissions permission;
310 struct GNUNET_MESSENGER_MessageLink *link;
311 uint64_t link_size, size;
312
315 return;
316
317 link_size = sizeof(storage.hash) + sizeof(storage.link.multiple) + sizeof(
318 storage.link.first);
319
320 if (size < link_size)
321 return;
322
323 permission = (GNUNET_DISK_PERM_USER_READ);
324
326 permission);
327
328 if (! links)
329 return;
330
331 memset (&storage, 0, sizeof(storage));
332 link = NULL;
333
334 while (size >= link_size)
335 {
336 if ((load_message_store_attribute_failed (links, storage.hash, size)) ||
338 storage.link.multiple, size)) ||
339 (load_message_store_attribute_failed (links, storage.link.first, size))
340 ||
341 ((GNUNET_YES == storage.link.multiple) &&
342 (load_message_store_attribute_failed (links, storage.link.second, size)
343 )))
344 break;
345
347
348 if (! link)
349 break;
350
351 GNUNET_memcpy (link, &(storage.link), sizeof(*link));
352
354 store->links, &(storage.hash))) ||
356 store->links, &(storage.hash), link,
358 break;
359
360 link = NULL;
361 }
362
363 if (link)
364 GNUNET_free (link);
365
367}

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 371 of file gnunet-service-messenger_message_store.c.

373{
374 enum GNUNET_DISK_AccessPermissions permission;
376 struct GNUNET_HashCode storage[2];
377 struct GNUNET_HashCode *epoch;
378 uint64_t epoch_size, size;
379
382 return;
383
384 epoch_size = sizeof(storage[0]) + sizeof(storage[1]);
385
386 if (size < epoch_size)
387 return;
388
389 permission = (GNUNET_DISK_PERM_USER_READ);
390
392 permission);
393
394 if (! epochs)
395 return;
396
397 epoch = NULL;
398
399 while (size >= epoch_size)
400 {
401 if ((load_message_store_attribute_failed (epochs, storage[0], size)) ||
403 break;
404
405 epoch = GNUNET_new (struct GNUNET_HashCode);
406
407 if (! epoch)
408 break;
409
410 GNUNET_memcpy (epoch, &(storage[1]), sizeof(*epoch));
411
413 store->epochs, &(storage[0]))) ||
415 store->epochs, &(storage[0]), epoch,
417 break;
418
419 epoch = NULL;
420 }
421
422 if (epoch)
423 GNUNET_free (epoch);
424
426}

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 430 of file gnunet-service-messenger_message_store.c.

431{
432 enum GNUNET_DISK_AccessPermissions permission;
433 char *filename;
434
435 GNUNET_assert (store);
436
437 if (! store->directory)
438 return;
439
441
442 if (store->storage_messages)
444
446 "%s%s", store->directory, "messages.store");
447
451 permission);
452 else
453 store->storage_messages = NULL;
454
456
457 if (! store->storage_messages)
458 return;
459
461 "%s%s", store->directory, "entries.store");
462
465
468 "%s%s", store->directory, "links.store");
469
472
475 "%s%s", store->directory, "epochs.store");
476
479
481}

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 493 of file gnunet-service-messenger_message_store.c.

496{
498 struct GNUNET_HashCode *epoch;
499
500 GNUNET_assert ((cls) && (key) && (value));
501
502 save = cls;
503 epoch = value;
504
505 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
506 (save_message_store_attribute_failed (save->storage, (*epoch))))
507 return GNUNET_NO;
508
509 return GNUNET_YES;
510}

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 514 of file gnunet-service-messenger_message_store.c.

517{
519 struct GNUNET_MESSENGER_MessageLink *link;
520
521 GNUNET_assert ((cls) && (key) && (value));
522
523 save = cls;
524 link = value;
525
526 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
529 return GNUNET_NO;
530
531 if ((GNUNET_YES == link->multiple) &&
533 return GNUNET_NO;
534
535 return GNUNET_YES;
536}

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 540 of file gnunet-service-messenger_message_store.c.

543{
545 struct GNUNET_MESSENGER_MessageEntry *entry;
546
547 GNUNET_assert ((cls) && (key) && (value));
548
549 save = cls;
550 entry = value;
551
552 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
553 (save_message_store_attribute_failed (save->storage, entry->offset)) ||
555 return GNUNET_NO;
556
557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message entry with hash: %s\n",
558 GNUNET_h2s (key));
559
560 return GNUNET_YES;
561}

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 565 of file gnunet-service-messenger_message_store.c.

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

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_BULK, 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 649 of file gnunet-service-messenger_message_store.c.

650{
652 enum GNUNET_DISK_AccessPermissions permission;
653 char *filename;
654
656
657 if (! store->directory)
658 return;
659
661
663 "%s%s", store->directory, "epochs.store");
664
665 save.store = store;
667 | GNUNET_DISK_OPEN_CREATE, permission);
668
670
671 if (! save.storage)
672 {
674 "No access to local storage of message epochs!\n");
675 goto save_links;
676 }
677
678 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
680 goto close_epochs;
681
683 &save);
684
685close_epochs:
687
688save_links:
690 goto save_entries;
691
693 "%s%s", store->directory, "links.store");
694
695 save.store = store;
697 | GNUNET_DISK_OPEN_CREATE, permission);
698
700
701 if (! save.storage)
702 {
704 "No access to local storage of message links!\n");
705 goto save_entries;
706 }
707
708 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
710 goto close_links;
711
713 &save);
715
716close_links:
718
719save_entries:
721 "%s%s", store->directory, "entries.store");
722
723 save.store = store;
725 | GNUNET_DISK_OPEN_CREATE, permission);
726
728
729 if (! save.storage)
730 {
732 "No access to local storage of message entries!\n");
733 return;
734 }
735
737 {
738 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
740 goto close_entries;
741
743 &save);
745 }
746 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
748 goto close_entries;
749
752
754 "%s%s", store->directory, "messages.store");
755
759 permission);
760
762
764 {
767
769 GNUNET_DISK_file_sync (save.storage);
770 }
771
772close_entries:
774 save.storage = NULL;
775}

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 779 of file gnunet-service-messenger_message_store.c.

781{
782 GNUNET_assert ((store) && (hash));
783
785 hash))
786 return GNUNET_YES;
787
789 hash))
790 return GNUNET_YES;
791
793}

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 797 of file gnunet-service-messenger_message_store.c.

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

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 908 of file gnunet-service-messenger_message_store.c.

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

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 948 of file gnunet-service-messenger_message_store.c.

950{
951 struct GNUNET_HashCode *epoch;
952
953 GNUNET_assert ((store) && (hash));
954
955 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
956
957 if (! epoch)
958 return hash;
959
960 return epoch;
961}

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

Referenced by callback_found_message(), handle_room_messages(), iterate_srv_handle_sync_finished(), notify_about_members(), put_store_message(), and sign_srv_room_message().

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 965 of file gnunet-service-messenger_message_store.c.

968{
969 struct GNUNET_MESSENGER_MessageLink *link;
970
971 GNUNET_assert ((store) && (hash) && (message));
972
973 if (GNUNET_is_zero (hash))
974 return;
975
977
978 GNUNET_memcpy (&(link->first), &(message->header.previous),
979 sizeof(link->first));
980
983
984 if (GNUNET_YES == link->multiple)
985 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
986 sizeof(link->second));
987 else
988 GNUNET_memcpy (&(link->second), &(message->header.previous),
989 sizeof(link->second));
990
992 store->links, hash, link,
994 GNUNET_free (link);
995 else
996 store->write_links = GNUNET_YES;
997}

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 1001 of file gnunet-service-messenger_message_store.c.

1004{
1005 struct GNUNET_HashCode *copy;
1006
1007 GNUNET_assert ((store) && (hash) && (epoch));
1008
1009 if (GNUNET_is_zero (hash))
1010 return;
1011
1013 store->epochs, hash))
1014 return;
1015
1016 copy = GNUNET_new (struct GNUNET_HashCode);
1017
1018 if (! copy)
1019 return;
1020
1021 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1022
1024 store->epochs, hash, copy,
1026 GNUNET_free (copy);
1027}

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 1031 of file gnunet-service-messenger_message_store.c.

1032{
1033 struct GNUNET_MESSENGER_MessageStore *store;
1034
1035 GNUNET_assert (cls);
1036
1037 store = cls;
1038 store->writing_task = NULL;
1039
1040 save_message_store (store);
1041}

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 1045 of file gnunet-service-messenger_message_store.c.

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

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 1170 of file gnunet-service-messenger_message_store.c.

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

References add_link(), GNUNET_MESSENGER_MessageStore::entries, get_store_message(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_get_multiple(), 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(), iterate_destroy_messages(), 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 1252 of file gnunet-service-messenger_message_store.c.

1255{
1257 struct GNUNET_MESSENGER_Message *message;
1258 const struct GNUNET_ShortHashCode *discourse;
1259
1260 GNUNET_assert ((cls) && (key) && (value));
1261
1262 cleanup = cls;
1263 message = value;
1264
1265 discourse = get_message_discourse (message);
1266
1267 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1268 return GNUNET_YES;
1269
1270 {
1273
1274 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1275 return GNUNET_YES;
1276 }
1277
1279 destroy_message (message);
1280
1281 return GNUNET_YES;
1282}

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 1286 of file gnunet-service-messenger_message_store.c.

1292{
1295
1296 GNUNET_assert ((store) && (discourse));
1297
1299
1300 cleanup.list = &list;
1301 cleanup.timestamp = timestamp;
1302
1303 GNUNET_memcpy (&(cleanup.discourse), discourse,
1304 sizeof (struct GNUNET_ShortHashCode));
1305
1308 &cleanup);
1309
1310 {
1311 struct GNUNET_MESSENGER_ListMessage *element;
1312 for (element = list.head; element; element = element->next)
1314 store->discourses,
1315 &(element->hash));
1316 }
1317
1319}

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: