aboutsummaryrefslogtreecommitdiff
path: root/src/lockmanager
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2012-05-10 15:26:19 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2012-05-10 15:26:19 +0000
commitf92e74047eaa5a949f50972fd52aabbf855e4e92 (patch)
tree5964e8d7f8b0fe6a82863a1e17230345a22f0f05 /src/lockmanager
parentab9ae5793e6bf50f53c548e2c97f102d0e002ac1 (diff)
downloadgnunet-f92e74047eaa5a949f50972fd52aabbf855e4e92.tar.gz
gnunet-f92e74047eaa5a949f50972fd52aabbf855e4e92.zip
lockmanager with new datastructure
Diffstat (limited to 'src/lockmanager')
-rw-r--r--src/lockmanager/gnunet-service-lockmanager.c607
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 */
77struct LockList 77struct 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 */
109struct 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 */
119struct ClientList 131struct 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 */
141static struct LockList *ll_head;
142
143/**
144 * Tail of the doubly linked list of the currently held locks
145 */ 163 */
146static struct LockList *ll_tail; 164static 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 */
169static struct LockList * 184static void
170ll_find_lock (const char *domain_name, 185get_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 */
193static struct LockList * 206static struct Lock *
194ll_find_lock_by_owner (const struct GNUNET_SERVER_Client *client) 207find_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 */
212static void 243static struct Lock *
213ll_add_lock (struct GNUNET_SERVER_Client *client, 244add_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 */
242static void 273static void
243ll_remove_lock (struct LockList *lock) 274remove_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 */
265static int 299static struct LockList *
266ll_wl_find_client (struct LockList *lock, 300cl_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 } 321static void
282 current_wl_entry = current_wl_entry->next; 322cl_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 */
344static void
345cl_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 */
368static struct WaitList *
369lock_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 */
296static void 391static void
297ll_wl_add_client (struct LockList *lock, 392lock_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 */
322static void 415static void
323ll_wl_remove_client (struct LockList *lock, 416lock_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 */
341static struct ClientList * 435static struct ClientList *
342cl_find_client (const struct GNUNET_SERVER_Client *client) 436cl_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 */
358static void 453static struct ClientList *
359cl_add_client (struct GNUNET_SERVER_Client *client) 454cl_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 */
380static void 475static void
381cl_remove_client (struct ClientList *client) 476cl_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 */
501static void 621static void
502process_lock_release (struct LockList *ll_entry) 622process_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