GNUnet 0.29.1-7-g14698f198
 
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_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.
 
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.
 
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 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
505 discourses,
506 key))
507 return GNUNET_YES;
508
509 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
510 (save_message_store_attribute_failed (save->storage, (*epoch))))
511 return GNUNET_NO;
512
513 return GNUNET_YES;
514}
515
516
518iterate_save_links (void *cls,
519 const struct GNUNET_HashCode *key,
520 void *value)
521{
523 struct GNUNET_MESSENGER_MessageLink *link;
524
525 GNUNET_assert ((cls) && (key) && (value));
526
527 save = cls;
528 link = value;
529
530 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
533 return GNUNET_NO;
534
535 if ((GNUNET_YES == link->multiple) &&
537 return GNUNET_NO;
538
539 return GNUNET_YES;
540}
541
542
544iterate_save_entries (void *cls,
545 const struct GNUNET_HashCode *key,
546 void *value)
547{
549 struct GNUNET_MESSENGER_MessageEntry *entry;
550
551 GNUNET_assert ((cls) && (key) && (value));
552
553 save = cls;
554 entry = value;
555
556 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
557 (save_message_store_attribute_failed (save->storage, entry->offset)) ||
559 return GNUNET_NO;
560
561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message entry with hash: %s\n",
562 GNUNET_h2s (key));
563
564 return GNUNET_YES;
565}
566
567
569iterate_save_messages (void *cls,
570 const struct GNUNET_HashCode *key,
571 void *value)
572{
575 struct GNUNET_MESSENGER_Message *message;
576
577 GNUNET_assert ((cls) && (key) && (value));
578
579 save = cls;
580
582 save->store->entries, key))
583 {
585 "Skipping storage of message: %s\n", GNUNET_h2s (key));
586 return GNUNET_YES;
587 }
588
589 message = value;
590
591 GNUNET_memcpy (&(storage.hash), key, sizeof(storage.hash));
592
593 storage.entry.length = get_message_size (message, GNUNET_YES);
594 storage.entry.offset = GNUNET_DISK_file_seek (
595 save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
596
597 if ((GNUNET_SYSERR == storage.entry.offset) ||
598 (save_message_store_attribute_failed (save->storage, storage.hash)) ||
600 storage.entry.offset)) ||
602 storage.entry.length)))
603 {
605 "Storing entry of message failed: %s\n", GNUNET_h2s (key));
606 return GNUNET_NO;
607 }
608
609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message with hash: %s\n",
610 GNUNET_h2s (&(storage.hash)));
611
612 {
613 char *buffer;
614 buffer = GNUNET_malloc (storage.entry.length);
615
616 if (! buffer)
617 return GNUNET_NO;
618
619 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
620
621 GNUNET_DISK_file_write (save->store->storage_messages, buffer,
622 storage.entry.length);
623
624 GNUNET_free (buffer);
625 }
626
627 {
628 struct GNUNET_MESSENGER_MessageEntry *entry;
630
631 if (! entry)
632 return GNUNET_NO;
633
634 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
635
637 save->store->entries, &(storage.hash), entry,
639 {
641 "Message entry might get stored twice: %s\n",
642 GNUNET_h2s (&(storage.hash)));
643 GNUNET_free (entry);
644 return GNUNET_NO;
645 }
646 }
647
648 return GNUNET_YES;
649}
650
651
652void
654{
656 enum GNUNET_DISK_AccessPermissions permission;
657 char *filename;
658
660
661 if (store->writing_task)
662 {
664 store->writing_task = NULL;
665 }
666
667 if (! store->directory)
668 return;
669
671
673 "%s%s", store->directory, "epochs.store");
674
675 save.store = store;
677 | GNUNET_DISK_OPEN_CREATE, permission);
678
680
681 if (! save.storage)
682 {
684 "No access to local storage of message epochs!\n");
685 goto save_links;
686 }
687
688 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
690 goto close_epochs;
691
693 &save);
694
695close_epochs:
697
698save_links:
700 goto save_entries;
701
703 "%s%s", store->directory, "links.store");
704
705 save.store = store;
707 | GNUNET_DISK_OPEN_CREATE, permission);
708
710
711 if (! save.storage)
712 {
714 "No access to local storage of message links!\n");
715 goto save_entries;
716 }
717
718 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
720 goto close_links;
721
723 &save);
725
726close_links:
728
729save_entries:
731 "%s%s", store->directory, "entries.store");
732
733 save.store = store;
735 | GNUNET_DISK_OPEN_CREATE, permission);
736
738
739 if (! save.storage)
740 {
742 "No access to local storage of message entries!\n");
743 return;
744 }
745
747 {
748 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
750 goto close_entries;
751
753 &save);
755 }
756 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
758 goto close_entries;
759
762
764 "%s%s", store->directory, "messages.store");
765
769 permission);
770
772
774 {
777
779 GNUNET_DISK_file_sync (save.storage);
780 }
781
782close_entries:
784 save.storage = NULL;
785}
786
787
790 const struct GNUNET_HashCode *hash)
791{
792 GNUNET_assert ((store) && (hash));
793
795 hash))
796 return GNUNET_YES;
797
799 hash))
800 return GNUNET_YES;
801
803}
804
805
806const struct GNUNET_MESSENGER_Message*
808 const struct GNUNET_HashCode *hash)
809{
810 struct GNUNET_MESSENGER_Message *message;
811 const struct GNUNET_MESSENGER_MessageEntry *entry;
812 enum GNUNET_GenericReturnValue decoding;
813 struct GNUNET_HashCode check;
814 char *buffer;
815
816 GNUNET_assert ((store) && (hash));
817
818 if (GNUNET_is_zero (hash))
819 return NULL;
820
821 message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
822
823 if (message)
824 return message;
825
826 message = GNUNET_CONTAINER_multihashmap_get (store->discourses, hash);
827
828 if (message)
829 return message;
830
831 if (! store->storage_messages)
832 {
834 "Local storage of messages is unavailable: %s\n",
835 GNUNET_h2s (hash));
836 return NULL;
837 }
838
839 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
840
841 if (! entry)
842 {
844 "No entry in storage for message found: %s\n",
845 GNUNET_h2s (hash));
846 return NULL;
847 }
848
849 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
850 entry->offset,
852 {
854 "Offset for message in local storage invalid: %s\n",
855 GNUNET_h2s (hash));
856 return NULL;
857 }
858
859 buffer = GNUNET_malloc (entry->length);
860
861 if (! buffer)
862 {
864 "Allocation for message data buffer failed: %s\n",
865 GNUNET_h2s (hash));
866 return NULL;
867 }
868
869 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) !=
870 entry->length) ||
872 GNUNET_YES)))
873 {
875 "Reading message from local storage failed: %s\n",
876 GNUNET_h2s (hash));
877 goto free_buffer;
878 }
879
881 decoding = decode_message (message, entry->length, buffer,
882 GNUNET_YES, NULL);
883
884 hash_message (message, entry->length, buffer, &check);
885
886 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
887 {
889 "Decoding message failed or checksum mismatched: %s\n",
890 GNUNET_h2s (hash));
891
893 hash, entry))
895 "Corrupted entry could not be removed from store: %s\n",
896 GNUNET_h2s (hash));
897
899 goto free_message;
900 }
901
903 store->messages, hash, message,
905 goto free_buffer;
906
907free_message:
908 destroy_message (message);
909 message = NULL;
910
911free_buffer:
912 GNUNET_free (buffer);
913 return message;
914}
915
916
919 const struct GNUNET_HashCode *hash,
920 enum GNUNET_GenericReturnValue deleted_only)
921{
922 const struct GNUNET_MESSENGER_Message *message;
923
924 if (GNUNET_is_zero (hash))
925 return NULL;
926
927 if (GNUNET_YES == deleted_only)
928 goto get_link;
929
930 message = get_store_message (store, hash);
931
932 if (message)
933 {
934 static struct GNUNET_MESSENGER_MessageLink link;
935
936 GNUNET_memcpy (&(link.first), &(message->header.previous),
937 sizeof(link.first));
938
941
942 if (GNUNET_YES == link.multiple)
943 GNUNET_memcpy (&(link.second), &(message->body.merge.previous),
944 sizeof(link.second));
945 else
946 GNUNET_memcpy (&(link.second), &(message->header.previous),
947 sizeof(link.second));
948
949 return &link;
950 }
951
952get_link:
953 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
954}
955
956
957const struct GNUNET_HashCode*
959 const struct GNUNET_HashCode *hash)
960{
961 struct GNUNET_HashCode *epoch;
962
963 GNUNET_assert ((store) && (hash));
964
965 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
966
967 if (! epoch)
968 return hash;
969
970 return epoch;
971}
972
973
974static void
976 const struct GNUNET_HashCode *hash,
977 const struct GNUNET_MESSENGER_Message *message)
978{
979 struct GNUNET_MESSENGER_MessageLink *link;
980
981 GNUNET_assert ((store) && (hash) && (message));
982
983 if (GNUNET_is_zero (hash))
984 return;
985
987
988 GNUNET_memcpy (&(link->first), &(message->header.previous),
989 sizeof(link->first));
990
993
994 if (GNUNET_YES == link->multiple)
995 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
996 sizeof(link->second));
997 else
998 GNUNET_memcpy (&(link->second), &(message->header.previous),
999 sizeof(link->second));
1000
1002 store->links, hash, link,
1004 GNUNET_free (link);
1005 else
1006 store->write_links = GNUNET_YES;
1007}
1008
1009
1010static void
1012 const struct GNUNET_HashCode *hash,
1013 const struct GNUNET_HashCode *epoch)
1014{
1015 struct GNUNET_HashCode *copy;
1016
1017 GNUNET_assert ((store) && (hash) && (epoch));
1018
1019 if (GNUNET_is_zero (hash))
1020 return;
1021
1023 store->epochs, hash))
1024 return;
1025
1026 copy = GNUNET_new (struct GNUNET_HashCode);
1027
1028 if (! copy)
1029 return;
1030
1031 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1032
1034 store->epochs, hash, copy,
1036 GNUNET_free (copy);
1037}
1038
1039
1040static void
1041task_save_messages (void *cls)
1042{
1043 struct GNUNET_MESSENGER_MessageStore *store;
1044
1045 GNUNET_assert (cls);
1046
1047 store = cls;
1048 store->writing_task = NULL;
1049
1050 save_message_store (store);
1051}
1052
1053
1056 const struct GNUNET_HashCode *hash,
1057 struct GNUNET_MESSENGER_Message *message)
1058{
1059 struct GNUNET_HashCode *epoch;
1062
1063 GNUNET_assert ((store) && (hash) && (message));
1064
1065 if (GNUNET_is_zero (hash))
1066 return GNUNET_SYSERR;
1067
1068 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
1069
1070 if (epoch)
1071 goto reverse_epoch;
1072
1073 epoch = GNUNET_new (struct GNUNET_HashCode);
1074
1075 if (! epoch)
1076 goto skip_epoch;
1077
1078 switch (message->header.kind)
1079 {
1082 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1083 break;
1085 {
1086 const struct GNUNET_HashCode *epoch0;
1087 const struct GNUNET_HashCode *epoch1;
1088
1089 epoch0 = &(message->body.merge.epochs[0]);
1090 epoch1 = &(message->body.merge.epochs[1]);
1091
1092 if (0 == GNUNET_CRYPTO_hash_cmp (epoch0, epoch1))
1093 GNUNET_memcpy (epoch, epoch0, sizeof (struct GNUNET_HashCode));
1094 else
1095 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1096
1097 break;
1098 }
1099 default:
1101 epoch,
1102 get_store_message_epoch (store, &(message->header.previous)),
1103 sizeof (struct GNUNET_HashCode));
1104 break;
1105 }
1106
1108 store->epochs, hash, epoch,
1110 {
1111 GNUNET_free (epoch);
1112 goto skip_epoch;
1113 }
1114
1115reverse_epoch:
1116 switch (message->header.kind)
1117 {
1120 store,
1121 &(message->header.previous),
1122 &(message->body.join.epoch));
1123 break;
1126 store,
1127 &(message->header.previous),
1128 &(message->body.leave.epoch));
1129 break;
1132 store,
1133 &(message->header.previous),
1134 &(message->body.merge.epochs[0]));
1136 store,
1137 &(message->body.merge.previous),
1138 &(message->body.merge.epochs[1]));
1139 break;
1140 default:
1142 store,
1143 &(message->header.previous),
1144 epoch);
1145 break;
1146 }
1147
1148skip_epoch:
1149 map = store->messages;
1150
1151 if (get_message_discourse (message))
1152 map = store->discourses;
1153
1155 {
1157 "Message has already been stored! (%s)\n",
1158 GNUNET_h2s (hash));
1159 return GNUNET_SYSERR;
1160 }
1161
1163 map, hash, message,
1165
1166 if ((GNUNET_OK != result) || (map == store->discourses))
1167 return result;
1168
1169 if (! store->writing_task)
1173 store);
1174
1175 return result;
1176}
1177
1178
1181 const struct GNUNET_HashCode *hash)
1182{
1183 const struct GNUNET_MESSENGER_MessageEntry *entry;
1184 const struct GNUNET_MESSENGER_Message *message;
1185
1186 GNUNET_assert ((store) && (hash));
1187
1188 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
1189
1190 if (! entry)
1191 goto clear_memory;
1192
1193 message = get_store_message (store, hash);
1194
1195 if (message)
1196 {
1197 if (GNUNET_YES == is_epoch_message (message))
1198 {
1200 "Deletion of message is not allowed! (%s)\n",
1201 GNUNET_h2s (hash));
1202 return GNUNET_SYSERR;
1203 }
1204
1205 add_link (store, hash, message);
1206 }
1207
1208 if (! store->storage_messages)
1209 goto clear_entry;
1210
1211 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
1212 entry->offset,
1214 return GNUNET_SYSERR;
1215
1216 {
1218 char *clear_buffer;
1219
1220 clear_buffer = GNUNET_malloc (entry->length);
1221
1222 if (! clear_buffer)
1223 return GNUNET_SYSERR;
1224
1225 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
1226
1227 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages,
1228 clear_buffer, entry->length))
1229 ||
1232 else
1233 result = GNUNET_OK;
1234
1235 GNUNET_free (clear_buffer);
1236
1237 if (GNUNET_OK != result)
1238 return result;
1239 }
1240
1241clear_entry:
1243 entry))
1244 store->rewrite_entries = GNUNET_YES;
1245
1246clear_memory:
1250 return GNUNET_OK;
1251}
1252
1253
1255{
1259};
1260
1261static enum GNUNET_GenericReturnValue
1263 const struct GNUNET_HashCode *key,
1264 void *value)
1265{
1267 struct GNUNET_MESSENGER_Message *message;
1268 const struct GNUNET_ShortHashCode *discourse;
1269
1270 GNUNET_assert ((cls) && (key) && (value));
1271
1272 cleanup = cls;
1273 message = value;
1274
1275 discourse = get_message_discourse (message);
1276
1277 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1278 return GNUNET_YES;
1279
1280 {
1283
1284 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1285 return GNUNET_YES;
1286 }
1287
1289 destroy_message (message);
1290
1291 return GNUNET_YES;
1292}
1293
1294
1295void
1297 store,
1298 const struct GNUNET_ShortHashCode *
1299 discourse,
1300 const struct GNUNET_TIME_Absolute
1301 timestamp)
1302{
1305
1306 GNUNET_assert ((store) && (discourse));
1307
1309
1310 cleanup.list = &list;
1311 cleanup.timestamp = timestamp;
1312
1313 GNUNET_memcpy (&(cleanup.discourse), discourse,
1314 sizeof (struct GNUNET_ShortHashCode));
1315
1318 &cleanup);
1319
1320 {
1321 struct GNUNET_MESSENGER_ListMessage *element;
1322 for (element = list.head; element; element = element->next)
1324 &(element->hash)))
1326 store->epochs, &(element->hash));
1327 }
1328
1330}
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.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
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.

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
506 discourses,
507 key))
508 return GNUNET_YES;
509
510 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
511 (save_message_store_attribute_failed (save->storage, (*epoch))))
512 return GNUNET_NO;
513
514 return GNUNET_YES;
515}

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_contains(), 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 519 of file gnunet-service-messenger_message_store.c.

522{
524 struct GNUNET_MESSENGER_MessageLink *link;
525
526 GNUNET_assert ((cls) && (key) && (value));
527
528 save = cls;
529 link = value;
530
531 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
534 return GNUNET_NO;
535
536 if ((GNUNET_YES == link->multiple) &&
538 return GNUNET_NO;
539
540 return GNUNET_YES;
541}

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

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

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

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

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

655{
657 enum GNUNET_DISK_AccessPermissions permission;
658 char *filename;
659
661
662 if (store->writing_task)
663 {
665 store->writing_task = NULL;
666 }
667
668 if (! store->directory)
669 return;
670
672
674 "%s%s", store->directory, "epochs.store");
675
676 save.store = store;
678 | GNUNET_DISK_OPEN_CREATE, permission);
679
681
682 if (! save.storage)
683 {
685 "No access to local storage of message epochs!\n");
686 goto save_links;
687 }
688
689 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
691 goto close_epochs;
692
694 &save);
695
696close_epochs:
698
699save_links:
701 goto save_entries;
702
704 "%s%s", store->directory, "links.store");
705
706 save.store = store;
708 | GNUNET_DISK_OPEN_CREATE, permission);
709
711
712 if (! save.storage)
713 {
715 "No access to local storage of message links!\n");
716 goto save_entries;
717 }
718
719 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
721 goto close_links;
722
724 &save);
726
727close_links:
729
730save_entries:
732 "%s%s", store->directory, "entries.store");
733
734 save.store = store;
736 | GNUNET_DISK_OPEN_CREATE, permission);
737
739
740 if (! save.storage)
741 {
743 "No access to local storage of message entries!\n");
744 return;
745 }
746
748 {
749 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
751 goto close_entries;
752
754 &save);
756 }
757 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
759 goto close_entries;
760
763
765 "%s%s", store->directory, "messages.store");
766
770 permission);
771
773
775 {
778
780 GNUNET_DISK_file_sync (save.storage);
781 }
782
783close_entries:
785 save.storage = NULL;
786}

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_SCHEDULER_cancel(), 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, GNUNET_MESSENGER_MessageStore::write_links, and GNUNET_MESSENGER_MessageStore::writing_task.

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

792{
793 GNUNET_assert ((store) && (hash));
794
796 hash))
797 return GNUNET_YES;
798
800 hash))
801 return GNUNET_YES;
802
804}

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

810{
811 struct GNUNET_MESSENGER_Message *message;
812 const struct GNUNET_MESSENGER_MessageEntry *entry;
813 enum GNUNET_GenericReturnValue decoding;
814 struct GNUNET_HashCode check;
815 char *buffer;
816
817 GNUNET_assert ((store) && (hash));
818
819 if (GNUNET_is_zero (hash))
820 return NULL;
821
822 message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
823
824 if (message)
825 return message;
826
827 message = GNUNET_CONTAINER_multihashmap_get (store->discourses, hash);
828
829 if (message)
830 return message;
831
832 if (! store->storage_messages)
833 {
835 "Local storage of messages is unavailable: %s\n",
836 GNUNET_h2s (hash));
837 return NULL;
838 }
839
840 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
841
842 if (! entry)
843 {
845 "No entry in storage for message found: %s\n",
846 GNUNET_h2s (hash));
847 return NULL;
848 }
849
850 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
851 entry->offset,
853 {
855 "Offset for message in local storage invalid: %s\n",
856 GNUNET_h2s (hash));
857 return NULL;
858 }
859
860 buffer = GNUNET_malloc (entry->length);
861
862 if (! buffer)
863 {
865 "Allocation for message data buffer failed: %s\n",
866 GNUNET_h2s (hash));
867 return NULL;
868 }
869
870 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) !=
871 entry->length) ||
873 GNUNET_YES)))
874 {
876 "Reading message from local storage failed: %s\n",
877 GNUNET_h2s (hash));
878 goto free_buffer;
879 }
880
882 decoding = decode_message (message, entry->length, buffer,
883 GNUNET_YES, NULL);
884
885 hash_message (message, entry->length, buffer, &check);
886
887 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
888 {
890 "Decoding message failed or checksum mismatched: %s\n",
891 GNUNET_h2s (hash));
892
894 hash, entry))
896 "Corrupted entry could not be removed from store: %s\n",
897 GNUNET_h2s (hash));
898
900 goto free_message;
901 }
902
904 store->messages, hash, message,
906 goto free_buffer;
907
908free_message:
909 destroy_message (message);
910 message = NULL;
911
912free_buffer:
913 GNUNET_free (buffer);
914 return message;
915}

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

922{
923 const struct GNUNET_MESSENGER_Message *message;
924
925 if (GNUNET_is_zero (hash))
926 return NULL;
927
928 if (GNUNET_YES == deleted_only)
929 goto get_link;
930
931 message = get_store_message (store, hash);
932
933 if (message)
934 {
935 static struct GNUNET_MESSENGER_MessageLink link;
936
937 GNUNET_memcpy (&(link.first), &(message->header.previous),
938 sizeof(link.first));
939
940 link.multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind?
942
943 if (GNUNET_YES == link.multiple)
944 GNUNET_memcpy (&(link.second), &(message->body.merge.previous),
945 sizeof(link.second));
946 else
947 GNUNET_memcpy (&(link.second), &(message->header.previous),
948 sizeof(link.second));
949
950 return &link;
951 }
952
953get_link:
954 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
955}

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

961{
962 struct GNUNET_HashCode *epoch;
963
964 GNUNET_assert ((store) && (hash));
965
966 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
967
968 if (! epoch)
969 return hash;
970
971 return epoch;
972}

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

979{
980 struct GNUNET_MESSENGER_MessageLink *link;
981
982 GNUNET_assert ((store) && (hash) && (message));
983
984 if (GNUNET_is_zero (hash))
985 return;
986
988
989 GNUNET_memcpy (&(link->first), &(message->header.previous),
990 sizeof(link->first));
991
994
995 if (GNUNET_YES == link->multiple)
996 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
997 sizeof(link->second));
998 else
999 GNUNET_memcpy (&(link->second), &(message->header.previous),
1000 sizeof(link->second));
1001
1003 store->links, hash, link,
1005 GNUNET_free (link);
1006 else
1007 store->write_links = GNUNET_YES;
1008}

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

1015{
1016 struct GNUNET_HashCode *copy;
1017
1018 GNUNET_assert ((store) && (hash) && (epoch));
1019
1020 if (GNUNET_is_zero (hash))
1021 return;
1022
1024 store->epochs, hash))
1025 return;
1026
1027 copy = GNUNET_new (struct GNUNET_HashCode);
1028
1029 if (! copy)
1030 return;
1031
1032 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1033
1035 store->epochs, hash, copy,
1037 GNUNET_free (copy);
1038}

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

1043{
1044 struct GNUNET_MESSENGER_MessageStore *store;
1045
1046 GNUNET_assert (cls);
1047
1048 store = cls;
1049 store->writing_task = NULL;
1050
1051 save_message_store (store);
1052}

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

1059{
1060 struct GNUNET_HashCode *epoch;
1063
1064 GNUNET_assert ((store) && (hash) && (message));
1065
1066 if (GNUNET_is_zero (hash))
1067 return GNUNET_SYSERR;
1068
1069 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
1070
1071 if (epoch)
1072 goto reverse_epoch;
1073
1074 epoch = GNUNET_new (struct GNUNET_HashCode);
1075
1076 if (! epoch)
1077 goto skip_epoch;
1078
1079 switch (message->header.kind)
1080 {
1083 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1084 break;
1086 {
1087 const struct GNUNET_HashCode *epoch0;
1088 const struct GNUNET_HashCode *epoch1;
1089
1090 epoch0 = &(message->body.merge.epochs[0]);
1091 epoch1 = &(message->body.merge.epochs[1]);
1092
1093 if (0 == GNUNET_CRYPTO_hash_cmp (epoch0, epoch1))
1094 GNUNET_memcpy (epoch, epoch0, sizeof (struct GNUNET_HashCode));
1095 else
1096 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1097
1098 break;
1099 }
1100 default:
1102 epoch,
1103 get_store_message_epoch (store, &(message->header.previous)),
1104 sizeof (struct GNUNET_HashCode));
1105 break;
1106 }
1107
1109 store->epochs, hash, epoch,
1111 {
1112 GNUNET_free (epoch);
1113 goto skip_epoch;
1114 }
1115
1116reverse_epoch:
1117 switch (message->header.kind)
1118 {
1121 store,
1122 &(message->header.previous),
1123 &(message->body.join.epoch));
1124 break;
1127 store,
1128 &(message->header.previous),
1129 &(message->body.leave.epoch));
1130 break;
1133 store,
1134 &(message->header.previous),
1135 &(message->body.merge.epochs[0]));
1137 store,
1138 &(message->body.merge.previous),
1139 &(message->body.merge.epochs[1]));
1140 break;
1141 default:
1143 store,
1144 &(message->header.previous),
1145 epoch);
1146 break;
1147 }
1148
1149skip_epoch:
1150 map = store->messages;
1151
1152 if (get_message_discourse (message))
1153 map = store->discourses;
1154
1156 {
1158 "Message has already been stored! (%s)\n",
1159 GNUNET_h2s (hash));
1160 return GNUNET_SYSERR;
1161 }
1162
1164 map, hash, message,
1166
1167 if ((GNUNET_OK != result) || (map == store->discourses))
1168 return result;
1169
1170 if (! store->writing_task)
1174 store);
1175
1176 return result;
1177}

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

1183{
1184 const struct GNUNET_MESSENGER_MessageEntry *entry;
1185 const struct GNUNET_MESSENGER_Message *message;
1186
1187 GNUNET_assert ((store) && (hash));
1188
1189 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
1190
1191 if (! entry)
1192 goto clear_memory;
1193
1194 message = get_store_message (store, hash);
1195
1196 if (message)
1197 {
1198 if (GNUNET_YES == is_epoch_message (message))
1199 {
1201 "Deletion of message is not allowed! (%s)\n",
1202 GNUNET_h2s (hash));
1203 return GNUNET_SYSERR;
1204 }
1205
1206 add_link (store, hash, message);
1207 }
1208
1209 if (! store->storage_messages)
1210 goto clear_entry;
1211
1212 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
1213 entry->offset,
1215 return GNUNET_SYSERR;
1216
1217 {
1219 char *clear_buffer;
1220
1221 clear_buffer = GNUNET_malloc (entry->length);
1222
1223 if (! clear_buffer)
1224 return GNUNET_SYSERR;
1225
1226 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
1227
1228 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages,
1229 clear_buffer, entry->length))
1230 ||
1233 else
1234 result = GNUNET_OK;
1235
1236 GNUNET_free (clear_buffer);
1237
1238 if (GNUNET_OK != result)
1239 return result;
1240 }
1241
1242clear_entry:
1244 entry))
1245 store->rewrite_entries = GNUNET_YES;
1246
1247clear_memory:
1251 return GNUNET_OK;
1252}

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

1266{
1268 struct GNUNET_MESSENGER_Message *message;
1269 const struct GNUNET_ShortHashCode *discourse;
1270
1271 GNUNET_assert ((cls) && (key) && (value));
1272
1273 cleanup = cls;
1274 message = value;
1275
1276 discourse = get_message_discourse (message);
1277
1278 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1279 return GNUNET_YES;
1280
1281 {
1284
1285 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1286 return GNUNET_YES;
1287 }
1288
1290 destroy_message (message);
1291
1292 return GNUNET_YES;
1293}

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

1303{
1306
1307 GNUNET_assert ((store) && (discourse));
1308
1310
1311 cleanup.list = &list;
1312 cleanup.timestamp = timestamp;
1313
1314 GNUNET_memcpy (&(cleanup.discourse), discourse,
1315 sizeof (struct GNUNET_ShortHashCode));
1316
1319 &cleanup);
1320
1321 {
1322 struct GNUNET_MESSENGER_ListMessage *element;
1323 for (element = list.head; element; element = element->next)
1325 &(element->hash)))
1327 store->epochs, &(element->hash));
1328 }
1329
1331}

References cleanup(), clear_list_messages(), GNUNET_MESSENGER_CleanupDiscourseMessages::discourse, GNUNET_MESSENGER_MessageStore::discourses, GNUNET_MESSENGER_MessageStore::epochs, 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: