aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/gnunet-service-namestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/gnunet-service-namestore.c')
-rw-r--r--src/namestore/gnunet-service-namestore.c825
1 files changed, 594 insertions, 231 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index f47c8776b..2d6020552 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -1,21 +1,19 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014 GNUnet e.V. 3 Copyright (C) 2012, 2013, 2014, 2018 GNUnet e.V.
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 it
6 it under the terms of the GNU General Public License as published 6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation; either version 3, or (at your 7 by the Free Software Foundation, either version 3 of the License,
8 option) any later version. 8 or (at your 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 Affero 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 Affero General Public License
16 along with GNUnet; see the file COPYING. If not, write to the 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/ 17*/
20 18
21/** 19/**
@@ -23,6 +21,9 @@
23 * @brief namestore for the GNUnet naming system 21 * @brief namestore for the GNUnet naming system
24 * @author Matthias Wachs 22 * @author Matthias Wachs
25 * @author Christian Grothoff 23 * @author Christian Grothoff
24 *
25 * TODO:
26 * - run testcases, make sure everything works!
26 */ 27 */
27#include "platform.h" 28#include "platform.h"
28#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
@@ -37,6 +38,11 @@
37 38
38#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) 39#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
39 40
41/**
42 * If a monitor takes more than 1 minute to process an event, print a warning.
43 */
44#define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES
45
40 46
41/** 47/**
42 * A namestore client 48 * A namestore client
@@ -161,6 +167,16 @@ struct ZoneMonitor
161 struct GNUNET_SCHEDULER_Task *task; 167 struct GNUNET_SCHEDULER_Task *task;
162 168
163 /** 169 /**
170 * Task to warn about slow monitors.
171 */
172 struct GNUNET_SCHEDULER_Task *sa_wait_warning;
173
174 /**
175 * Since when are we blocked on this monitor?
176 */
177 struct GNUNET_TIME_Absolute sa_waiting_start;
178
179 /**
164 * Last sequence number in the zone iteration used to address next 180 * Last sequence number in the zone iteration used to address next
165 * result of the zone iteration in the store 181 * result of the zone iteration in the store
166 * 182 *
@@ -175,6 +191,27 @@ struct ZoneMonitor
175 */ 191 */
176 uint64_t limit; 192 uint64_t limit;
177 193
194 /**
195 * How many more requests may we receive from the iterator
196 * before it is at the limit we gave it? Will be below or
197 * equal to @e limit. The effective limit for monitor
198 * events is thus @e iteration_cnt - @e limit!
199 */
200 uint64_t iteration_cnt;
201
202 /**
203 * Are we (still) in the initial iteration pass?
204 */
205 int in_first_iteration;
206
207 /**
208 * Is there a store activity waiting for this monitor? We only raise the
209 * flag when it happens and search the DLL for the store activity when we
210 * had a limit increase. If we cannot find any waiting store activity at
211 * that time, we clear the flag again.
212 */
213 int sa_waiting;
214
178}; 215};
179 216
180 217
@@ -212,6 +249,46 @@ struct CacheOperation
212 249
213 250
214/** 251/**
252 * Information for an ongoing #handle_record_store() operation.
253 * Needed as we may wait for monitors to be ready for the notification.
254 */
255struct StoreActivity
256{
257 /**
258 * Kept in a DLL.
259 */
260 struct StoreActivity *next;
261
262 /**
263 * Kept in a DLL.
264 */
265 struct StoreActivity *prev;
266
267 /**
268 * Which client triggered the store activity?
269 */
270 struct NamestoreClient *nc;
271
272 /**
273 * Copy of the original store message (as data fields in @e rd will
274 * point into it!).
275 */
276 const struct RecordStoreMessage *rsm;
277
278 /**
279 * Next zone monitor that still needs to be notified about this PUT.
280 */
281 struct ZoneMonitor *zm_pos;
282
283 /**
284 * Label nicely canonicalized (lower case).
285 */
286 char *conv_name;
287
288};
289
290
291/**
215 * Public key of all zeros. 292 * Public key of all zeros.
216 */ 293 */
217static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero; 294static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero;
@@ -262,6 +339,16 @@ static struct ZoneMonitor *monitor_head;
262static struct ZoneMonitor *monitor_tail; 339static struct ZoneMonitor *monitor_tail;
263 340
264/** 341/**
342 * Head of DLL of monitor-blocked store activities.
343 */
344static struct StoreActivity *sa_head;
345
346/**
347 * Tail of DLL of monitor-blocked store activities.
348 */
349static struct StoreActivity *sa_tail;
350
351/**
265 * Notification context shared by all monitors. 352 * Notification context shared by all monitors.
266 */ 353 */
267static struct GNUNET_NotificationContext *monitor_nc; 354static struct GNUNET_NotificationContext *monitor_nc;
@@ -326,80 +413,18 @@ cleanup_task (void *cls)
326 413
327 414
328/** 415/**
329 * Called whenever a client is disconnected. 416 * Release memory used by @a sa.
330 * Frees our resources associated with that client.
331 * 417 *
332 * @param cls closure 418 * @param sa activity to free
333 * @param client identification of the client
334 * @param app_ctx the `struct NamestoreClient` of @a client
335 */ 419 */
336static void 420static void
337client_disconnect_cb (void *cls, 421free_store_activity (struct StoreActivity *sa)
338 struct GNUNET_SERVICE_Client *client,
339 void *app_ctx)
340{
341 struct NamestoreClient *nc = app_ctx;
342 struct ZoneIteration *no;
343 struct ZoneMonitor *zm;
344 struct CacheOperation *cop;
345
346 (void) cls;
347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
348 "Client %p disconnected\n",
349 client);
350 for (zm = monitor_head; NULL != zm; zm = zm->next)
351 {
352 if (nc == zm->nc)
353 {
354 GNUNET_CONTAINER_DLL_remove (monitor_head,
355 monitor_tail,
356 zm);
357 if (NULL != zm->task)
358 {
359 GNUNET_SCHEDULER_cancel (zm->task);
360 zm->task = NULL;
361 }
362 GNUNET_free (zm);
363 break;
364 }
365 }
366 while (NULL != (no = nc->op_head))
367 {
368 GNUNET_CONTAINER_DLL_remove (nc->op_head,
369 nc->op_tail,
370 no);
371 GNUNET_free (no);
372 }
373 for (cop = cop_head; NULL != cop; cop = cop->next)
374 if (nc == cop->nc)
375 cop->nc = NULL;
376 GNUNET_free (nc);
377}
378
379
380/**
381 * Add a client to our list of active clients.
382 *
383 * @param cls NULL
384 * @param client client to add
385 * @param mq message queue for @a client
386 * @return internal namestore client structure for this client
387 */
388static void *
389client_connect_cb (void *cls,
390 struct GNUNET_SERVICE_Client *client,
391 struct GNUNET_MQ_Handle *mq)
392{ 422{
393 struct NamestoreClient *nc; 423 GNUNET_CONTAINER_DLL_remove (sa_head,
394 424 sa_tail,
395 (void) cls; 425 sa);
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 426 GNUNET_free (sa->conv_name);
397 "Client %p connected\n", 427 GNUNET_free (sa);
398 client);
399 nc = GNUNET_new (struct NamestoreClient);
400 nc->client = client;
401 nc->mq = mq;
402 return nc;
403} 428}
404 429
405 430
@@ -509,51 +534,63 @@ merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd,
509 uint64_t latest_expiration; 534 uint64_t latest_expiration;
510 size_t req; 535 size_t req;
511 char *data; 536 char *data;
512 int record_offset;
513 size_t data_offset; 537 size_t data_offset;
538 struct GNUNET_GNSRECORD_Data *target;
514 539
515 (*rdc_res) = 1 + rd2_length; 540 (*rdc_res) = 1 + rd2_length;
516 if (0 == 1 + rd2_length) 541 if (0 == 1 + rd2_length)
517 { 542 {
543 GNUNET_break (0);
518 (*rd_res) = NULL; 544 (*rd_res) = NULL;
519 return; 545 return;
520 } 546 }
521 req = 0; 547 req = sizeof (struct GNUNET_GNSRECORD_Data) + nick_rd->data_size;
522 for (unsigned int c=0; c< 1; c++) 548 for (unsigned int i=0; i<rd2_length; i++)
523 req += sizeof (struct GNUNET_GNSRECORD_Data) + nick_rd[c].data_size; 549 {
524 for (unsigned int c=0; c< rd2_length; c++) 550 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
525 req += sizeof (struct GNUNET_GNSRECORD_Data) + rd2[c].data_size; 551
526 (*rd_res) = GNUNET_malloc (req); 552 if (req + sizeof (struct GNUNET_GNSRECORD_Data) + orig->data_size < req)
527 data = (char *) &(*rd_res)[1 + rd2_length]; 553 {
554 GNUNET_break (0);
555 (*rd_res) = NULL;
556 return;
557 }
558 req += sizeof (struct GNUNET_GNSRECORD_Data) + orig->data_size;
559 }
560 target = GNUNET_malloc (req);
561 (*rd_res) = target;
562 data = (char *) &target[1 + rd2_length];
528 data_offset = 0; 563 data_offset = 0;
529 latest_expiration = 0; 564 latest_expiration = 0;
530 for (unsigned int c=0; c< rd2_length; c++) 565 for (unsigned int i=0;i<rd2_length;i++)
531 { 566 {
532 if (0 != (rd2[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) 567 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
568
569 if (0 != (orig->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
533 { 570 {
534 if ((GNUNET_TIME_absolute_get().abs_value_us + rd2[c].expiration_time) > 571 if ((GNUNET_TIME_absolute_get().abs_value_us + orig->expiration_time) >
535 latest_expiration) 572 latest_expiration)
536 latest_expiration = rd2[c].expiration_time; 573 latest_expiration = orig->expiration_time;
537 } 574 }
538 else if (rd2[c].expiration_time > latest_expiration) 575 else if (orig->expiration_time > latest_expiration)
539 latest_expiration = rd2[c].expiration_time; 576 latest_expiration = orig->expiration_time;
540 (*rd_res)[c] = rd2[c]; 577 target[i] = *orig;
541 (*rd_res)[c].data = (void *) &data[data_offset]; 578 target[i].data = (void *) &data[data_offset];
542 GNUNET_memcpy ((void *) (*rd_res)[c].data, 579 GNUNET_memcpy (&data[data_offset],
543 rd2[c].data, 580 orig->data,
544 rd2[c].data_size); 581 orig->data_size);
545 data_offset += (*rd_res)[c].data_size; 582 data_offset += orig->data_size;
546 } 583 }
547 /* append nick */ 584 /* append nick */
548 record_offset = rd2_length; 585 target[rd2_length] = *nick_rd;
549 (*rd_res)[record_offset] = *nick_rd; 586 target[rd2_length].expiration_time = latest_expiration;
550 (*rd_res)[record_offset].expiration_time = latest_expiration; 587 target[rd2_length].data = (void *) &data[data_offset];
551 (*rd_res)[record_offset].data = (void *) &data[data_offset]; 588 GNUNET_memcpy (&data[data_offset],
552 GNUNET_memcpy ((void *) (*rd_res)[record_offset].data,
553 nick_rd->data, 589 nick_rd->data,
554 nick_rd->data_size); 590 nick_rd->data_size);
555 data_offset += (*rd_res)[record_offset].data_size; 591 data_offset += nick_rd->data_size;
556 GNUNET_assert (req == (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset); 592 GNUNET_assert (req ==
593 (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset);
557} 594}
558 595
559 596
@@ -582,11 +619,16 @@ send_lookup_response (struct NamestoreClient *nc,
582 struct GNUNET_GNSRECORD_Data *res; 619 struct GNUNET_GNSRECORD_Data *res;
583 unsigned int res_count; 620 unsigned int res_count;
584 size_t name_len; 621 size_t name_len;
585 size_t rd_ser_len; 622 ssize_t rd_ser_len;
586 char *name_tmp; 623 char *name_tmp;
587 char *rd_ser; 624 char *rd_ser;
588 625
589 nick = get_nick_record (zone_key); 626 nick = get_nick_record (zone_key);
627
628 GNUNET_assert (-1 !=
629 GNUNET_GNSRECORD_records_get_size (rd_count,
630 rd));
631
590 if ( (NULL != nick) && 632 if ( (NULL != nick) &&
591 (0 != strcmp (name, 633 (0 != strcmp (name,
592 GNUNET_GNS_EMPTY_LABEL_AT))) 634 GNUNET_GNS_EMPTY_LABEL_AT)))
@@ -605,25 +647,44 @@ send_lookup_response (struct NamestoreClient *nc,
605 res = (struct GNUNET_GNSRECORD_Data *) rd; 647 res = (struct GNUNET_GNSRECORD_Data *) rd;
606 } 648 }
607 649
650 GNUNET_assert (-1 !=
651 GNUNET_GNSRECORD_records_get_size (res_count,
652 res));
653
654
608 name_len = strlen (name) + 1; 655 name_len = strlen (name) + 1;
609 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res); 656 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count,
657 res);
658 if (rd_ser_len < 0)
659 {
660 GNUNET_break (0);
661 GNUNET_SERVICE_client_drop (nc->client);
662 return;
663 }
664 if (rd_ser_len >= UINT16_MAX - name_len - sizeof (*zir_msg))
665 {
666 GNUNET_break (0);
667 GNUNET_SERVICE_client_drop (nc->client);
668 return;
669 }
610 env = GNUNET_MQ_msg_extra (zir_msg, 670 env = GNUNET_MQ_msg_extra (zir_msg,
611 name_len + rd_ser_len, 671 name_len + rd_ser_len,
612 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT); 672 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
613 zir_msg->gns_header.r_id = htonl (request_id); 673 zir_msg->gns_header.r_id = htonl (request_id);
614 zir_msg->name_len = htons (name_len); 674 zir_msg->name_len = htons (name_len);
615 zir_msg->rd_count = htons (res_count); 675 zir_msg->rd_count = htons (res_count);
616 zir_msg->rd_len = htons (rd_ser_len); 676 zir_msg->rd_len = htons ((uint16_t) rd_ser_len);
617 zir_msg->private_key = *zone_key; 677 zir_msg->private_key = *zone_key;
618 name_tmp = (char *) &zir_msg[1]; 678 name_tmp = (char *) &zir_msg[1];
619 GNUNET_memcpy (name_tmp, 679 GNUNET_memcpy (name_tmp,
620 name, 680 name,
621 name_len); 681 name_len);
622 rd_ser = &name_tmp[name_len]; 682 rd_ser = &name_tmp[name_len];
623 GNUNET_GNSRECORD_records_serialize (res_count, 683 GNUNET_assert (rd_ser_len ==
624 res, 684 GNUNET_GNSRECORD_records_serialize (res_count,
625 rd_ser_len, 685 res,
626 rd_ser); 686 rd_ser_len,
687 rd_ser));
627 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 688 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
628 "Sending RECORD_RESULT message with %u records\n", 689 "Sending RECORD_RESULT message with %u records\n",
629 res_count); 690 res_count);
@@ -655,6 +716,10 @@ send_store_response (struct NamestoreClient *nc,
655 716
656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
657 "Sending RECORD_STORE_RESPONSE message\n"); 718 "Sending RECORD_STORE_RESPONSE message\n");
719 GNUNET_STATISTICS_update (statistics,
720 "Store requests completed",
721 1,
722 GNUNET_NO);
658 env = GNUNET_MQ_msg (rcr_msg, 723 env = GNUNET_MQ_msg (rcr_msg,
659 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE); 724 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
660 rcr_msg->gns_header.r_id = htonl (rid); 725 rcr_msg->gns_header.r_id = htonl (rid);
@@ -795,6 +860,206 @@ refresh_block (struct NamestoreClient *nc,
795 860
796 861
797/** 862/**
863 * Print a warning that one of our monitors is no longer reacting.
864 *
865 * @param cls a `struct ZoneMonitor` to warn about
866 */
867static void
868warn_monitor_slow (void *cls)
869{
870 struct ZoneMonitor *zm = cls;
871
872 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
873 "No response from monitor since %s\n",
874 GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
875 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
876 &warn_monitor_slow,
877 zm);
878}
879
880
881/**
882 * Continue processing the @a sa.
883 *
884 * @param sa store activity to process
885 */
886static void
887continue_store_activity (struct StoreActivity *sa)
888{
889 const struct RecordStoreMessage *rp_msg = sa->rsm;
890 unsigned int rd_count;
891 size_t name_len;
892 size_t rd_ser_len;
893 uint32_t rid;
894 const char *name_tmp;
895 const char *rd_ser;
896
897 rid = ntohl (rp_msg->gns_header.r_id);
898 name_len = ntohs (rp_msg->name_len);
899 rd_count = ntohs (rp_msg->rd_count);
900 rd_ser_len = ntohs (rp_msg->rd_len);
901 name_tmp = (const char *) &rp_msg[1];
902 rd_ser = &name_tmp[name_len];
903 {
904 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
905
906 /* We did this before, must succeed again */
907 GNUNET_assert (GNUNET_OK ==
908 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
909 rd_ser,
910 rd_count,
911 rd));
912
913 for (struct ZoneMonitor *zm = sa->zm_pos;
914 NULL != zm;
915 zm = sa->zm_pos)
916 {
917 if ( (0 != memcmp (&rp_msg->private_key,
918 &zm->zone,
919 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) &&
920 (0 != memcmp (&zm->zone,
921 &zero,
922 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
923 sa->zm_pos = zm->next; /* not interesting to this monitor */
924 if (zm->limit == zm->iteration_cnt)
925 {
926 zm->sa_waiting = GNUNET_YES;
927 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
928 if (NULL != zm->sa_wait_warning)
929 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
930 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
931 &warn_monitor_slow,
932 zm);
933 return; /* blocked on zone monitor */
934 }
935 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
936 "Notifying monitor about changes under label `%s'\n",
937 sa->conv_name);
938 zm->limit--;
939 send_lookup_response (zm->nc,
940 0,
941 &rp_msg->private_key,
942 sa->conv_name,
943 rd_count,
944 rd);
945 sa->zm_pos = zm->next;
946 }
947 /* great, done with the monitors, unpack (again) for refresh_block operation */
948 refresh_block (sa->nc,
949 rid,
950 &rp_msg->private_key,
951 sa->conv_name,
952 rd_count,
953 rd);
954 }
955 GNUNET_SERVICE_client_continue (sa->nc->client);
956 free_store_activity (sa);
957}
958
959
960/**
961 * Called whenever a client is disconnected.
962 * Frees our resources associated with that client.
963 *
964 * @param cls closure
965 * @param client identification of the client
966 * @param app_ctx the `struct NamestoreClient` of @a client
967 */
968static void
969client_disconnect_cb (void *cls,
970 struct GNUNET_SERVICE_Client *client,
971 void *app_ctx)
972{
973 struct NamestoreClient *nc = app_ctx;
974 struct ZoneIteration *no;
975 struct CacheOperation *cop;
976
977 (void) cls;
978 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
979 "Client %p disconnected\n",
980 client);
981 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
982 {
983 struct StoreActivity *san;
984
985 if (nc != zm->nc)
986 continue;
987 GNUNET_CONTAINER_DLL_remove (monitor_head,
988 monitor_tail,
989 zm);
990 if (NULL != zm->task)
991 {
992 GNUNET_SCHEDULER_cancel (zm->task);
993 zm->task = NULL;
994 }
995 if (NULL != zm->sa_wait_warning)
996 {
997 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
998 zm->sa_wait_warning = NULL;
999 }
1000 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
1001 {
1002 san = sa->next;
1003 if (zm == sa->zm_pos)
1004 {
1005 sa->zm_pos = zm->next;
1006 /* this may free sa */
1007 continue_store_activity (sa);
1008 }
1009 }
1010 GNUNET_free (zm);
1011 break;
1012 }
1013 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
1014 {
1015 if (sa->nc == nc)
1016 {
1017 /* this may free sa */
1018 free_store_activity (sa);
1019 break; /* there can only be one per nc */
1020 }
1021 }
1022 while (NULL != (no = nc->op_head))
1023 {
1024 GNUNET_CONTAINER_DLL_remove (nc->op_head,
1025 nc->op_tail,
1026 no);
1027 GNUNET_free (no);
1028 }
1029 for (cop = cop_head; NULL != cop; cop = cop->next)
1030 if (nc == cop->nc)
1031 cop->nc = NULL;
1032 GNUNET_free (nc);
1033}
1034
1035
1036/**
1037 * Add a client to our list of active clients.
1038 *
1039 * @param cls NULL
1040 * @param client client to add
1041 * @param mq message queue for @a client
1042 * @return internal namestore client structure for this client
1043 */
1044static void *
1045client_connect_cb (void *cls,
1046 struct GNUNET_SERVICE_Client *client,
1047 struct GNUNET_MQ_Handle *mq)
1048{
1049 struct NamestoreClient *nc;
1050
1051 (void) cls;
1052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1053 "Client %p connected\n",
1054 client);
1055 nc = GNUNET_new (struct NamestoreClient);
1056 nc->client = client;
1057 nc->mq = mq;
1058 return nc;
1059}
1060
1061
1062/**
798 * Closure for #lookup_it(). 1063 * Closure for #lookup_it().
799 */ 1064 */
800struct RecordLookupContext 1065struct RecordLookupContext
@@ -828,12 +1093,13 @@ struct RecordLookupContext
828 /** 1093 /**
829 * FIXME. 1094 * FIXME.
830 */ 1095 */
831 size_t rd_ser_len; 1096 ssize_t rd_ser_len;
832}; 1097};
833 1098
834 1099
835/** 1100/**
836 * FIXME. 1101 * FIXME.
1102 *
837 * @param seq sequence number of the record 1103 * @param seq sequence number of the record
838 */ 1104 */
839static void 1105static void
@@ -845,60 +1111,93 @@ lookup_it (void *cls,
845 const struct GNUNET_GNSRECORD_Data *rd) 1111 const struct GNUNET_GNSRECORD_Data *rd)
846{ 1112{
847 struct RecordLookupContext *rlc = cls; 1113 struct RecordLookupContext *rlc = cls;
848 struct GNUNET_GNSRECORD_Data *rd_res;
849 unsigned int rdc_res;
850 1114
851 (void) private_key; 1115 (void) private_key;
852 (void) seq; 1116 (void) seq;
853 if (0 == strcmp (label, 1117 if (0 != strcmp (label,
854 rlc->label)) 1118 rlc->label))
1119 return;
1120 rlc->found = GNUNET_YES;
1121 if (0 == rd_count)
855 { 1122 {
856 rlc->found = GNUNET_YES; 1123 rlc->rd_ser_len = 0;
857 if (0 != rd_count) 1124 rlc->res_rd_count = 0;
1125 rlc->res_rd = NULL;
1126 return;
1127 }
1128 if ( (NULL != rlc->nick) &&
1129 (0 != strcmp (label,
1130 GNUNET_GNS_EMPTY_LABEL_AT)) )
1131 {
1132 /* Merge */
1133 struct GNUNET_GNSRECORD_Data *rd_res;
1134 unsigned int rdc_res;
1135
1136 rd_res = NULL;
1137 rdc_res = 0;
1138 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
1139 merge_with_nick_records (rlc->nick,
1140 rd_count,
1141 rd,
1142 &rdc_res,
1143 &rd_res);
1144 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res,
1145 rd_res);
1146 if (rlc->rd_ser_len < 0)
858 { 1147 {
859 if ( (NULL != rlc->nick) && 1148 GNUNET_break (0);
860 (0 != strcmp (label, 1149 GNUNET_free (rd_res);
861 GNUNET_GNS_EMPTY_LABEL_AT)) ) 1150 rlc->found = GNUNET_NO;
862 { 1151 rlc->rd_ser_len = 0;
863 /* Merge */ 1152 return;
864 rd_res = NULL; 1153 }
865 rdc_res = 0; 1154 rlc->res_rd_count = rdc_res;
866 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; 1155 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
867 merge_with_nick_records (rlc->nick, 1156 if (rlc->rd_ser_len !=
868 rd_count,
869 rd,
870 &rdc_res,
871 &rd_res);
872 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res,
873 rd_res);
874 rlc->res_rd_count = rdc_res;
875 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
876 GNUNET_GNSRECORD_records_serialize (rdc_res, 1157 GNUNET_GNSRECORD_records_serialize (rdc_res,
877 rd_res, 1158 rd_res,
878 rlc->rd_ser_len, 1159 rlc->rd_ser_len,
879 rlc->res_rd); 1160 rlc->res_rd))
880 1161 {
881 GNUNET_free (rd_res); 1162 GNUNET_break (0);
882 GNUNET_free (rlc->nick); 1163 GNUNET_free (rlc->res_rd);
883 rlc->nick = NULL; 1164 rlc->res_rd = NULL;
884 } 1165 rlc->res_rd_count = 0;
885 else 1166 rlc->rd_ser_len = 0;
886 { 1167 GNUNET_free (rd_res);
887 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, 1168 rlc->found = GNUNET_NO;
888 rd); 1169 return;
889 rlc->res_rd_count = rd_count; 1170 }
890 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); 1171 GNUNET_free (rd_res);
1172 GNUNET_free (rlc->nick);
1173 rlc->nick = NULL;
1174 }
1175 else
1176 {
1177 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1178 rd);
1179 if (rlc->rd_ser_len < 0)
1180 {
1181 GNUNET_break (0);
1182 rlc->found = GNUNET_NO;
1183 rlc->rd_ser_len = 0;
1184 return;
1185 }
1186 rlc->res_rd_count = rd_count;
1187 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1188 if (rlc->rd_ser_len !=
891 GNUNET_GNSRECORD_records_serialize (rd_count, 1189 GNUNET_GNSRECORD_records_serialize (rd_count,
892 rd, 1190 rd,
893 rlc->rd_ser_len, 1191 rlc->rd_ser_len,
894 rlc->res_rd); 1192 rlc->res_rd))
895 }
896 }
897 else
898 { 1193 {
899 rlc->rd_ser_len = 0; 1194 GNUNET_break (0);
900 rlc->res_rd_count = 0; 1195 GNUNET_free (rlc->res_rd);
901 rlc->res_rd = NULL; 1196 rlc->res_rd = NULL;
1197 rlc->res_rd_count = 0;
1198 rlc->rd_ser_len = 0;
1199 rlc->found = GNUNET_NO;
1200 return;
902 } 1201 }
903 } 1202 }
904} 1203}
@@ -1073,7 +1372,7 @@ handle_record_store (void *cls,
1073 const char *rd_ser; 1372 const char *rd_ser;
1074 unsigned int rd_count; 1373 unsigned int rd_count;
1075 int res; 1374 int res;
1076 struct ZoneMonitor *zm; 1375 struct StoreActivity *sa;
1077 1376
1078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1079 "Received NAMESTORE_RECORD_STORE message\n"); 1378 "Received NAMESTORE_RECORD_STORE message\n");
@@ -1085,7 +1384,7 @@ handle_record_store (void *cls,
1085 name_tmp = (const char *) &rp_msg[1]; 1384 name_tmp = (const char *) &rp_msg[1];
1086 rd_ser = &name_tmp[name_len]; 1385 rd_ser = &name_tmp[name_len];
1087 { 1386 {
1088 struct GNUNET_GNSRECORD_Data rd[rd_count]; 1387 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
1089 1388
1090 if (GNUNET_OK != 1389 if (GNUNET_OK !=
1091 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, 1390 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
@@ -1108,6 +1407,10 @@ handle_record_store (void *cls,
1108 GNUNET_SERVICE_client_drop (nc->client); 1407 GNUNET_SERVICE_client_drop (nc->client);
1109 return; 1408 return;
1110 } 1409 }
1410 GNUNET_STATISTICS_update (statistics,
1411 "Well-formed store requests received",
1412 1,
1413 GNUNET_NO);
1111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1414 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1112 "Creating %u records for name `%s'\n", 1415 "Creating %u records for name `%s'\n",
1113 (unsigned int) rd_count, 1416 (unsigned int) rd_count,
@@ -1128,11 +1431,11 @@ handle_record_store (void *cls,
1128 } 1431 }
1129 else 1432 else
1130 { 1433 {
1131 struct GNUNET_GNSRECORD_Data rd_clean[rd_count];
1132 unsigned int rd_clean_off;
1133
1134 /* remove "NICK" records, unless this is for the 1434 /* remove "NICK" records, unless this is for the
1135 #GNUNET_GNS_EMPTY_LABEL_AT label */ 1435 #GNUNET_GNS_EMPTY_LABEL_AT label */
1436 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL(rd_count)];
1437 unsigned int rd_clean_off;
1438
1136 rd_clean_off = 0; 1439 rd_clean_off = 0;
1137 for (unsigned int i=0;i<rd_count;i++) 1440 for (unsigned int i=0;i<rd_count;i++)
1138 { 1441 {
@@ -1147,59 +1450,33 @@ handle_record_store (void *cls,
1147 conv_name, 1450 conv_name,
1148 rd_clean_off, 1451 rd_clean_off,
1149 rd_clean); 1452 rd_clean);
1150 if (GNUNET_OK == res)
1151 {
1152 for (zm = monitor_head; NULL != zm; zm = zm->next)
1153 {
1154 if ( (0 == memcmp (&rp_msg->private_key,
1155 &zm->zone,
1156 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) ||
1157 (0 == memcmp (&zm->zone,
1158 &zero,
1159 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
1160 {
1161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1162 "Notifying monitor about changes under label `%s'\n",
1163 conv_name);
1164 send_lookup_response (zm->nc,
1165 0,
1166 &rp_msg->private_key,
1167 conv_name,
1168 rd_count, rd);
1169 }
1170 else
1171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1172 "Monitor is for another zone\n");
1173 }
1174 if (NULL == monitor_head)
1175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1176 "No monitors active\n");
1177 }
1178 else
1179 {
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1181 "Error storing record: %d\n",
1182 res);
1183 }
1184 } 1453 }
1185 if (GNUNET_OK == res) 1454
1455 if (GNUNET_OK != res)
1186 { 1456 {
1187 refresh_block (nc, 1457 /* store not successful, not need to tell monitors */
1188 rid, 1458 send_store_response (nc,
1189 &rp_msg->private_key, 1459 res,
1190 conv_name, 1460 rid);
1191 rd_count,
1192 rd);
1193 GNUNET_SERVICE_client_continue (nc->client); 1461 GNUNET_SERVICE_client_continue (nc->client);
1194 GNUNET_free (conv_name); 1462 GNUNET_free (conv_name);
1195 return; 1463 return;
1196 } 1464 }
1197 GNUNET_free (conv_name); 1465
1466 sa = GNUNET_malloc (sizeof (struct StoreActivity) +
1467 ntohs (rp_msg->gns_header.header.size));
1468 GNUNET_CONTAINER_DLL_insert (sa_head,
1469 sa_tail,
1470 sa);
1471 sa->nc = nc;
1472 sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1473 GNUNET_memcpy (&sa[1],
1474 rp_msg,
1475 ntohs (rp_msg->gns_header.header.size));
1476 sa->zm_pos = monitor_head;
1477 sa->conv_name = conv_name;
1478 continue_store_activity (sa);
1198 } 1479 }
1199 send_store_response (nc,
1200 res,
1201 rid);
1202 GNUNET_SERVICE_client_continue (nc->client);
1203} 1480}
1204 1481
1205 1482
@@ -1251,7 +1528,7 @@ handle_zone_to_name_it (void *cls,
1251 struct ZoneToNameResponseMessage *ztnr_msg; 1528 struct ZoneToNameResponseMessage *ztnr_msg;
1252 int16_t res; 1529 int16_t res;
1253 size_t name_len; 1530 size_t name_len;
1254 size_t rd_ser_len; 1531 ssize_t rd_ser_len;
1255 size_t msg_size; 1532 size_t msg_size;
1256 char *name_tmp; 1533 char *name_tmp;
1257 char *rd_tmp; 1534 char *rd_tmp;
@@ -1262,7 +1539,14 @@ handle_zone_to_name_it (void *cls,
1262 name); 1539 name);
1263 res = GNUNET_YES; 1540 res = GNUNET_YES;
1264 name_len = (NULL == name) ? 0 : strlen (name) + 1; 1541 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1265 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); 1542 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1543 rd);
1544 if (rd_ser_len < 0)
1545 {
1546 GNUNET_break (0);
1547 ztn_ctx->success = GNUNET_SYSERR;
1548 return;
1549 }
1266 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len; 1550 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1267 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE) 1551 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1268 { 1552 {
@@ -1285,10 +1569,11 @@ handle_zone_to_name_it (void *cls,
1285 name, 1569 name,
1286 name_len); 1570 name_len);
1287 rd_tmp = &name_tmp[name_len]; 1571 rd_tmp = &name_tmp[name_len];
1288 GNUNET_GNSRECORD_records_serialize (rd_count, 1572 GNUNET_assert (rd_ser_len ==
1289 rd, 1573 GNUNET_GNSRECORD_records_serialize (rd_count,
1290 rd_ser_len, 1574 rd,
1291 rd_tmp); 1575 rd_ser_len,
1576 rd_tmp));
1292 ztn_ctx->success = GNUNET_OK; 1577 ztn_ctx->success = GNUNET_OK;
1293 GNUNET_MQ_send (ztn_ctx->nc->mq, 1578 GNUNET_MQ_send (ztn_ctx->nc->mq,
1294 env); 1579 env);
@@ -1311,8 +1596,7 @@ handle_zone_to_name (void *cls,
1311 struct ZoneToNameResponseMessage *ztnr_msg; 1596 struct ZoneToNameResponseMessage *ztnr_msg;
1312 1597
1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1314 "Received `%s' message\n", 1599 "Received ZONE_TO_NAME message\n");
1315 "ZONE_TO_NAME");
1316 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id); 1600 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1317 ztn_ctx.nc = nc; 1601 ztn_ctx.nc = nc;
1318 ztn_ctx.success = GNUNET_NO; 1602 ztn_ctx.success = GNUNET_NO;
@@ -1601,6 +1885,46 @@ handle_iteration_next (void *cls,
1601 1885
1602 1886
1603/** 1887/**
1888 * Function called when the monitor is ready for more data, and we
1889 * should thus unblock PUT operations that were blocked on the
1890 * monitor not being ready.
1891 */
1892static void
1893monitor_unblock (struct ZoneMonitor *zm)
1894{
1895 struct StoreActivity *sa = sa_head;
1896
1897 while ( (NULL != sa) &&
1898 (zm->limit > zm->iteration_cnt) )
1899 {
1900 struct StoreActivity *sn = sa->next;
1901
1902 if (sa->zm_pos == zm)
1903 continue_store_activity (sa);
1904 sa = sn;
1905 }
1906 if (zm->limit > zm->iteration_cnt)
1907 {
1908 zm->sa_waiting = GNUNET_NO;
1909 if (NULL != zm->sa_wait_warning)
1910 {
1911 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1912 zm->sa_wait_warning = NULL;
1913 }
1914 }
1915 else if (GNUNET_YES == zm->sa_waiting)
1916 {
1917 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1918 if (NULL != zm->sa_wait_warning)
1919 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1920 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1921 &warn_monitor_slow,
1922 zm);
1923 }
1924}
1925
1926
1927/**
1604 * Send 'sync' message to zone monitor, we're now in sync. 1928 * Send 'sync' message to zone monitor, we're now in sync.
1605 * 1929 *
1606 * @param zm monitor that is now in sync 1930 * @param zm monitor that is now in sync
@@ -1615,16 +1939,22 @@ monitor_sync (struct ZoneMonitor *zm)
1615 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC); 1939 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
1616 GNUNET_MQ_send (zm->nc->mq, 1940 GNUNET_MQ_send (zm->nc->mq,
1617 env); 1941 env);
1942 /* mark iteration done */
1943 zm->in_first_iteration = GNUNET_NO;
1944 zm->iteration_cnt = 0;
1945 if ( (zm->limit > 0) &&
1946 (zm->sa_waiting) )
1947 monitor_unblock (zm);
1618} 1948}
1619 1949
1620 1950
1621/** 1951/**
1622 * Obtain the next datum during the zone monitor's zone intiial iteration. 1952 * Obtain the next datum during the zone monitor's zone initial iteration.
1623 * 1953 *
1624 * @param cls zone monitor that does its initial iteration 1954 * @param cls zone monitor that does its initial iteration
1625 */ 1955 */
1626static void 1956static void
1627monitor_next (void *cls); 1957monitor_iteration_next (void *cls);
1628 1958
1629 1959
1630/** 1960/**
@@ -1658,14 +1988,23 @@ monitor_iterate_cb (void *cls,
1658 "Monitor notifications sent", 1988 "Monitor notifications sent",
1659 1, 1989 1,
1660 GNUNET_NO); 1990 GNUNET_NO);
1991 zm->limit--;
1992 zm->iteration_cnt--;
1661 send_lookup_response (zm->nc, 1993 send_lookup_response (zm->nc,
1662 0, 1994 0,
1663 zone_key, 1995 zone_key,
1664 name, 1996 name,
1665 rd_count, 1997 rd_count,
1666 rd); 1998 rd);
1667 zm->task = GNUNET_SCHEDULER_add_now (&monitor_next, 1999 if ( (0 == zm->iteration_cnt) &&
1668 zm); 2000 (0 != zm->limit) )
2001 {
2002 /* We are done with the current iteration batch, AND the
2003 client would right now accept more, so go again! */
2004 GNUNET_assert (NULL == zm->task);
2005 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2006 zm);
2007 }
1669} 2008}
1670 2009
1671 2010
@@ -1687,6 +2026,8 @@ handle_monitor_start (void *cls,
1687 zm = GNUNET_new (struct ZoneMonitor); 2026 zm = GNUNET_new (struct ZoneMonitor);
1688 zm->nc = nc; 2027 zm->nc = nc;
1689 zm->zone = zis_msg->zone; 2028 zm->zone = zis_msg->zone;
2029 zm->limit = 1;
2030 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
1690 GNUNET_CONTAINER_DLL_insert (monitor_head, 2031 GNUNET_CONTAINER_DLL_insert (monitor_head,
1691 monitor_tail, 2032 monitor_tail,
1692 zm); 2033 zm);
@@ -1694,8 +2035,8 @@ handle_monitor_start (void *cls,
1694 GNUNET_SERVICE_client_continue (nc->client); 2035 GNUNET_SERVICE_client_continue (nc->client);
1695 GNUNET_notification_context_add (monitor_nc, 2036 GNUNET_notification_context_add (monitor_nc,
1696 nc->mq); 2037 nc->mq);
1697 if (GNUNET_YES == ntohl (zis_msg->iterate_first)) 2038 if (zm->in_first_iteration)
1698 zm->task = GNUNET_SCHEDULER_add_now (&monitor_next, 2039 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
1699 zm); 2040 zm);
1700 else 2041 else
1701 monitor_sync (zm); 2042 monitor_sync (zm);
@@ -1708,12 +2049,17 @@ handle_monitor_start (void *cls,
1708 * @param cls zone monitor that does its initial iteration 2049 * @param cls zone monitor that does its initial iteration
1709 */ 2050 */
1710static void 2051static void
1711monitor_next (void *cls) 2052monitor_iteration_next (void *cls)
1712{ 2053{
1713 struct ZoneMonitor *zm = cls; 2054 struct ZoneMonitor *zm = cls;
1714 int ret; 2055 int ret;
1715 2056
1716 zm->task = NULL; 2057 zm->task = NULL;
2058 GNUNET_assert (0 == zm->iteration_cnt);
2059 if (zm->limit > 16)
2060 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2061 else
2062 zm->iteration_cnt = zm->limit; /* use it all */
1717 ret = GSN_database->iterate_records (GSN_database->cls, 2063 ret = GSN_database->iterate_records (GSN_database->cls,
1718 (0 == memcmp (&zm->zone, 2064 (0 == memcmp (&zm->zone,
1719 &zero, 2065 &zero,
@@ -1721,7 +2067,7 @@ monitor_next (void *cls)
1721 ? NULL 2067 ? NULL
1722 : &zm->zone, 2068 : &zm->zone,
1723 zm->seq, 2069 zm->seq,
1724 1, 2070 zm->iteration_cnt,
1725 &monitor_iterate_cb, 2071 &monitor_iterate_cb,
1726 zm); 2072 zm);
1727 if (GNUNET_SYSERR == ret) 2073 if (GNUNET_SYSERR == ret)
@@ -1773,13 +2119,30 @@ handle_monitor_next (void *cls,
1773 return; 2119 return;
1774 } 2120 }
1775 zm->limit += inc; 2121 zm->limit += inc;
1776#if 0 2122 if ( (zm->in_first_iteration) &&
1777 if (GNUNET_YES == ntohl (zis_msg->iterate_first)) 2123 (zm->limit == inc) )
1778 zm->task = GNUNET_SCHEDULER_add_now (&monitor_next, 2124 {
1779 zm); 2125 /* We are still iterating, and the previous iteration must
1780 else 2126 have stopped due to the client's limit, so continue it! */
1781 monitor_sync (zm); 2127 GNUNET_assert (NULL == zm->task);
1782#endif 2128 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2129 zm);
2130 }
2131 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2132 if ( (zm->limit > zm->iteration_cnt) &&
2133 (zm->sa_waiting) )
2134 {
2135 monitor_unblock (zm);
2136 }
2137 else if (GNUNET_YES == zm->sa_waiting)
2138 {
2139 if (NULL != zm->sa_wait_warning)
2140 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2141 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2142 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2143 &warn_monitor_slow,
2144 zm);
2145 }
1783} 2146}
1784 2147
1785 2148