diff options
Diffstat (limited to 'src/statistics/gnunet-service-statistics.c')
-rw-r--r-- | src/statistics/gnunet-service-statistics.c | 468 |
1 files changed, 216 insertions, 252 deletions
diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c index c506dee7b..5e0be1183 100644 --- a/src/statistics/gnunet-service-statistics.c +++ b/src/statistics/gnunet-service-statistics.c | |||
@@ -50,7 +50,7 @@ struct WatchEntry | |||
50 | struct GNUNET_SERVER_Client *client; | 50 | struct GNUNET_SERVER_Client *client; |
51 | 51 | ||
52 | uint64_t last_value; | 52 | uint64_t last_value; |
53 | 53 | ||
54 | uint32_t wid; | 54 | uint32_t wid; |
55 | 55 | ||
56 | }; | 56 | }; |
@@ -67,7 +67,7 @@ struct ClientEntry | |||
67 | struct ClientEntry *prev; | 67 | struct ClientEntry *prev; |
68 | 68 | ||
69 | struct GNUNET_SERVER_Client *client; | 69 | struct GNUNET_SERVER_Client *client; |
70 | 70 | ||
71 | uint32_t max_wid; | 71 | uint32_t max_wid; |
72 | 72 | ||
73 | }; | 73 | }; |
@@ -156,9 +156,7 @@ static uint32_t uidgen; | |||
156 | 156 | ||
157 | 157 | ||
158 | static void | 158 | static void |
159 | inject_message (void *cls, | 159 | inject_message (void *cls, void *client, const struct GNUNET_MessageHeader *msg) |
160 | void *client, | ||
161 | const struct GNUNET_MessageHeader *msg) | ||
162 | { | 160 | { |
163 | struct GNUNET_SERVER_Handle *server = cls; | 161 | struct GNUNET_SERVER_Handle *server = cls; |
164 | 162 | ||
@@ -188,37 +186,33 @@ load (struct GNUNET_SERVER_Handle *server) | |||
188 | if (fn == NULL) | 186 | if (fn == NULL) |
189 | return; | 187 | return; |
190 | if ((0 != stat (fn, &sb)) || (sb.st_size == 0)) | 188 | if ((0 != stat (fn, &sb)) || (sb.st_size == 0)) |
191 | { | 189 | { |
192 | GNUNET_free (fn); | 190 | GNUNET_free (fn); |
193 | return; | 191 | return; |
194 | } | 192 | } |
195 | fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ, | 193 | fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); |
196 | GNUNET_DISK_PERM_NONE); | ||
197 | if (!fh) | 194 | if (!fh) |
198 | { | 195 | { |
199 | GNUNET_free (fn); | 196 | GNUNET_free (fn); |
200 | return; | 197 | return; |
201 | } | 198 | } |
202 | buf = GNUNET_DISK_file_map (fh, &mh, GNUNET_DISK_MAP_TYPE_READ, sb.st_size); | 199 | buf = GNUNET_DISK_file_map (fh, &mh, GNUNET_DISK_MAP_TYPE_READ, sb.st_size); |
203 | if (NULL == buf) | 200 | if (NULL == buf) |
204 | { | 201 | { |
205 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "mmap", fn); | 202 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "mmap", fn); |
206 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh)); | 203 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh)); |
207 | GNUNET_free (fn); | 204 | GNUNET_free (fn); |
208 | return; | 205 | return; |
209 | } | 206 | } |
210 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 207 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
211 | _("Loading %llu bytes of statistics from `%s'\n"), | 208 | _("Loading %llu bytes of statistics from `%s'\n"), |
212 | (unsigned long long) sb.st_size, fn); | 209 | (unsigned long long) sb.st_size, fn); |
213 | mst = GNUNET_SERVER_mst_create (&inject_message, | 210 | mst = GNUNET_SERVER_mst_create (&inject_message, server); |
214 | server); | ||
215 | GNUNET_break (GNUNET_OK == | 211 | GNUNET_break (GNUNET_OK == |
216 | GNUNET_SERVER_mst_receive (mst, | 212 | GNUNET_SERVER_mst_receive (mst, |
217 | NULL, | 213 | NULL, |
218 | buf, | 214 | buf, |
219 | sb.st_size, | 215 | sb.st_size, GNUNET_YES, GNUNET_NO)); |
220 | GNUNET_YES, | ||
221 | GNUNET_NO)); | ||
222 | GNUNET_SERVER_mst_destroy (mst); | 216 | GNUNET_SERVER_mst_destroy (mst); |
223 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_unmap (mh)); | 217 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_unmap (mh)); |
224 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh)); | 218 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh)); |
@@ -229,7 +223,7 @@ load (struct GNUNET_SERVER_Handle *server) | |||
229 | * Write persistent statistics to disk. | 223 | * Write persistent statistics to disk. |
230 | */ | 224 | */ |
231 | static void | 225 | static void |
232 | save () | 226 | save () |
233 | { | 227 | { |
234 | struct StatsEntry *pos; | 228 | struct StatsEntry *pos; |
235 | char *fn; | 229 | char *fn; |
@@ -242,36 +236,37 @@ save () | |||
242 | "statistics", "statistics.data", NULL); | 236 | "statistics", "statistics.data", NULL); |
243 | if (fn != NULL) | 237 | if (fn != NULL) |
244 | fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_WRITE | 238 | fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_WRITE |
245 | | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_TRUNCATE, | 239 | | GNUNET_DISK_OPEN_CREATE | |
246 | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); | 240 | GNUNET_DISK_OPEN_TRUNCATE, |
241 | GNUNET_DISK_PERM_USER_READ | | ||
242 | GNUNET_DISK_PERM_USER_WRITE); | ||
247 | total = 0; | 243 | total = 0; |
248 | while (NULL != (pos = start)) | 244 | while (NULL != (pos = start)) |
245 | { | ||
246 | start = pos->next; | ||
247 | if ((pos->persistent) && (NULL != fh)) | ||
249 | { | 248 | { |
250 | start = pos->next; | 249 | size = htons (pos->msg->header.size); |
251 | if ((pos->persistent) && (NULL != fh)) | 250 | if (size != GNUNET_DISK_file_write (fh, pos->msg, size)) |
252 | { | 251 | { |
253 | size = htons (pos->msg->header.size); | 252 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn); |
254 | if (size != GNUNET_DISK_file_write (fh, pos->msg, size)) | 253 | GNUNET_DISK_file_close (fh); |
255 | { | 254 | fh = NULL; |
256 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | 255 | } |
257 | "write", fn); | ||
258 | GNUNET_DISK_file_close (fh); | ||
259 | fh = NULL; | ||
260 | } | ||
261 | else | ||
262 | total += size; | ||
263 | } | ||
264 | GNUNET_free (pos); | ||
265 | } | ||
266 | if (NULL != fh) | ||
267 | { | ||
268 | GNUNET_DISK_file_close (fh); | ||
269 | if (total == 0) | ||
270 | GNUNET_break (0 == UNLINK (fn)); | ||
271 | else | 256 | else |
272 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 257 | total += size; |
273 | _("Wrote %llu bytes of statistics to `%s'\n"), total, fn); | ||
274 | } | 258 | } |
259 | GNUNET_free (pos); | ||
260 | } | ||
261 | if (NULL != fh) | ||
262 | { | ||
263 | GNUNET_DISK_file_close (fh); | ||
264 | if (total == 0) | ||
265 | GNUNET_break (0 == UNLINK (fn)); | ||
266 | else | ||
267 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
268 | _("Wrote %llu bytes of statistics to `%s'\n"), total, fn); | ||
269 | } | ||
275 | GNUNET_free_non_null (fn); | 270 | GNUNET_free_non_null (fn); |
276 | } | 271 | } |
277 | 272 | ||
@@ -280,15 +275,14 @@ save () | |||
280 | * Transmit the given stats value. | 275 | * Transmit the given stats value. |
281 | */ | 276 | */ |
282 | static void | 277 | static void |
283 | transmit (struct GNUNET_SERVER_Client *client, | 278 | transmit (struct GNUNET_SERVER_Client *client, const struct StatsEntry *e) |
284 | const struct StatsEntry *e) | ||
285 | { | 279 | { |
286 | struct GNUNET_STATISTICS_ReplyMessage *m; | 280 | struct GNUNET_STATISTICS_ReplyMessage *m; |
287 | size_t size; | 281 | size_t size; |
288 | 282 | ||
289 | size = | 283 | size = |
290 | sizeof (struct GNUNET_STATISTICS_ReplyMessage) + strlen (e->service) + 1 + | 284 | sizeof (struct GNUNET_STATISTICS_ReplyMessage) + strlen (e->service) + 1 + |
291 | strlen (e->name) + 1; | 285 | strlen (e->name) + 1; |
292 | GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); | 286 | GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); |
293 | m = GNUNET_malloc (size); | 287 | m = GNUNET_malloc (size); |
294 | m->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_VALUE); | 288 | m->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_VALUE); |
@@ -304,10 +298,10 @@ transmit (struct GNUNET_SERVER_Client *client, | |||
304 | #if DEBUG_STATISTICS | 298 | #if DEBUG_STATISTICS |
305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
306 | "Transmitting value for `%s:%s' (%d): %llu\n", | 300 | "Transmitting value for `%s:%s' (%d): %llu\n", |
307 | e->service, e->name, | 301 | e->service, e->name, e->persistent, e->value); |
308 | e->persistent, e->value); | ||
309 | #endif | 302 | #endif |
310 | GNUNET_SERVER_notification_context_unicast (nc, client, &m->header, GNUNET_NO); | 303 | GNUNET_SERVER_notification_context_unicast (nc, client, &m->header, |
304 | GNUNET_NO); | ||
311 | GNUNET_free (m); | 305 | GNUNET_free (m); |
312 | } | 306 | } |
313 | 307 | ||
@@ -320,7 +314,7 @@ matches (const struct StatsEntry *e, const char *service, const char *name) | |||
320 | { | 314 | { |
321 | return ((0 == strlen (service)) || | 315 | return ((0 == strlen (service)) || |
322 | (0 == strcmp (service, e->service))) | 316 | (0 == strcmp (service, e->service))) |
323 | && ((0 == strlen (name)) || (0 == strcmp (name, e->name))); | 317 | && ((0 == strlen (name)) || (0 == strcmp (name, e->name))); |
324 | } | 318 | } |
325 | 319 | ||
326 | 320 | ||
@@ -332,19 +326,16 @@ make_client_entry (struct GNUNET_SERVER_Client *client) | |||
332 | GNUNET_assert (client != NULL); | 326 | GNUNET_assert (client != NULL); |
333 | ce = client_head; | 327 | ce = client_head; |
334 | while (ce != NULL) | 328 | while (ce != NULL) |
335 | { | 329 | { |
336 | if (ce->client == client) | 330 | if (ce->client == client) |
337 | return ce; | 331 | return ce; |
338 | ce = ce->next; | 332 | ce = ce->next; |
339 | } | 333 | } |
340 | ce = GNUNET_malloc (sizeof (struct ClientEntry)); | 334 | ce = GNUNET_malloc (sizeof (struct ClientEntry)); |
341 | ce->client = client; | 335 | ce->client = client; |
342 | GNUNET_SERVER_client_keep (client); | 336 | GNUNET_SERVER_client_keep (client); |
343 | GNUNET_CONTAINER_DLL_insert (client_head, | 337 | GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ce); |
344 | client_tail, | 338 | GNUNET_SERVER_notification_context_add (nc, client); |
345 | ce); | ||
346 | GNUNET_SERVER_notification_context_add (nc, | ||
347 | client); | ||
348 | return ce; | 339 | return ce; |
349 | } | 340 | } |
350 | 341 | ||
@@ -374,11 +365,11 @@ handle_get (void *cls, | |||
374 | size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); | 365 | size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); |
375 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], | 366 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], |
376 | size, 2, &service, &name)) | 367 | size, 2, &service, &name)) |
377 | { | 368 | { |
378 | GNUNET_break (0); | 369 | GNUNET_break (0); |
379 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 370 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
380 | return; | 371 | return; |
381 | } | 372 | } |
382 | #if DEBUG_STATISTICS | 373 | #if DEBUG_STATISTICS |
383 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 374 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
384 | "Received request for statistics on `%s:%s'\n", | 375 | "Received request for statistics on `%s:%s'\n", |
@@ -386,19 +377,15 @@ handle_get (void *cls, | |||
386 | #endif | 377 | #endif |
387 | pos = start; | 378 | pos = start; |
388 | while (pos != NULL) | 379 | while (pos != NULL) |
389 | { | 380 | { |
390 | if (matches (pos, service, name)) | 381 | if (matches (pos, service, name)) |
391 | transmit (client, pos); | 382 | transmit (client, pos); |
392 | pos = pos->next; | 383 | pos = pos->next; |
393 | } | 384 | } |
394 | end.size = htons (sizeof (struct GNUNET_MessageHeader)); | 385 | end.size = htons (sizeof (struct GNUNET_MessageHeader)); |
395 | end.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_END); | 386 | end.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_END); |
396 | GNUNET_SERVER_notification_context_unicast (nc, | 387 | GNUNET_SERVER_notification_context_unicast (nc, client, &end, GNUNET_NO); |
397 | client, | 388 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
398 | &end, | ||
399 | GNUNET_NO); | ||
400 | GNUNET_SERVER_receive_done (client, | ||
401 | GNUNET_OK); | ||
402 | } | 389 | } |
403 | 390 | ||
404 | 391 | ||
@@ -410,23 +397,23 @@ notify_change (struct StatsEntry *se) | |||
410 | 397 | ||
411 | pos = se->we_head; | 398 | pos = se->we_head; |
412 | while (pos != NULL) | 399 | while (pos != NULL) |
400 | { | ||
401 | if (pos->last_value != se->value) | ||
413 | { | 402 | { |
414 | if (pos->last_value != se->value) | 403 | wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE); |
415 | { | 404 | wvm.header.size = |
416 | wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE); | 405 | htons (sizeof (struct GNUNET_STATISTICS_WatchValueMessage)); |
417 | wvm.header.size = htons (sizeof (struct GNUNET_STATISTICS_WatchValueMessage)); | 406 | wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_PERSIST_BIT : 0); |
418 | wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_PERSIST_BIT : 0); | 407 | wvm.wid = htonl (pos->wid); |
419 | wvm.wid = htonl (pos->wid); | 408 | wvm.reserved = htonl (0); |
420 | wvm.reserved = htonl (0); | 409 | wvm.value = GNUNET_htonll (se->value); |
421 | wvm.value = GNUNET_htonll (se->value); | 410 | GNUNET_SERVER_notification_context_unicast (nc, |
422 | GNUNET_SERVER_notification_context_unicast (nc, | 411 | pos->client, |
423 | pos->client, | 412 | &wvm.header, GNUNET_NO); |
424 | &wvm.header, | 413 | pos->last_value = se->value; |
425 | GNUNET_NO); | ||
426 | pos->last_value = se->value; | ||
427 | } | ||
428 | pos = pos->next; | ||
429 | } | 414 | } |
415 | pos = pos->next; | ||
416 | } | ||
430 | } | 417 | } |
431 | 418 | ||
432 | /** | 419 | /** |
@@ -457,81 +444,77 @@ handle_set (void *cls, | |||
457 | make_client_entry (client); | 444 | make_client_entry (client); |
458 | msize = ntohs (message->size); | 445 | msize = ntohs (message->size); |
459 | if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage)) | 446 | if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage)) |
460 | { | 447 | { |
461 | GNUNET_break (0); | 448 | GNUNET_break (0); |
462 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 449 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
463 | return; | 450 | return; |
464 | } | 451 | } |
465 | size = msize - sizeof (struct GNUNET_STATISTICS_SetMessage); | 452 | size = msize - sizeof (struct GNUNET_STATISTICS_SetMessage); |
466 | msg = (const struct GNUNET_STATISTICS_SetMessage *) message; | 453 | msg = (const struct GNUNET_STATISTICS_SetMessage *) message; |
467 | 454 | ||
468 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1], | 455 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1], |
469 | size, 2, &service, &name)) | 456 | size, 2, &service, &name)) |
470 | { | 457 | { |
471 | GNUNET_break (0); | 458 | GNUNET_break (0); |
472 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 459 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
473 | return; | 460 | return; |
474 | } | 461 | } |
475 | flags = ntohl (msg->flags); | 462 | flags = ntohl (msg->flags); |
476 | value = GNUNET_ntohll (msg->value); | 463 | value = GNUNET_ntohll (msg->value); |
477 | #if DEBUG_STATISTICS | 464 | #if DEBUG_STATISTICS |
478 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 465 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
479 | "Received request to update statistic on `%s:%s' (%u) to/by %llu\n", | 466 | "Received request to update statistic on `%s:%s' (%u) to/by %llu\n", |
480 | service, name, | 467 | service, name, (unsigned int) flags, (unsigned long long) value); |
481 | (unsigned int) flags, | ||
482 | (unsigned long long) value); | ||
483 | #endif | 468 | #endif |
484 | pos = start; | 469 | pos = start; |
485 | prev = NULL; | 470 | prev = NULL; |
486 | while (pos != NULL) | 471 | while (pos != NULL) |
472 | { | ||
473 | if (matches (pos, service, name)) | ||
487 | { | 474 | { |
488 | if (matches (pos, service, name)) | 475 | if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) |
476 | { | ||
477 | changed = (pos->value != value); | ||
478 | pos->value = value; | ||
479 | } | ||
480 | else | ||
481 | { | ||
482 | delta = (int64_t) value; | ||
483 | if ((delta < 0) && (pos->value < -delta)) | ||
484 | { | ||
485 | changed = (pos->value != 0); | ||
486 | pos->value = 0; | ||
487 | } | ||
488 | else | ||
489 | { | 489 | { |
490 | if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) | 490 | changed = (delta != 0); |
491 | { | 491 | GNUNET_break ((delta <= 0) || (pos->value + delta > pos->value)); |
492 | changed = (pos->value != value); | 492 | pos->value += delta; |
493 | pos->value = value; | 493 | } |
494 | } | 494 | } |
495 | else | 495 | pos->msg->value = GNUNET_htonll (pos->value); |
496 | { | 496 | pos->msg->flags = msg->flags; |
497 | delta = (int64_t) value; | 497 | pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT)); |
498 | if ((delta < 0) && (pos->value < -delta)) | 498 | if (prev != NULL) |
499 | { | 499 | { |
500 | changed = (pos->value != 0); | 500 | /* move to front for faster setting next time! */ |
501 | pos->value = 0; | 501 | prev->next = pos->next; |
502 | } | 502 | pos->next = start; |
503 | else | 503 | start = pos; |
504 | { | 504 | } |
505 | changed = (delta != 0); | ||
506 | GNUNET_break ((delta <= 0) || | ||
507 | (pos->value + delta > pos->value)); | ||
508 | pos->value += delta; | ||
509 | } | ||
510 | } | ||
511 | pos->msg->value = GNUNET_htonll (pos->value); | ||
512 | pos->msg->flags = msg->flags; | ||
513 | pos->persistent = | ||
514 | (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT)); | ||
515 | if (prev != NULL) | ||
516 | { | ||
517 | /* move to front for faster setting next time! */ | ||
518 | prev->next = pos->next; | ||
519 | pos->next = start; | ||
520 | start = pos; | ||
521 | } | ||
522 | #if DEBUG_STATISTICS | 505 | #if DEBUG_STATISTICS |
523 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 506 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
524 | "Statistic `%s:%s' updated to value %llu.\n", | 507 | "Statistic `%s:%s' updated to value %llu.\n", |
525 | service, name, pos->value); | 508 | service, name, pos->value); |
526 | #endif | 509 | #endif |
527 | if (changed) | 510 | if (changed) |
528 | notify_change (pos); | 511 | notify_change (pos); |
529 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 512 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
530 | return; | 513 | return; |
531 | } | ||
532 | prev = pos; | ||
533 | pos = pos->next; | ||
534 | } | 514 | } |
515 | prev = pos; | ||
516 | pos = pos->next; | ||
517 | } | ||
535 | pos = GNUNET_malloc (sizeof (struct StatsEntry) + msize); | 518 | pos = GNUNET_malloc (sizeof (struct StatsEntry) + msize); |
536 | pos->next = start; | 519 | pos->next = start; |
537 | if (((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) || | 520 | if (((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) || |
@@ -563,8 +546,8 @@ handle_set (void *cls, | |||
563 | */ | 546 | */ |
564 | static void | 547 | static void |
565 | handle_watch (void *cls, | 548 | handle_watch (void *cls, |
566 | struct GNUNET_SERVER_Client *client, | 549 | struct GNUNET_SERVER_Client *client, |
567 | const struct GNUNET_MessageHeader *message) | 550 | const struct GNUNET_MessageHeader *message) |
568 | { | 551 | { |
569 | char *service; | 552 | char *service; |
570 | char *name; | 553 | char *name; |
@@ -578,19 +561,19 @@ handle_watch (void *cls, | |||
578 | ce = make_client_entry (client); | 561 | ce = make_client_entry (client); |
579 | msize = ntohs (message->size); | 562 | msize = ntohs (message->size); |
580 | if (msize < sizeof (struct GNUNET_MessageHeader)) | 563 | if (msize < sizeof (struct GNUNET_MessageHeader)) |
581 | { | 564 | { |
582 | GNUNET_break (0); | 565 | GNUNET_break (0); |
583 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 566 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
584 | return; | 567 | return; |
585 | } | 568 | } |
586 | size = msize - sizeof (struct GNUNET_MessageHeader); | 569 | size = msize - sizeof (struct GNUNET_MessageHeader); |
587 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], | 570 | if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], |
588 | size, 2, &service, &name)) | 571 | size, 2, &service, &name)) |
589 | { | 572 | { |
590 | GNUNET_break (0); | 573 | GNUNET_break (0); |
591 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 574 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
592 | return; | 575 | return; |
593 | } | 576 | } |
594 | #if DEBUG_STATISTICS | 577 | #if DEBUG_STATISTICS |
595 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 578 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
596 | "Received request to watch statistic on `%s:%s'\n", | 579 | "Received request to watch statistic on `%s:%s'\n", |
@@ -598,40 +581,36 @@ handle_watch (void *cls, | |||
598 | #endif | 581 | #endif |
599 | pos = start; | 582 | pos = start; |
600 | while (pos != NULL) | 583 | while (pos != NULL) |
601 | { | 584 | { |
602 | if (matches (pos, service, name)) | 585 | if (matches (pos, service, name)) |
603 | break; | 586 | break; |
604 | pos = pos->next; | 587 | pos = pos->next; |
605 | } | 588 | } |
606 | if (pos == NULL) | 589 | if (pos == NULL) |
607 | { | 590 | { |
608 | pos = GNUNET_malloc (sizeof (struct StatsEntry) + | 591 | pos = GNUNET_malloc (sizeof (struct StatsEntry) + |
609 | sizeof (struct GNUNET_STATISTICS_SetMessage) + | 592 | sizeof (struct GNUNET_STATISTICS_SetMessage) + size); |
610 | size); | 593 | pos->next = start; |
611 | pos->next = start; | 594 | pos->uid = uidgen++; |
612 | pos->uid = uidgen++; | 595 | pos->msg = (void *) &pos[1]; |
613 | pos->msg = (void *) &pos[1]; | 596 | pos->msg->header.size = |
614 | pos->msg->header.size = htons (sizeof (struct GNUNET_STATISTICS_SetMessage) + | 597 | htons (sizeof (struct GNUNET_STATISTICS_SetMessage) + size); |
615 | size); | 598 | pos->msg->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_SET); |
616 | pos->msg->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_SET); | 599 | pos->service = (const char *) &pos->msg[1]; |
617 | pos->service = (const char *) &pos->msg[1]; | 600 | slen = strlen (service) + 1; |
618 | slen = strlen (service) + 1; | 601 | memcpy ((void *) pos->service, service, slen); |
619 | memcpy ((void*) pos->service, service, slen); | 602 | pos->name = &pos->service[slen]; |
620 | pos->name = &pos->service[slen]; | 603 | memcpy ((void *) pos->name, name, strlen (name) + 1); |
621 | memcpy ((void*) pos->name, name, strlen (name)+1); | 604 | start = pos; |
622 | start = pos; | 605 | } |
623 | } | ||
624 | we = GNUNET_malloc (sizeof (struct WatchEntry)); | 606 | we = GNUNET_malloc (sizeof (struct WatchEntry)); |
625 | we->client = client; | 607 | we->client = client; |
626 | GNUNET_SERVER_client_keep (client); | 608 | GNUNET_SERVER_client_keep (client); |
627 | we->wid = ce->max_wid++; | 609 | we->wid = ce->max_wid++; |
628 | GNUNET_CONTAINER_DLL_insert (pos->we_head, | 610 | GNUNET_CONTAINER_DLL_insert (pos->we_head, pos->we_tail, we); |
629 | pos->we_tail, | ||
630 | we); | ||
631 | if (pos->value != 0) | 611 | if (pos->value != 0) |
632 | notify_change (pos); | 612 | notify_change (pos); |
633 | GNUNET_SERVER_receive_done (client, | 613 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
634 | GNUNET_OK); | ||
635 | } | 614 | } |
636 | 615 | ||
637 | 616 | ||
@@ -642,8 +621,7 @@ handle_watch (void *cls, | |||
642 | * @param tc unused | 621 | * @param tc unused |
643 | */ | 622 | */ |
644 | static void | 623 | static void |
645 | shutdown_task (void *cls, | 624 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
646 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
647 | { | 625 | { |
648 | struct ClientEntry *ce; | 626 | struct ClientEntry *ce; |
649 | struct WatchEntry *we; | 627 | struct WatchEntry *we; |
@@ -653,26 +631,22 @@ shutdown_task (void *cls, | |||
653 | GNUNET_SERVER_notification_context_destroy (nc); | 631 | GNUNET_SERVER_notification_context_destroy (nc); |
654 | nc = NULL; | 632 | nc = NULL; |
655 | while (NULL != (ce = client_head)) | 633 | while (NULL != (ce = client_head)) |
656 | { | 634 | { |
657 | GNUNET_SERVER_client_drop (ce->client); | 635 | GNUNET_SERVER_client_drop (ce->client); |
658 | GNUNET_CONTAINER_DLL_remove (client_head, | 636 | GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce); |
659 | client_tail, | 637 | GNUNET_free (ce); |
660 | ce); | 638 | } |
661 | GNUNET_free (ce); | ||
662 | } | ||
663 | while (NULL != (se = start)) | 639 | while (NULL != (se = start)) |
640 | { | ||
641 | start = se->next; | ||
642 | while (NULL != (we = se->we_head)) | ||
664 | { | 643 | { |
665 | start = se->next; | 644 | GNUNET_SERVER_client_drop (we->client); |
666 | while (NULL != (we = se->we_head)) | 645 | GNUNET_CONTAINER_DLL_remove (se->we_head, se->we_tail, we); |
667 | { | 646 | GNUNET_free (we); |
668 | GNUNET_SERVER_client_drop (we->client); | ||
669 | GNUNET_CONTAINER_DLL_remove (se->we_head, | ||
670 | se->we_tail, | ||
671 | we); | ||
672 | GNUNET_free (we); | ||
673 | } | ||
674 | GNUNET_free (se); | ||
675 | } | 647 | } |
648 | GNUNET_free (se); | ||
649 | } | ||
676 | } | 650 | } |
677 | 651 | ||
678 | 652 | ||
@@ -683,46 +657,40 @@ shutdown_task (void *cls, | |||
683 | * @param client identification of the client | 657 | * @param client identification of the client |
684 | */ | 658 | */ |
685 | static void | 659 | static void |
686 | handle_client_disconnect (void *cls, | 660 | handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) |
687 | struct GNUNET_SERVER_Client | ||
688 | * client) | ||
689 | { | 661 | { |
690 | struct ClientEntry *ce; | 662 | struct ClientEntry *ce; |
691 | struct WatchEntry *we; | 663 | struct WatchEntry *we; |
692 | struct WatchEntry *wen; | 664 | struct WatchEntry *wen; |
693 | struct StatsEntry *se; | 665 | struct StatsEntry *se; |
694 | 666 | ||
695 | ce = client_head; | 667 | ce = client_head; |
696 | while (NULL != ce) | 668 | while (NULL != ce) |
669 | { | ||
670 | if (ce->client == client) | ||
697 | { | 671 | { |
698 | if (ce->client == client) | 672 | GNUNET_SERVER_client_drop (ce->client); |
699 | { | 673 | GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce); |
700 | GNUNET_SERVER_client_drop (ce->client); | 674 | GNUNET_free (ce); |
701 | GNUNET_CONTAINER_DLL_remove (client_head, | 675 | break; |
702 | client_tail, | ||
703 | ce); | ||
704 | GNUNET_free (ce); | ||
705 | break; | ||
706 | } | ||
707 | ce = ce->next; | ||
708 | } | 676 | } |
677 | ce = ce->next; | ||
678 | } | ||
709 | se = start; | 679 | se = start; |
710 | while (NULL != se) | 680 | while (NULL != se) |
681 | { | ||
682 | wen = se->we_head; | ||
683 | while (NULL != (we = wen)) | ||
711 | { | 684 | { |
712 | wen = se->we_head; | 685 | wen = we->next; |
713 | while (NULL != (we = wen)) | 686 | if (we->client != client) |
714 | { | 687 | continue; |
715 | wen = we->next; | 688 | GNUNET_SERVER_client_drop (we->client); |
716 | if (we->client != client) | 689 | GNUNET_CONTAINER_DLL_remove (se->we_head, se->we_tail, we); |
717 | continue; | 690 | GNUNET_free (we); |
718 | GNUNET_SERVER_client_drop (we->client); | ||
719 | GNUNET_CONTAINER_DLL_remove (se->we_head, | ||
720 | se->we_tail, | ||
721 | we); | ||
722 | GNUNET_free (we); | ||
723 | } | ||
724 | se = se->next; | ||
725 | } | 691 | } |
692 | se = se->next; | ||
693 | } | ||
726 | } | 694 | } |
727 | 695 | ||
728 | 696 | ||
@@ -747,13 +715,10 @@ run (void *cls, | |||
747 | cfg = c; | 715 | cfg = c; |
748 | GNUNET_SERVER_add_handlers (server, handlers); | 716 | GNUNET_SERVER_add_handlers (server, handlers); |
749 | nc = GNUNET_SERVER_notification_context_create (server, 16); | 717 | nc = GNUNET_SERVER_notification_context_create (server, 16); |
750 | GNUNET_SERVER_disconnect_notify (server, | 718 | GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); |
751 | &handle_client_disconnect, | ||
752 | NULL); | ||
753 | load (server); | 719 | load (server); |
754 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | 720 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, |
755 | &shutdown_task, | 721 | &shutdown_task, NULL); |
756 | NULL); | ||
757 | } | 722 | } |
758 | 723 | ||
759 | 724 | ||
@@ -771,8 +736,7 @@ main (int argc, char *const *argv) | |||
771 | GNUNET_SERVICE_run (argc, | 736 | GNUNET_SERVICE_run (argc, |
772 | argv, | 737 | argv, |
773 | "statistics", | 738 | "statistics", |
774 | GNUNET_SERVICE_OPTION_NONE, | 739 | GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; |
775 | &run, NULL)) ? 0 : 1; | ||
776 | } | 740 | } |
777 | 741 | ||
778 | /* end of gnunet-service-statistics.c */ | 742 | /* end of gnunet-service-statistics.c */ |