GNUnet  0.11.x
gnunet-service-messenger_message_store.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2020 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
27 #include "messenger_api_message.h"
28 
29 void
31 {
32  store->storage_messages = NULL;
33 
36 }
37 
38 static int
39 iterate_destroy_entries (void *cls, const struct GNUNET_HashCode *key, void *value)
40 {
41  struct GNUNET_MESSENGER_MessageEntry *entry = value;
42 
43  GNUNET_free(entry);
44 
45  return GNUNET_YES;
46 }
47 
48 static int
49 iterate_destroy_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
50 {
51  struct GNUNET_MESSENGER_Message *message = value;
52 
53  destroy_message (message);
54 
55  return GNUNET_YES;
56 }
57 
58 void
60 {
61  if (store->storage_messages)
62  {
64 
65  store->storage_messages = NULL;
66  }
67 
70 
73 }
74 
76 {
79 };
80 
81 void
82 load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
83 {
85 
86  if (store->storage_messages)
88 
89  char *filename;
90  GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
91 
92  if (GNUNET_YES == GNUNET_DISK_file_test (filename))
93  store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
94  else
95  store->storage_messages = NULL;
96 
97  GNUNET_free(filename);
98 
99  if (!store->storage_messages)
100  return;
101 
102  GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
103 
104  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
105  goto free_filename;
106 
108 
109  if (!entries)
110  goto free_filename;
111 
114 
115  do
116  {
118 
119  if (GNUNET_DISK_file_read (entries, &storage, sizeof(storage)) == sizeof(storage))
120  {
121  GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry));
122 
123  if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry,
125  GNUNET_free(entry);
126  }
127  else
128  {
129  GNUNET_free(entry);
130 
131  entry = NULL;
132  }
133  }
134  while (entry);
135 
136  GNUNET_DISK_file_close (entries);
137 
138 free_filename:
139  GNUNET_free(filename);
140 }
141 
143 {
145 
147 };
148 
149 static int
150 iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
151 {
152  struct GNUNET_MESSENGER_MessageSave *save = cls;
153 
155  return GNUNET_YES;
156 
157  struct GNUNET_MESSENGER_Message *message = value;
159 
160  GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
161 
162  storage.entry.length = get_message_size (message);
164 
165  if ((GNUNET_SYSERR == storage.entry.offset) ||
166  (sizeof(storage) != GNUNET_DISK_file_write (save->storage_entries, &storage, sizeof(storage))))
167  return GNUNET_YES;
168 
169  char *buffer = GNUNET_malloc(storage.entry.length);
170 
171  encode_message (message, storage.entry.length, buffer);
172 
173  GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length);
174 
175  GNUNET_free(buffer);
176 
177  return GNUNET_YES;
178 }
179 
180 void
181 save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
182 {
183  struct GNUNET_MESSENGER_MessageSave save;
184 
186 
187  char *filename;
188  GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
189 
190  save.store = store;
192 
193  GNUNET_free(filename);
194 
195  if (!save.storage_entries)
196  return;
197 
199  goto close_entries;
200 
201  if (store->storage_messages)
203 
204  GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
205 
207  permission);
208 
209  GNUNET_free(filename);
210 
211  if (store->storage_messages)
212  {
214 
217  }
218 
219 close_entries:
221 }
222 
223 int
225 {
227  return GNUNET_YES;
228 
229  return GNUNET_CONTAINER_multihashmap_contains (store->entries, hash);
230 }
231 
232 const struct GNUNET_MESSENGER_Message*
234 {
236 
237  if (message)
238  return message;
239 
240  if (!store->storage_messages)
241  return NULL;
242 
243  const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
244 
245  if (!entry)
246  return NULL;
247 
249  return message;
250 
251  char *buffer = GNUNET_malloc(entry->length);
252 
253  if (GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length)
254  goto free_buffer;
255 
256 
258 
259  if ((GNUNET_YES != decode_message (message, entry->length, buffer)) || (GNUNET_OK
260  != GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
262  {
263  destroy_message (message);
264 
265  message = NULL;
266 
267  GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry);
268  }
269 
270 free_buffer:
271  GNUNET_free(buffer);
272 
273  return message;
274 }
275 
276 int
278  struct GNUNET_MESSENGER_Message *message)
279 {
280  return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
282 }
int decode_message(struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer)
Decodes a message from a given buffer of a maximal length in bytes.
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:544
Open the file for reading.
int GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1433
Create file if it doesn&#39;t exist.
void destroy_message(struct GNUNET_MESSENGER_Message *message)
Destroys a message and frees its memory fully.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1280
void save_message_store(struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
Saves messages from a message store into a directory.
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:732
struct GNUNET_DISK_FileHandle * storage_messages
struct GNUNET_CONTAINER_MultiHashMap * messages
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t get_message_size(const struct GNUNET_MESSENGER_Message *message)
Returns the exact size in bytes to encode a given message.
void encode_message(const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer)
Encodes a given message into a buffer of a maximal length in bytes.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int 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)...
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:226
struct GNUNET_MESSENGER_Message * create_message(enum GNUNET_MESSENGER_MessageKind kind)
Creates and allocates a new message with a specific kind.
static void save()
Write persistent statistics to disk.
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.
static int iterate_save_messages(void *cls, const struct GNUNET_HashCode *key, void *value)
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
static char * value
Value of the record to add/remove.
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:820
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
void load_message_store(struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
Loads messages from a directory into a message store.
struct ListEntry * entries
List of peers in the list.
static char * filename
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
int contains_store_message(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Checks if a message matching a given hash is stored in a message store.
GNUNET_DISK_AccessPermissions
File access permissions, UNIX-style.
A 512-bit hashcode.
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.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
static int iterate_destroy_messages(void *cls, const struct GNUNET_HashCode *key, void *value)
struct GNUNET_HashCode key
The key used in the DHT.
Seek an absolute position from the end of the file.
Open the file for writing.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static int iterate_destroy_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
Seek an absolute position (from the start of the file).
Open the file for both reading and writing.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
void init_message_store(struct GNUNET_MESSENGER_MessageStore *store)
Initializes a message store as fully empty.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
int 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.
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:1203
Handle used to access files (and pipes).
struct GNUNET_MESSENGER_MessageStore * store
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_CONTAINER_MultiHashMap * entries
#define GNUNET_free(ptr)
Wrapper around free.
messenger api: client and service implementation of GNUnet MESSENGER service
void clear_message_store(struct GNUNET_MESSENGER_MessageStore *store)
Clears a message store, wipes its content and deallocates its memory.