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