diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2012-05-10 15:26:19 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2012-05-10 15:26:19 +0000 |
commit | f92e74047eaa5a949f50972fd52aabbf855e4e92 (patch) | |
tree | 5964e8d7f8b0fe6a82863a1e17230345a22f0f05 /src/lockmanager | |
parent | ab9ae5793e6bf50f53c548e2c97f102d0e002ac1 (diff) | |
download | gnunet-f92e74047eaa5a949f50972fd52aabbf855e4e92.tar.gz gnunet-f92e74047eaa5a949f50972fd52aabbf855e4e92.zip |
lockmanager with new datastructure
Diffstat (limited to 'src/lockmanager')
-rw-r--r-- | src/lockmanager/gnunet-service-lockmanager.c | 607 |
1 files changed, 378 insertions, 229 deletions
diff --git a/src/lockmanager/gnunet-service-lockmanager.c b/src/lockmanager/gnunet-service-lockmanager.c index 3a7a729c3..efd505a60 100644 --- a/src/lockmanager/gnunet-service-lockmanager.c +++ b/src/lockmanager/gnunet-service-lockmanager.c | |||
@@ -1,21 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2012 Christian Grothoff (and other contributing authors) | 3 | (C) 2012 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
7 | by the Free Software Foundation; either version 2, or (at your | 7 | by the Free Software Foundation; either version 2, or (at your |
8 | option) any later version. | 8 | option) any later version. |
9 | 9 | ||
10 | GNUnet is distributed in the hope that it will be useful, but | 10 | GNUnet is distributed in the hope that it will be useful, but |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | General Public License for more details. | 13 | General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU General Public License | 15 | You should have received a copy of the GNU General Public License |
16 | along with GNUnet; see the file COPYING. If not, write to the | 16 | along with GNUnet; see the file COPYING. If not, write to the |
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 | Boston, MA 02111-1307, USA. | 18 | Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
@@ -34,10 +34,10 @@ | |||
34 | #include "lockmanager.h" | 34 | #include "lockmanager.h" |
35 | 35 | ||
36 | 36 | ||
37 | #define LOG(kind,...) \ | 37 | #define LOG(kind,...) \ |
38 | GNUNET_log (kind, __VA_ARGS__) | 38 | GNUNET_log (kind, __VA_ARGS__) |
39 | 39 | ||
40 | #define TIME_REL_MINS(min) \ | 40 | #define TIME_REL_MINS(min) \ |
41 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, min) | 41 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, min) |
42 | 42 | ||
43 | #define TIMEOUT TIME_REL_MINS(3) | 43 | #define TIMEOUT TIME_REL_MINS(3) |
@@ -67,39 +67,29 @@ struct WaitList | |||
67 | /** | 67 | /** |
68 | * Pointer to the client | 68 | * Pointer to the client |
69 | */ | 69 | */ |
70 | struct GNUNET_SERVER_Client *client; | 70 | struct ClientList *cl_entry; |
71 | }; | 71 | }; |
72 | 72 | ||
73 | 73 | ||
74 | /** | 74 | /** |
75 | * A Lock element for a doubly linked list | 75 | * Structure representing a Lock |
76 | */ | 76 | */ |
77 | struct LockList | 77 | struct Lock |
78 | { | 78 | { |
79 | /** | 79 | /** |
80 | * The next element pointer | ||
81 | */ | ||
82 | struct LockList *next; | ||
83 | |||
84 | /** | ||
85 | * Pointer to the previous element | ||
86 | */ | ||
87 | struct LockList *prev; | ||
88 | |||
89 | /** | ||
90 | * List head of clients waiting for this lock | 80 | * List head of clients waiting for this lock |
91 | */ | 81 | */ |
92 | struct WaitList *wait_list_head; | 82 | struct WaitList *wl_head; |
93 | 83 | ||
94 | /** | 84 | /** |
95 | * List tail of clients waiting for this lock | 85 | * List tail of clients waiting for this lock |
96 | */ | 86 | */ |
97 | struct WaitList *wait_list_tail; | 87 | struct WaitList *wl_tail; |
98 | 88 | ||
99 | /** | 89 | /** |
100 | * The client which is currently holding this lock | 90 | * The client which is currently holding this lock |
101 | */ | 91 | */ |
102 | struct GNUNET_SERVER_Client *client; | 92 | struct ClientList *cl_entry; |
103 | 93 | ||
104 | /** | 94 | /** |
105 | * The name of the locking domain this lock belongs to | 95 | * The name of the locking domain this lock belongs to |
@@ -114,10 +104,33 @@ struct LockList | |||
114 | 104 | ||
115 | 105 | ||
116 | /** | 106 | /** |
107 | * A Lock element for a doubly linked list | ||
108 | */ | ||
109 | struct LockList | ||
110 | { | ||
111 | /** | ||
112 | * The next element pointer | ||
113 | */ | ||
114 | struct LockList *next; | ||
115 | |||
116 | /** | ||
117 | * Pointer to the previous element | ||
118 | */ | ||
119 | struct LockList *prev; | ||
120 | |||
121 | /** | ||
122 | * Pointer to the Lock | ||
123 | */ | ||
124 | struct Lock *lock; | ||
125 | }; | ||
126 | |||
127 | |||
128 | /** | ||
117 | * Doubly linked list of clients having connections to us | 129 | * Doubly linked list of clients having connections to us |
118 | */ | 130 | */ |
119 | struct ClientList | 131 | struct ClientList |
120 | { | 132 | { |
133 | |||
121 | /** | 134 | /** |
122 | * The next client structure | 135 | * The next client structure |
123 | */ | 136 | */ |
@@ -129,6 +142,16 @@ struct ClientList | |||
129 | struct ClientList *prev; | 142 | struct ClientList *prev; |
130 | 143 | ||
131 | /** | 144 | /** |
145 | * Head of the doubly linked list of the currently held locks by this client | ||
146 | */ | ||
147 | struct LockList *ll_head; | ||
148 | |||
149 | /** | ||
150 | * Tail of the doubly linked list of the currently held locks by this client | ||
151 | */ | ||
152 | struct LockList *ll_tail; | ||
153 | |||
154 | /** | ||
132 | * Pointer to the client | 155 | * Pointer to the client |
133 | */ | 156 | */ |
134 | struct GNUNET_SERVER_Client *client; | 157 | struct GNUNET_SERVER_Client *client; |
@@ -136,14 +159,9 @@ struct ClientList | |||
136 | 159 | ||
137 | 160 | ||
138 | /** | 161 | /** |
139 | * Head of the doubly linked list of the currently held locks | 162 | * Map of lock-keys to the 'struct LockList' entry for the key. |
140 | */ | ||
141 | static struct LockList *ll_head; | ||
142 | |||
143 | /** | ||
144 | * Tail of the doubly linked list of the currently held locks | ||
145 | */ | 163 | */ |
146 | static struct LockList *ll_tail; | 164 | static struct GNUNET_CONTAINER_MultiHashMap *lock_map; |
147 | 165 | ||
148 | /** | 166 | /** |
149 | * Head of the doubly linked list of clients currently connected | 167 | * Head of the doubly linked list of clients currently connected |
@@ -157,133 +175,210 @@ static struct ClientList *cl_tail; | |||
157 | 175 | ||
158 | 176 | ||
159 | /** | 177 | /** |
160 | * Function to search for a lock in lock_list matching the given domain_name and | 178 | * Get the key for the given lock in the 'lock_map'. |
161 | * lock number | ||
162 | * | 179 | * |
163 | * @param domain_name the name of the locking domain | 180 | * @param domain_name |
164 | * @param lock_num the number of the lock | 181 | * @param lock_number |
165 | * @param ret this will be the pointer to the corresponding Lock if found; else | 182 | * @param key set to the key |
166 | * it will be the last element in the locks list | ||
167 | * @return GNUNET_YES if a matching lock is present in lock_list; GNUNET_NO if not | ||
168 | */ | 183 | */ |
169 | static struct LockList * | 184 | static void |
170 | ll_find_lock (const char *domain_name, | 185 | get_key (const char *domain_name, |
171 | const uint32_t lock_num) | 186 | uint32_t lock_number, |
172 | 187 | struct GNUNET_HashCode *key) | |
173 | { | 188 | { |
174 | struct LockList *current_lock; | 189 | uint32_t *last_32; |
175 | 190 | ||
176 | for (current_lock = ll_head; NULL != current_lock; current_lock = current_lock->next) | 191 | GNUNET_CRYPTO_hash (domain_name, |
177 | if ( (lock_num == current_lock->lock_num) && | 192 | strlen (domain_name), |
178 | (0 == strcmp (domain_name, current_lock->domain_name)) ) | 193 | key); |
179 | return current_lock; | 194 | last_32 = (uint32_t *) key; |
180 | return NULL; | 195 | *last_32 ^= lock_number; |
181 | } | 196 | } |
182 | 197 | ||
183 | 198 | ||
184 | /** | 199 | /** |
185 | * Function to search for a lock in lock_list matching the given domain_name and | 200 | * Function to search for a lock in the global lock hashmap |
186 | * lock number | ||
187 | * | 201 | * |
188 | * @param client the client owning this lock currently | 202 | * @param domain_name the name of the locking domain |
189 | * @param ret this will be the pointer to the corresponding Lock if found; else | 203 | * @param lock_num the number of the lock |
190 | * it will be the last element in the locks list | 204 | * @return the lock if found; NULL if not |
191 | * @return GNUNET_YES if a matching lock is present in lock_list; GNUNET_NO if not | ||
192 | */ | 205 | */ |
193 | static struct LockList * | 206 | static struct Lock * |
194 | ll_find_lock_by_owner (const struct GNUNET_SERVER_Client *client) | 207 | find_lock (const char *domain_name, |
208 | const uint32_t lock_num) | ||
209 | |||
195 | { | 210 | { |
196 | struct LockList *current_lock; | 211 | struct Lock *matched_lock; |
197 | 212 | struct GNUNET_HashCode key; | |
198 | for (current_lock = ll_head; NULL != current_lock; current_lock = current_lock->next) | 213 | |
199 | if (client == current_lock->client) | 214 | matched_lock = NULL; |
200 | return current_lock; | 215 | int match_lock (void *cls, |
201 | return NULL; | 216 | const GNUNET_HashCode *key, |
217 | void *value) | ||
218 | { | ||
219 | matched_lock = value; | ||
220 | |||
221 | if ((lock_num == matched_lock->lock_num) | ||
222 | && (0 == strcmp (domain_name, matched_lock->domain_name))) | ||
223 | return GNUNET_NO; | ||
224 | matched_lock = NULL; | ||
225 | return GNUNET_YES; | ||
226 | } | ||
227 | get_key (domain_name, lock_num, &key); | ||
228 | GNUNET_CONTAINER_multihashmap_get_multiple (lock_map, | ||
229 | &key, | ||
230 | &match_lock, | ||
231 | NULL); | ||
232 | return matched_lock; | ||
202 | } | 233 | } |
203 | 234 | ||
204 | 235 | ||
205 | /** | 236 | /** |
206 | * Function to append a lock to the global lock list | 237 | * Adds a lock to the global lock hashmap |
207 | * | 238 | * |
208 | * @param client the client which currently owns this lock | 239 | * @param domain_name the name of the lock's locking domain |
209 | * @param domain_name the name of the locking domain | 240 | * @param lock_num the lock number |
210 | * @param lock_num the number of the lock | 241 | * @return pointer to the lock structure which is added to lock map |
211 | */ | 242 | */ |
212 | static void | 243 | static struct Lock * |
213 | ll_add_lock (struct GNUNET_SERVER_Client *client, | 244 | add_lock (const char *domain_name, |
214 | const char *domain_name, | 245 | uint32_t lock_num) |
215 | const uint32_t lock_num) | ||
216 | { | 246 | { |
217 | struct LockList *lock; | 247 | struct Lock *lock; |
248 | struct GNUNET_HashCode key; | ||
218 | size_t domain_name_len; | 249 | size_t domain_name_len; |
219 | 250 | ||
220 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 251 | lock = GNUNET_malloc (sizeof (struct Lock)); |
221 | "Adding a lock with num: %u and domain: %s to lock list\n", | ||
222 | lock_num, domain_name); | ||
223 | |||
224 | lock = GNUNET_malloc (sizeof (struct LockList)); | ||
225 | domain_name_len = strlen (domain_name) + 1; | 252 | domain_name_len = strlen (domain_name) + 1; |
226 | lock->domain_name = GNUNET_malloc (domain_name_len); | 253 | lock->domain_name = GNUNET_malloc (domain_name_len); |
227 | strncpy (lock->domain_name, domain_name, domain_name_len); | 254 | strncpy (lock->domain_name, domain_name, domain_name_len); |
228 | lock->lock_num = lock_num; | 255 | lock->lock_num = lock_num; |
229 | lock->client = client; | 256 | get_key (domain_name, lock_num, &key); |
230 | 257 | LOG (GNUNET_ERROR_TYPE_DEBUG, | |
231 | GNUNET_CONTAINER_DLL_insert_tail (ll_head, | 258 | "Adding a lock with num: %d and domain: %s to the lock map\n", |
232 | ll_tail, | 259 | lock->lock_num, lock->domain_name); |
233 | lock); | 260 | GNUNET_CONTAINER_multihashmap_put (lock_map, |
261 | &key, | ||
262 | lock, | ||
263 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
264 | return lock; | ||
234 | } | 265 | } |
235 | 266 | ||
236 | 267 | ||
237 | /** | 268 | /** |
238 | * Function to delete a lock from the lock list | 269 | * Removes a lock from the lock map |
239 | * | 270 | * |
240 | * @param lock the lock to be deleted | 271 | * @param the lock to remove |
241 | */ | 272 | */ |
242 | static void | 273 | static void |
243 | ll_remove_lock (struct LockList *lock) | 274 | remove_lock (struct Lock *lock) |
244 | { | 275 | { |
276 | struct GNUNET_HashCode key; | ||
277 | |||
278 | get_key (lock->domain_name, | ||
279 | lock->lock_num, | ||
280 | &key); | ||
245 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 281 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
246 | "Removing lock with num: %u, domain: %s\n", | 282 | "Removing lock with num: %u, domain: %s from lock map\n", |
247 | lock->lock_num, lock->domain_name); | 283 | lock->lock_num, lock->domain_name); |
248 | GNUNET_assert (NULL != ll_head); | 284 | GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove |
249 | GNUNET_CONTAINER_DLL_remove (ll_head, | 285 | (lock_map, &key, lock)); |
250 | ll_tail, | ||
251 | lock); | ||
252 | GNUNET_free (lock->domain_name); | 286 | GNUNET_free (lock->domain_name); |
253 | GNUNET_free (lock); | 287 | GNUNET_free (lock); |
254 | } | 288 | } |
255 | 289 | ||
256 | 290 | ||
257 | /** | 291 | /** |
258 | * Find a client in the waiting list of a lock | 292 | * Find the LockList entry corresponding to the given Lock in a ClientList |
293 | * entry | ||
259 | * | 294 | * |
260 | * @param lock the LockList entry of a lock | 295 | * @param cl_entry the ClientList entry whose lock list has to be searched |
261 | * @param client the client to look for | 296 | * @param lock the lock which has to be matched |
262 | * @param ret where to store the matched wait list entry | 297 | * @return the matching LockList entry; NULL if no match is found |
263 | * @return GNUNET_YES if a match is found; GNUNET_NO if not | ||
264 | */ | 298 | */ |
265 | static int | 299 | static struct LockList * |
266 | ll_wl_find_client (struct LockList *lock, | 300 | cl_ll_find_lock (struct ClientList *cl_entry, |
267 | const struct GNUNET_SERVER_Client *client, | 301 | const struct Lock *lock) |
268 | struct WaitList **ret) | ||
269 | { | 302 | { |
270 | struct WaitList *current_wl_entry; | 303 | struct LockList *ll_entry; |
271 | 304 | ||
272 | current_wl_entry = lock->wait_list_head; | 305 | for (ll_entry = cl_entry->ll_head; |
306 | NULL != ll_entry; ll_entry = ll_entry->next) | ||
307 | { | ||
308 | if (lock == ll_entry->lock) | ||
309 | return ll_entry; | ||
310 | } | ||
311 | return NULL; | ||
312 | } | ||
273 | 313 | ||
274 | while (NULL != current_wl_entry) | 314 | |
275 | { | 315 | /** |
276 | if (client == current_wl_entry->client) | 316 | * Function to append a lock to the lock list of a ClientList entry |
277 | { | 317 | * |
278 | if (NULL != ret) | 318 | * @param cl_entry the client which currently owns this lock |
279 | *ret = current_wl_entry; | 319 | * @param lock the lock to be added to the cl_entry's lock list |
280 | return GNUNET_YES; | 320 | */ |
281 | } | 321 | static void |
282 | current_wl_entry = current_wl_entry->next; | 322 | cl_ll_add_lock (struct ClientList *cl_entry, |
283 | } | 323 | struct Lock *lock) |
284 | if (NULL != ret) | 324 | { |
285 | *ret = current_wl_entry; | 325 | struct LockList *ll_entry; |
286 | return GNUNET_NO; | 326 | |
327 | ll_entry = GNUNET_malloc (sizeof (struct LockList)); | ||
328 | ll_entry->lock = lock; | ||
329 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
330 | "Adding a lock with num: %u and domain: %s to lock list\n", | ||
331 | lock->lock_num, lock->domain_name); | ||
332 | GNUNET_CONTAINER_DLL_insert_tail (cl_entry->ll_head, | ||
333 | cl_entry->ll_tail, | ||
334 | ll_entry); | ||
335 | } | ||
336 | |||
337 | |||
338 | /** | ||
339 | * Function to delete a lock from the lock list of the given ClientList entry | ||
340 | * | ||
341 | * @param cl_entry the ClientList entry | ||
342 | * @param ll_entry the LockList entry to be deleted | ||
343 | */ | ||
344 | static void | ||
345 | cl_ll_remove_lock (struct ClientList *cl_entry, | ||
346 | struct LockList *ll_entry) | ||
347 | { | ||
348 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
349 | "Removing lock with num: %u, domain: %s from lock list of a client\n", | ||
350 | ll_entry->lock->lock_num, | ||
351 | ll_entry->lock->domain_name); | ||
352 | GNUNET_assert (NULL != cl_entry->ll_head); | ||
353 | GNUNET_CONTAINER_DLL_remove (cl_entry->ll_head, | ||
354 | cl_entry->ll_tail, | ||
355 | ll_entry); | ||
356 | GNUNET_free (ll_entry); | ||
357 | } | ||
358 | |||
359 | |||
360 | /** | ||
361 | * Find a WaitList entry in the waiting list of a lock | ||
362 | * | ||
363 | * @param lock the lock whose wait list has to be searched | ||
364 | * @param cl_entry the ClientList entry to be searched | ||
365 | * @return the WaitList entry matching the given cl_entry; NULL if not match | ||
366 | * was found | ||
367 | */ | ||
368 | static struct WaitList * | ||
369 | lock_wl_find (const struct Lock *lock, | ||
370 | const struct ClientList *cl_entry) | ||
371 | { | ||
372 | struct WaitList *wl_entry; | ||
373 | |||
374 | for (wl_entry = lock->wl_head; | ||
375 | NULL != wl_entry; | ||
376 | wl_entry = wl_entry->next) | ||
377 | { | ||
378 | if (cl_entry == wl_entry->cl_entry) | ||
379 | return wl_entry; | ||
380 | } | ||
381 | return NULL; | ||
287 | } | 382 | } |
288 | 383 | ||
289 | 384 | ||
@@ -291,42 +386,43 @@ ll_wl_find_client (struct LockList *lock, | |||
291 | * Add a client to the wait list of given lock | 386 | * Add a client to the wait list of given lock |
292 | * | 387 | * |
293 | * @param lock the lock list entry of a lock | 388 | * @param lock the lock list entry of a lock |
294 | * @param client the client to queue for the lock's wait list | 389 | * @param cl_entry the client to queue for the lock's wait list |
295 | */ | 390 | */ |
296 | static void | 391 | static void |
297 | ll_wl_add_client (struct LockList *lock, | 392 | lock_wl_add_client (struct Lock *lock, |
298 | struct GNUNET_SERVER_Client *client) | 393 | struct ClientList *cl_entry) |
299 | { | 394 | { |
300 | struct WaitList *wl_entry; | 395 | struct WaitList *wl_entry; |
301 | 396 | ||
302 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 397 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
303 | "Adding a client to lock's wait list\n" | 398 | "Adding a client to lock's wait list (lock num: %u, domain: %s)\n", |
304 | "\t lock num: %u, domain: %s\n", | ||
305 | lock->lock_num, | 399 | lock->lock_num, |
306 | lock->domain_name); | 400 | lock->domain_name); |
307 | |||
308 | wl_entry = GNUNET_malloc (sizeof (struct WaitList)); | 401 | wl_entry = GNUNET_malloc (sizeof (struct WaitList)); |
309 | wl_entry->client = client; | 402 | wl_entry->cl_entry = cl_entry; |
310 | GNUNET_CONTAINER_DLL_insert_tail (lock->wait_list_head, | 403 | GNUNET_CONTAINER_DLL_insert_tail (lock->wl_head, |
311 | lock->wait_list_tail, | 404 | lock->wl_tail, |
312 | wl_entry); | 405 | wl_entry); |
313 | } | 406 | } |
314 | 407 | ||
315 | 408 | ||
316 | /** | 409 | /** |
317 | * Remove a client from the wait list of the given lock | 410 | * Remove an entry from the wait list of the given lock |
318 | * | 411 | * |
319 | * @param lock the lock list entry of the lock | 412 | * @param lock the lock |
320 | * @param wl_client the wait list entry to be removed | 413 | * @param wl_entry the wait list entry to be removed |
321 | */ | 414 | */ |
322 | static void | 415 | static void |
323 | ll_wl_remove_client (struct LockList *lock, | 416 | lock_wl_remove (struct Lock *lock, |
324 | struct WaitList *wl_client) | 417 | struct WaitList *wl_entry) |
325 | { | 418 | { |
326 | GNUNET_CONTAINER_DLL_remove (lock->wait_list_head, | 419 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
327 | lock->wait_list_tail, | 420 | "Removing client from wait list of lock with num: %u, domain: %s\n", |
328 | wl_client); | 421 | lock->lock_num, lock->domain_name); |
329 | GNUNET_free (wl_client); | 422 | GNUNET_CONTAINER_DLL_remove (lock->wl_head, |
423 | lock->wl_tail, | ||
424 | wl_entry); | ||
425 | GNUNET_free (wl_entry); | ||
330 | } | 426 | } |
331 | 427 | ||
332 | 428 | ||
@@ -334,9 +430,7 @@ ll_wl_remove_client (struct LockList *lock, | |||
334 | * Search for a client in the client list | 430 | * Search for a client in the client list |
335 | * | 431 | * |
336 | * @param client the client to be searched for | 432 | * @param client the client to be searched for |
337 | * @param ret will be pointing to the matched list entry (if there is a match); | 433 | * @return the ClientList entry; NULL if the client is not found |
338 | * else to the tail of the client list | ||
339 | * @return GNUNET_YES if the client is present; GNUNET_NO if not | ||
340 | */ | 434 | */ |
341 | static struct ClientList * | 435 | static struct ClientList * |
342 | cl_find_client (const struct GNUNET_SERVER_Client *client) | 436 | cl_find_client (const struct GNUNET_SERVER_Client *client) |
@@ -344,8 +438,8 @@ cl_find_client (const struct GNUNET_SERVER_Client *client) | |||
344 | struct ClientList *current; | 438 | struct ClientList *current; |
345 | 439 | ||
346 | for (current = cl_head; NULL != current; current = current->next) | 440 | for (current = cl_head; NULL != current; current = current->next) |
347 | if (client == current->client) | 441 | if (client == current->client) |
348 | return current; | 442 | return current; |
349 | return NULL; | 443 | return NULL; |
350 | } | 444 | } |
351 | 445 | ||
@@ -354,39 +448,40 @@ cl_find_client (const struct GNUNET_SERVER_Client *client) | |||
354 | * Append a client to the client list | 448 | * Append a client to the client list |
355 | * | 449 | * |
356 | * @param client the client to be appended to the list | 450 | * @param client the client to be appended to the list |
451 | * @return the client list entry which is added to the client list | ||
357 | */ | 452 | */ |
358 | static void | 453 | static struct ClientList * |
359 | cl_add_client (struct GNUNET_SERVER_Client *client) | 454 | cl_add_client (struct GNUNET_SERVER_Client *client) |
360 | { | 455 | { |
361 | struct ClientList *new_client; | 456 | struct ClientList *new_client; |
362 | 457 | ||
363 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 458 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
364 | "Adding a client to the client list\n"); | 459 | "Adding a client to the client list\n"); |
365 | |||
366 | new_client = GNUNET_malloc (sizeof (struct ClientList)); | 460 | new_client = GNUNET_malloc (sizeof (struct ClientList)); |
367 | GNUNET_SERVER_client_keep (client); | 461 | GNUNET_SERVER_client_keep (client); |
368 | new_client->client = client; | 462 | new_client->client = client; |
369 | GNUNET_CONTAINER_DLL_insert_tail (cl_head, | 463 | GNUNET_CONTAINER_DLL_insert_tail (cl_head, |
370 | cl_tail, | 464 | cl_tail, |
371 | new_client); | 465 | new_client); |
466 | return new_client; | ||
372 | } | 467 | } |
373 | 468 | ||
374 | 469 | ||
375 | /** | 470 | /** |
376 | * Delete the given client from the client list | 471 | * Delete the given client from the client list |
377 | * | 472 | * |
378 | * @param client the client list entry to delete | 473 | * @param cl_entry the client list entry to delete |
379 | */ | 474 | */ |
380 | static void | 475 | static void |
381 | cl_remove_client (struct ClientList *client) | 476 | cl_remove_client (struct ClientList *cl_entry) |
382 | { | 477 | { |
383 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 478 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
384 | "Removing a client from the client list\n"); | 479 | "Removing a client from the client list\n"); |
385 | GNUNET_SERVER_client_drop (client->client); | 480 | GNUNET_SERVER_client_drop (cl_entry->client); |
386 | GNUNET_CONTAINER_DLL_remove (cl_head, | 481 | GNUNET_CONTAINER_DLL_remove (cl_head, |
387 | cl_tail, | 482 | cl_tail, |
388 | client); | 483 | cl_entry); |
389 | GNUNET_free (client); | 484 | GNUNET_free (cl_entry); |
390 | } | 485 | } |
391 | 486 | ||
392 | 487 | ||
@@ -405,10 +500,10 @@ transmit_notify (void *cls, size_t size, void *buf) | |||
405 | uint16_t msg_size; | 500 | uint16_t msg_size; |
406 | 501 | ||
407 | if ((0 == size) || (NULL == buf)) | 502 | if ((0 == size) || (NULL == buf)) |
408 | { | 503 | { |
409 | /* FIXME: Timed out -- requeue? */ | 504 | /* FIXME: Timed out -- requeue? */ |
410 | return 0; | 505 | return 0; |
411 | } | 506 | } |
412 | msg_size = ntohs (msg->header.size); | 507 | msg_size = ntohs (msg->header.size); |
413 | GNUNET_assert (size >= msg_size); | 508 | GNUNET_assert (size >= msg_size); |
414 | memcpy (buf, msg, msg_size); | 509 | memcpy (buf, msg, msg_size); |
@@ -442,6 +537,9 @@ send_success_msg (struct GNUNET_SERVER_Client *client, | |||
442 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS); | 537 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS); |
443 | reply->lock = htonl (lock_num); | 538 | reply->lock = htonl (lock_num); |
444 | strncpy ((char *) &reply[1], domain_name, domain_name_len); | 539 | strncpy ((char *) &reply[1], domain_name, domain_name_len); |
540 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
541 | "Sending SUCCESS message for lock with num: %u, domain: %s\n", | ||
542 | lock_num, domain_name); | ||
445 | GNUNET_SERVER_notify_transmit_ready (client, | 543 | GNUNET_SERVER_notify_transmit_ready (client, |
446 | reply_size, | 544 | reply_size, |
447 | TIMEOUT, | 545 | TIMEOUT, |
@@ -464,74 +562,84 @@ handle_acquire (void *cls, | |||
464 | { | 562 | { |
465 | const struct GNUNET_LOCKMANAGER_Message *request; | 563 | const struct GNUNET_LOCKMANAGER_Message *request; |
466 | const char *domain_name; | 564 | const char *domain_name; |
467 | struct LockList *ll_entry; | 565 | struct Lock *lock; |
566 | struct ClientList *cl_entry; | ||
468 | uint32_t lock_num; | 567 | uint32_t lock_num; |
568 | uint16_t msize; | ||
469 | 569 | ||
470 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 570 | msize = htons (message->size); |
471 | "Received an ACQUIRE message\n"); | 571 | if (msize <= sizeof (struct GNUNET_LOCKMANAGER_Message)) |
472 | /* Check if the client is in client list */ | 572 | { |
473 | if (NULL == cl_find_client (client)) | 573 | GNUNET_break (0); |
474 | cl_add_client (client); | 574 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
475 | 575 | return; | |
576 | } | ||
476 | request = (struct GNUNET_LOCKMANAGER_Message *) message; | 577 | request = (struct GNUNET_LOCKMANAGER_Message *) message; |
578 | domain_name = (const char *) &request[1]; | ||
579 | msize -= sizeof (struct GNUNET_LOCKMANAGER_Message); | ||
580 | if ('\0' != domain_name[msize]) | ||
581 | { | ||
582 | GNUNET_break (0); | ||
583 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
584 | return; | ||
585 | } | ||
477 | lock_num = ntohl (request->lock); | 586 | lock_num = ntohl (request->lock); |
478 | domain_name = (char *) &request[1]; | 587 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
479 | if (NULL != (ll_entry = ll_find_lock (domain_name, | 588 | "Received an ACQUIRE message for lock num: %u domain: %s\n", |
480 | lock_num))) | 589 | lock_num, domain_name); |
481 | {/* Add client to the lock's wait list */ | 590 | if (NULL == (cl_entry = cl_find_client (client))) |
482 | ll_wl_add_client (ll_entry, client); | 591 | cl_entry = cl_add_client (client); /* Add client if not in client list */ |
483 | } | 592 | if (NULL != (lock = find_lock (domain_name,lock_num))) |
484 | else | 593 | { |
485 | { | 594 | if (lock->cl_entry == cl_entry) |
486 | ll_add_lock (client, domain_name, lock_num); | 595 | { /* Client is requesting a lock it already owns */ |
487 | send_success_msg (client, domain_name, lock_num); | 596 | GNUNET_break (0); |
597 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
598 | return; | ||
488 | } | 599 | } |
489 | 600 | lock_wl_add_client (lock, cl_entry); | |
601 | cl_ll_add_lock (cl_entry, lock); | ||
602 | } | ||
603 | else /* Lock not present */ | ||
604 | { | ||
605 | lock = add_lock (domain_name, lock_num); | ||
606 | lock->cl_entry = cl_entry; | ||
607 | cl_ll_add_lock (cl_entry, lock); | ||
608 | send_success_msg (cl_entry->client, domain_name, lock_num); | ||
609 | } | ||
490 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 610 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
491 | } | 611 | } |
492 | 612 | ||
493 | 613 | ||
494 | /** | 614 | /** |
495 | * This function gives the lock to the first client in the wait list of the | 615 | * This function gives the lock to the first client in the wait list of the |
496 | * lock. If no clients are currently waiting for this lock, the lock is | 616 | * lock. If no clients are currently waiting for this lock, the lock is then |
497 | * destroyed. | 617 | * destroyed. |
498 | * | 618 | * |
499 | * @param ll_entry the lock list entry corresponding to a lock | 619 | * @param lock the lock which has to be processed for release |
500 | */ | 620 | */ |
501 | static void | 621 | static void |
502 | process_lock_release (struct LockList *ll_entry) | 622 | process_lock_release (struct Lock *lock) |
503 | { | 623 | { |
504 | struct WaitList *wl_entry; | 624 | struct WaitList *wl_entry; |
505 | 625 | ||
506 | wl_entry = ll_entry->wait_list_head; | 626 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
627 | "Processing lock release for lock with num: %u, domain: %s\n", | ||
628 | lock->lock_num, lock->domain_name); | ||
629 | wl_entry = lock->wl_head; | ||
507 | if (NULL == wl_entry) | 630 | if (NULL == wl_entry) |
508 | { | 631 | { |
509 | ll_remove_lock (ll_entry); | 632 | remove_lock (lock); /* No clients waiting for this lock - delete */ |
510 | return; | 633 | return; |
511 | } | 634 | } |
512 | 635 | LOG (GNUNET_ERROR_TYPE_DEBUG, | |
513 | while (NULL != wl_entry) | 636 | "Giving lock to a client from wait list\n"); |
514 | { | 637 | lock->cl_entry = wl_entry->cl_entry; |
515 | ll_wl_remove_client(ll_entry, wl_entry); | 638 | cl_ll_add_lock (wl_entry->cl_entry, lock); |
516 | 639 | lock_wl_remove(lock, wl_entry); | |
517 | if (NULL == cl_find_client (wl_entry->client)) | 640 | send_success_msg (lock->cl_entry->client, |
518 | { | 641 | lock->domain_name, |
519 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 642 | lock->lock_num); |
520 | "Removing disconnected client from wait list\n"); | ||
521 | wl_entry = ll_entry->wait_list_head; | ||
522 | continue; | ||
523 | } | ||
524 | |||
525 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
526 | "Giving lock to a client from wait list\n"); | ||
527 | ll_entry->client = wl_entry->client; | ||
528 | send_success_msg (wl_entry->client, | ||
529 | ll_entry->domain_name, | ||
530 | ll_entry->lock_num); | ||
531 | return; | ||
532 | } | ||
533 | /* We ran out of clients in the wait list -- destroy lock */ | ||
534 | ll_remove_lock (ll_entry); | ||
535 | return; | 643 | return; |
536 | } | 644 | } |
537 | 645 | ||
@@ -549,31 +657,68 @@ handle_release (void *cls, | |||
549 | const struct GNUNET_MessageHeader *message) | 657 | const struct GNUNET_MessageHeader *message) |
550 | { | 658 | { |
551 | const struct GNUNET_LOCKMANAGER_Message *request; | 659 | const struct GNUNET_LOCKMANAGER_Message *request; |
552 | const char *domain_name; | 660 | struct ClientList *cl_entry; |
661 | struct WaitList *wl_entry; | ||
553 | struct LockList *ll_entry; | 662 | struct LockList *ll_entry; |
663 | const char *domain_name; | ||
664 | struct Lock *lock; | ||
554 | uint32_t lock_num; | 665 | uint32_t lock_num; |
666 | uint16_t msize; | ||
555 | 667 | ||
556 | request = (struct GNUNET_LOCKMANAGER_Message *) message; | 668 | msize = ntohs (message->size); |
669 | if (msize <= sizeof (struct GNUNET_LOCKMANAGER_Message)) | ||
670 | { | ||
671 | GNUNET_break (0); | ||
672 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
673 | return; | ||
674 | } | ||
675 | request = (const struct GNUNET_LOCKMANAGER_Message *) message; | ||
676 | domain_name = (const char *) &request[1]; | ||
677 | msize -= sizeof (struct GNUNET_LOCKMANAGER_Message); | ||
678 | if ('\0' != domain_name[msize-1]) | ||
679 | { | ||
680 | GNUNET_break (0); | ||
681 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
682 | return; | ||
683 | |||
684 | |||
685 | } | ||
557 | lock_num = ntohl (request->lock); | 686 | lock_num = ntohl (request->lock); |
558 | domain_name = (char *) &request[1]; | ||
559 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 687 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
560 | "Received a RELEASE message on lock with num: %d, domain: %s\n", | 688 | "Received RELEASE message for lock with num: %d, domain: %s\n", |
561 | lock_num, domain_name); | 689 | lock_num, domain_name); |
690 | if (NULL == (cl_entry = cl_find_client (client))) | ||
691 | { | ||
692 | GNUNET_break(0); | ||
693 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
694 | return; | ||
695 | } | ||
696 | lock = find_lock (domain_name, lock_num); | ||
697 | if(NULL == lock) | ||
698 | { | ||
699 | GNUNET_break (0); | ||
700 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
701 | return; | ||
702 | } | ||
703 | if (NULL == (ll_entry = cl_ll_find_lock (cl_entry, lock))) | ||
704 | { | ||
705 | GNUNET_break (0); | ||
706 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
707 | return; | ||
708 | } | ||
709 | cl_ll_remove_lock (cl_entry, ll_entry); | ||
710 | if (cl_entry == lock->cl_entry) | ||
711 | { | ||
712 | process_lock_release (lock); | ||
713 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
714 | return; | ||
715 | } | ||
716 | /* remove 'client' from wait list (check that it is not there...) */ | ||
717 | if (NULL != (wl_entry = lock_wl_find (lock, cl_entry))) | ||
718 | { | ||
719 | lock_wl_remove (lock, wl_entry); | ||
720 | } | ||
562 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 721 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
563 | if (NULL != (ll_entry = ll_find_lock (domain_name, lock_num))) | ||
564 | { | ||
565 | if (client != ll_entry->client) | ||
566 | { | ||
567 | GNUNET_break (0); | ||
568 | return; | ||
569 | } | ||
570 | process_lock_release (ll_entry); | ||
571 | } | ||
572 | else | ||
573 | { | ||
574 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
575 | _("Client tried to release lock that it doesn't exist\n")); | ||
576 | } | ||
577 | } | 722 | } |
578 | 723 | ||
579 | 724 | ||
@@ -594,9 +739,12 @@ client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) | |||
594 | cl_entry = cl_find_client (client); | 739 | cl_entry = cl_find_client (client); |
595 | if (NULL == cl_entry) | 740 | if (NULL == cl_entry) |
596 | return; | 741 | return; |
742 | while (NULL != (ll_entry = cl_entry->ll_head)) | ||
743 | { | ||
744 | process_lock_release (ll_entry->lock); | ||
745 | cl_ll_remove_lock (cl_entry, ll_entry); | ||
746 | } | ||
597 | cl_remove_client (cl_entry); | 747 | cl_remove_client (cl_entry); |
598 | while (NULL != (ll_entry = ll_find_lock_by_owner (client))) | ||
599 | process_lock_release (ll_entry); | ||
600 | } | 748 | } |
601 | 749 | ||
602 | 750 | ||
@@ -622,7 +770,8 @@ lockmanager_run (void *cls, | |||
622 | message_handlers); | 770 | message_handlers); |
623 | GNUNET_SERVER_disconnect_notify (server, | 771 | GNUNET_SERVER_disconnect_notify (server, |
624 | &client_disconnect_cb, | 772 | &client_disconnect_cb, |
625 | NULL); | 773 | NULL); |
774 | lock_map = GNUNET_CONTAINER_multihashmap_create (30); | ||
626 | } | 775 | } |
627 | 776 | ||
628 | 777 | ||