aboutsummaryrefslogtreecommitdiff
path: root/src/service/messenger/gnunet-service-messenger_operation_store.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/messenger/gnunet-service-messenger_operation_store.c')
-rw-r--r--src/service/messenger/gnunet-service-messenger_operation_store.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/src/service/messenger/gnunet-service-messenger_operation_store.c b/src/service/messenger/gnunet-service-messenger_operation_store.c
new file mode 100644
index 000000000..630ed6dbd
--- /dev/null
+++ b/src/service/messenger/gnunet-service-messenger_operation_store.c
@@ -0,0 +1,268 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021--2024 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 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_operation_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "platform.h"
27#include "gnunet-service-messenger_operation_store.h"
28
29#include "gnunet-service-messenger_operation.h"
30#include "gnunet-service-messenger_room.h"
31
32void
33init_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
34 struct GNUNET_MESSENGER_SrvRoom *room)
35{
36 GNUNET_assert ((store) && (room));
37
38 store->room = room;
39 store->operations = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
40}
41
42
43static enum GNUNET_GenericReturnValue
44iterate_destroy_operations (void *cls,
45 const struct GNUNET_HashCode *key,
46 void *value)
47{
48 struct GNUNET_MESSENGER_Operation *op = value;
49
50 destroy_operation (op);
51
52 return GNUNET_YES;
53}
54
55
56void
57clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store)
58{
59 GNUNET_assert (store);
60
61 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Clear operation store of room: %s\n",
62 GNUNET_h2s (get_srv_room_key (store->room)));
63
64 GNUNET_CONTAINER_multihashmap_iterate (store->operations,
65 iterate_destroy_operations, NULL);
66 GNUNET_CONTAINER_multihashmap_destroy (store->operations);
67}
68
69
70static enum GNUNET_GenericReturnValue
71callback_scan_for_operations (void *cls,
72 const char *filename)
73{
74 struct GNUNET_MESSENGER_OperationStore *store = cls;
75
76 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
77 return GNUNET_OK;
78
79 if ((strlen (filename) <= 4) || (0 != strcmp (filename + strlen (filename)
80 - 4, ".cfg")))
81 return GNUNET_OK;
82
83 struct GNUNET_MESSENGER_Operation *op = load_operation (store, filename);
84
85 if ((op) && (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (
86 store->operations,
87 &(op->hash), op,
88 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
89 {
90 destroy_operation (op);
91 }
92
93 return GNUNET_OK;
94}
95
96
97void
98load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
99 const char *directory)
100{
101 GNUNET_assert ((store) && (directory));
102
103 char *load_dir;
104 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
105
106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
107 "Load operation store from directory: %s\n",
108 load_dir);
109
110 if (GNUNET_OK == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
111 GNUNET_DISK_directory_scan (load_dir, callback_scan_for_operations, store);
112
113 GNUNET_free (load_dir);
114}
115
116
117static enum GNUNET_GenericReturnValue
118iterate_save_operations (void *cls,
119 const struct GNUNET_HashCode *key,
120 void *value)
121{
122 const char *save_dir = cls;
123
124 struct GNUNET_MESSENGER_Operation *op = value;
125
126 if (! op)
127 return GNUNET_YES;
128
129 char *op_dir;
130 GNUNET_asprintf (&op_dir, "%s%s.cfg", save_dir, GNUNET_h2s (key));
131 save_operation (op, op_dir);
132
133 GNUNET_free (op_dir);
134 return GNUNET_YES;
135}
136
137
138void
139save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
140 const char *directory)
141{
142 GNUNET_assert ((store) && (directory));
143
144 char *save_dir;
145 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
146
147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148 "Save operation store to directory: %s\n",
149 save_dir);
150
151 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
152 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
153 GNUNET_CONTAINER_multihashmap_iterate (store->operations,
154 iterate_save_operations, save_dir);
155
156 GNUNET_free (save_dir);
157}
158
159
160enum GNUNET_MESSENGER_OperationType
161get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
162 const struct GNUNET_HashCode *hash)
163{
164 GNUNET_assert ((store) && (hash));
165
166 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get (
167 store->operations, hash);
168
169 if (! op)
170 return GNUNET_MESSENGER_OP_UNKNOWN;
171
172 return op->type;
173}
174
175
176enum GNUNET_GenericReturnValue
177use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
178 const struct GNUNET_HashCode *hash,
179 enum GNUNET_MESSENGER_OperationType type,
180 struct GNUNET_TIME_Relative delay)
181{
182 GNUNET_assert ((store) && (hash));
183
184 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get (
185 store->operations, hash);
186
187 if (op)
188 goto use_op;
189
190 op = create_operation (hash);
191
192 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->operations, hash,
193 op,
194 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
195 {
196 destroy_operation (op);
197
198 return GNUNET_SYSERR;
199 }
200
201use_op:
202 if ((op->type != GNUNET_MESSENGER_OP_UNKNOWN) &&
203 (type == GNUNET_MESSENGER_OP_DELETE))
204 stop_operation (op);
205
206 return start_operation (op, type, store, delay);
207}
208
209
210void
211cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
212 const struct GNUNET_HashCode *hash)
213{
214 GNUNET_assert ((store) && (hash));
215
216 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get (
217 store->operations, hash);
218
219 if (! op)
220 return;
221
222 stop_operation (op);
223
224 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (store->operations,
225 hash, op))
226 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
227 "Canceled operation could not be removed: %s\n",
228 GNUNET_h2s (hash));
229
230 destroy_operation (op);
231}
232
233
234extern void
235callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room,
236 const struct GNUNET_HashCode *hash);
237
238extern void
239callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room,
240 const struct GNUNET_HashCode *hash);
241
242void
243callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
244 enum GNUNET_MESSENGER_OperationType type,
245 const struct GNUNET_HashCode *hash)
246{
247 GNUNET_assert ((store) && (hash));
248
249 struct GNUNET_HashCode op_hash;
250 GNUNET_memcpy (&op_hash, hash, sizeof(op_hash));
251 cancel_store_operation (store, &op_hash);
252
253 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
254
255 switch (type)
256 {
257 case GNUNET_MESSENGER_OP_REQUEST:
258 break;
259 case GNUNET_MESSENGER_OP_DELETE:
260 callback_room_deletion (room, &op_hash);
261 break;
262 case GNUNET_MESSENGER_OP_MERGE:
263 callback_room_merge (room, &op_hash);
264 break;
265 default:
266 break;
267 }
268}