aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/gnunet-service-namestore.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-05-09 17:33:04 +0200
committerChristian Grothoff <christian@grothoff.org>2018-05-09 17:33:04 +0200
commit8bb475af99260f1d107dbc8908268ae93960aa83 (patch)
tree1a7a1fc03424df841a6f977b137482439b09bc9f /src/namestore/gnunet-service-namestore.c
parent1f80a11e90ee982bffaae4685e281f75ee1c225d (diff)
downloadgnunet-8bb475af99260f1d107dbc8908268ae93960aa83.tar.gz
gnunet-8bb475af99260f1d107dbc8908268ae93960aa83.zip
implement new functions in libgnunetsq, clean up sqlite namestore plugin, implement flow control in namestore API and tests
Diffstat (limited to 'src/namestore/gnunet-service-namestore.c')
-rw-r--r--src/namestore/gnunet-service-namestore.c501
1 files changed, 362 insertions, 139 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index f47c8776b..a92b8104a 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -1,6 +1,6 @@
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
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
@@ -23,6 +23,9 @@
23 * @brief namestore for the GNUnet naming system 23 * @brief namestore for the GNUnet naming system
24 * @author Matthias Wachs 24 * @author Matthias Wachs
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 *
27 * TODO:
28 * - run testcases, make sure everything works!
26 */ 29 */
27#include "platform.h" 30#include "platform.h"
28#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
@@ -175,6 +178,27 @@ struct ZoneMonitor
175 */ 178 */
176 uint64_t limit; 179 uint64_t limit;
177 180
181 /**
182 * How many more requests may we receive from the iterator
183 * before it is at the limit we gave it? Will be below or
184 * equal to @e limit. The effective limit for monitor
185 * events is thus @e iteration_cnt - @e limit!
186 */
187 uint64_t iteration_cnt;
188
189 /**
190 * Are we (still) in the initial iteration pass?
191 */
192 int in_first_iteration;
193
194 /**
195 * Is there a store activity waiting for this monitor? We only raise the
196 * flag when it happens and search the DLL for the store activity when we
197 * had a limit increase. If we cannot find any waiting store activity at
198 * that time, we clear the flag again.
199 */
200 int sa_waiting;
201
178}; 202};
179 203
180 204
@@ -212,6 +236,57 @@ struct CacheOperation
212 236
213 237
214/** 238/**
239 * Information for an ongoing #handle_record_store() operation.
240 * Needed as we may wait for monitors to be ready for the notification.
241 */
242struct StoreActivity
243{
244 /**
245 * Kept in a DLL.
246 */
247 struct StoreActivity *next;
248
249 /**
250 * Kept in a DLL.
251 */
252 struct StoreActivity *prev;
253
254 /**
255 * Which client triggered the store activity?
256 */
257 struct NamestoreClient *nc;
258
259 /**
260 * Copy of the original store message (as data fields in @e rd will
261 * point into it!).
262 */
263 const struct RecordStoreMessage *rsm;
264
265 /**
266 * Array of record data to store (without NICK unless this is about
267 * #GNUNET_GNS_EMPTY_LABEL_AT). Length is in @e rd_count.
268 */
269 struct GNUNET_GNSRECORD_Data *rd;
270
271 /**
272 * Next zone monitor that still needs to be notified about this PUT.
273 */
274 struct ZoneMonitor *zm_pos;
275
276 /**
277 * Label nicely canonicalized (lower case).
278 */
279 char *conv_name;
280
281 /**
282 * How many records do we try to store?
283 */
284 unsigned int rd_count;
285
286};
287
288
289/**
215 * Public key of all zeros. 290 * Public key of all zeros.
216 */ 291 */
217static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero; 292static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero;
@@ -262,6 +337,16 @@ static struct ZoneMonitor *monitor_head;
262static struct ZoneMonitor *monitor_tail; 337static struct ZoneMonitor *monitor_tail;
263 338
264/** 339/**
340 * Head of DLL of monitor-blocked store activities.
341 */
342static struct StoreActivity *sa_head;
343
344/**
345 * Tail of DLL of monitor-blocked store activities.
346 */
347static struct StoreActivity *sa_tail;
348
349/**
265 * Notification context shared by all monitors. 350 * Notification context shared by all monitors.
266 */ 351 */
267static struct GNUNET_NotificationContext *monitor_nc; 352static struct GNUNET_NotificationContext *monitor_nc;
@@ -326,80 +411,21 @@ cleanup_task (void *cls)
326 411
327 412
328/** 413/**
329 * Called whenever a client is disconnected. 414 * Release memory used by @a sa.
330 * Frees our resources associated with that client.
331 * 415 *
332 * @param cls closure 416 * @param sa activity to free
333 * @param client identification of the client
334 * @param app_ctx the `struct NamestoreClient` of @a client
335 */ 417 */
336static void 418static void
337client_disconnect_cb (void *cls, 419free_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{ 420{
393 struct NamestoreClient *nc; 421 GNUNET_CONTAINER_DLL_remove (sa_head,
394 422 sa_tail,
395 (void) cls; 423 sa);
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 424 GNUNET_array_grow (sa->rd,
397 "Client %p connected\n", 425 sa->rd_count,
398 client); 426 0);
399 nc = GNUNET_new (struct NamestoreClient); 427 GNUNET_free (sa->conv_name);
400 nc->client = client; 428 GNUNET_free (sa);
401 nc->mq = mq;
402 return nc;
403} 429}
404 430
405 431
@@ -795,6 +821,173 @@ refresh_block (struct NamestoreClient *nc,
795 821
796 822
797/** 823/**
824 * Continue processing the @a sa.
825 *
826 * @param sa store activity to process
827 */
828static void
829continue_store_activity (struct StoreActivity *sa)
830{
831 const struct RecordStoreMessage *rp_msg = sa->rsm;
832
833 for (struct ZoneMonitor *zm = sa->zm_pos;
834 NULL != zm;
835 zm = sa->zm_pos)
836 {
837 if ( (0 != memcmp (&rp_msg->private_key,
838 &zm->zone,
839 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) &&
840 (0 != memcmp (&zm->zone,
841 &zero,
842 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
843 sa->zm_pos = zm->next; /* not interesting to this monitor */
844 if (zm->limit == zm->iteration_cnt)
845 {
846 zm->sa_waiting = GNUNET_YES;
847 return; /* blocked on zone monitor */
848 }
849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
850 "Notifying monitor about changes under label `%s'\n",
851 sa->conv_name);
852 zm->limit--;
853 send_lookup_response (zm->nc,
854 0,
855 &rp_msg->private_key,
856 sa->conv_name,
857 sa->rd_count,
858 sa->rd);
859 sa->zm_pos = zm->next;
860 }
861 /* great, done with the monitors, unpack (again) for refresh_block operation */
862 {
863 size_t name_len;
864 size_t rd_ser_len;
865 uint32_t rid;
866 const char *name_tmp;
867 const char *rd_ser;
868 unsigned int rd_count;
869
870 rid = ntohl (rp_msg->gns_header.r_id);
871 name_len = ntohs (rp_msg->name_len);
872 rd_count = ntohs (rp_msg->rd_count);
873 rd_ser_len = ntohs (rp_msg->rd_len);
874 name_tmp = (const char *) &rp_msg[1];
875 rd_ser = &name_tmp[name_len];
876 {
877 struct GNUNET_GNSRECORD_Data rd[rd_count];
878
879 /* We did this before, must succeed again */
880 GNUNET_assert (GNUNET_OK ==
881 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
882 rd_ser,
883 rd_count,
884 rd));
885 refresh_block (sa->nc,
886 rid,
887 &rp_msg->private_key,
888 sa->conv_name,
889 rd_count,
890 rd);
891 }
892 }
893 GNUNET_SERVICE_client_continue (sa->nc->client);
894 free_store_activity (sa);
895}
896
897
898/**
899 * Called whenever a client is disconnected.
900 * Frees our resources associated with that client.
901 *
902 * @param cls closure
903 * @param client identification of the client
904 * @param app_ctx the `struct NamestoreClient` of @a client
905 */
906static void
907client_disconnect_cb (void *cls,
908 struct GNUNET_SERVICE_Client *client,
909 void *app_ctx)
910{
911 struct NamestoreClient *nc = app_ctx;
912 struct ZoneIteration *no;
913 struct CacheOperation *cop;
914
915 (void) cls;
916 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
917 "Client %p disconnected\n",
918 client);
919 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
920 {
921 if (nc != zm->nc)
922 continue;
923 GNUNET_CONTAINER_DLL_remove (monitor_head,
924 monitor_tail,
925 zm);
926 if (NULL != zm->task)
927 {
928 GNUNET_SCHEDULER_cancel (zm->task);
929 zm->task = NULL;
930 }
931 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
932 {
933 if (zm == sa->zm_pos)
934 {
935 sa->zm_pos = zm->next;
936 continue_store_activity (sa);
937 }
938 }
939 GNUNET_free (zm);
940 break;
941 }
942 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
943 {
944 if (sa->nc == nc)
945 {
946 free_store_activity (sa);
947 break; /* there can only be one per nc */
948 }
949 }
950 while (NULL != (no = nc->op_head))
951 {
952 GNUNET_CONTAINER_DLL_remove (nc->op_head,
953 nc->op_tail,
954 no);
955 GNUNET_free (no);
956 }
957 for (cop = cop_head; NULL != cop; cop = cop->next)
958 if (nc == cop->nc)
959 cop->nc = NULL;
960 GNUNET_free (nc);
961}
962
963
964/**
965 * Add a client to our list of active clients.
966 *
967 * @param cls NULL
968 * @param client client to add
969 * @param mq message queue for @a client
970 * @return internal namestore client structure for this client
971 */
972static void *
973client_connect_cb (void *cls,
974 struct GNUNET_SERVICE_Client *client,
975 struct GNUNET_MQ_Handle *mq)
976{
977 struct NamestoreClient *nc;
978
979 (void) cls;
980 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
981 "Client %p connected\n",
982 client);
983 nc = GNUNET_new (struct NamestoreClient);
984 nc->client = client;
985 nc->mq = mq;
986 return nc;
987}
988
989
990/**
798 * Closure for #lookup_it(). 991 * Closure for #lookup_it().
799 */ 992 */
800struct RecordLookupContext 993struct RecordLookupContext
@@ -1073,7 +1266,7 @@ handle_record_store (void *cls,
1073 const char *rd_ser; 1266 const char *rd_ser;
1074 unsigned int rd_count; 1267 unsigned int rd_count;
1075 int res; 1268 int res;
1076 struct ZoneMonitor *zm; 1269 struct StoreActivity *sa;
1077 1270
1078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1079 "Received NAMESTORE_RECORD_STORE message\n"); 1272 "Received NAMESTORE_RECORD_STORE message\n");
@@ -1085,7 +1278,9 @@ handle_record_store (void *cls,
1085 name_tmp = (const char *) &rp_msg[1]; 1278 name_tmp = (const char *) &rp_msg[1];
1086 rd_ser = &name_tmp[name_len]; 1279 rd_ser = &name_tmp[name_len];
1087 { 1280 {
1088 struct GNUNET_GNSRECORD_Data rd[rd_count]; 1281 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
1282 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL(rd_count)];
1283 unsigned int rd_clean_off;
1089 1284
1090 if (GNUNET_OK != 1285 if (GNUNET_OK !=
1091 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, 1286 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
@@ -1128,9 +1323,6 @@ handle_record_store (void *cls,
1128 } 1323 }
1129 else 1324 else
1130 { 1325 {
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 1326 /* remove "NICK" records, unless this is for the
1135 #GNUNET_GNS_EMPTY_LABEL_AT label */ 1327 #GNUNET_GNS_EMPTY_LABEL_AT label */
1136 rd_clean_off = 0; 1328 rd_clean_off = 0;
@@ -1147,59 +1339,39 @@ handle_record_store (void *cls,
1147 conv_name, 1339 conv_name,
1148 rd_clean_off, 1340 rd_clean_off,
1149 rd_clean); 1341 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 } 1342 }
1185 if (GNUNET_OK == res) 1343
1344 if (GNUNET_OK != res)
1186 { 1345 {
1187 refresh_block (nc, 1346 /* store not successful, not need to tell monitors */
1188 rid, 1347 send_store_response (nc,
1189 &rp_msg->private_key, 1348 res,
1190 conv_name, 1349 rid);
1191 rd_count,
1192 rd);
1193 GNUNET_SERVICE_client_continue (nc->client); 1350 GNUNET_SERVICE_client_continue (nc->client);
1194 GNUNET_free (conv_name); 1351 GNUNET_free (conv_name);
1195 return; 1352 return;
1196 } 1353 }
1197 GNUNET_free (conv_name); 1354
1355 sa = GNUNET_malloc (sizeof (struct StoreActivity) +
1356 ntohs (rp_msg->gns_header.header.size));
1357 GNUNET_CONTAINER_DLL_insert (sa_head,
1358 sa_tail,
1359 sa);
1360 sa->nc = nc;
1361 sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1362 memcpy (&sa[1],
1363 rp_msg,
1364 ntohs (rp_msg->gns_header.header.size));
1365 sa->zm_pos = monitor_head;
1366 sa->conv_name = conv_name;
1367 GNUNET_array_grow (sa->rd,
1368 sa->rd_count,
1369 rd_clean_off);
1370 memcpy (sa->rd,
1371 rd_clean,
1372 sizeof (struct GNUNET_GNSRECORD_Data) * rd_clean_off);
1373 continue_store_activity (sa);
1198 } 1374 }
1199 send_store_response (nc,
1200 res,
1201 rid);
1202 GNUNET_SERVICE_client_continue (nc->client);
1203} 1375}
1204 1376
1205 1377
@@ -1311,8 +1483,7 @@ handle_zone_to_name (void *cls,
1311 struct ZoneToNameResponseMessage *ztnr_msg; 1483 struct ZoneToNameResponseMessage *ztnr_msg;
1312 1484
1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1314 "Received `%s' message\n", 1486 "Received ZONE_TO_NAME message\n");
1315 "ZONE_TO_NAME");
1316 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id); 1487 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1317 ztn_ctx.nc = nc; 1488 ztn_ctx.nc = nc;
1318 ztn_ctx.success = GNUNET_NO; 1489 ztn_ctx.success = GNUNET_NO;
@@ -1601,6 +1772,30 @@ handle_iteration_next (void *cls,
1601 1772
1602 1773
1603/** 1774/**
1775 * Function called when the monitor is ready for more data, and we
1776 * should thus unblock PUT operations that were blocked on the
1777 * monitor not being ready.
1778 */
1779static void
1780monitor_unblock (struct ZoneMonitor *zm)
1781{
1782 struct StoreActivity *sa = sa_head;
1783
1784 while ( (NULL != sa) &&
1785 (zm->limit > zm->iteration_cnt) )
1786 {
1787 struct StoreActivity *sn = sa->next;
1788
1789 if (sa->zm_pos == zm)
1790 continue_store_activity (sa);
1791 sa = sn;
1792 }
1793 if (zm->limit > zm->iteration_cnt)
1794 zm->sa_waiting = GNUNET_NO;
1795}
1796
1797
1798/**
1604 * Send 'sync' message to zone monitor, we're now in sync. 1799 * Send 'sync' message to zone monitor, we're now in sync.
1605 * 1800 *
1606 * @param zm monitor that is now in sync 1801 * @param zm monitor that is now in sync
@@ -1615,16 +1810,22 @@ monitor_sync (struct ZoneMonitor *zm)
1615 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC); 1810 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
1616 GNUNET_MQ_send (zm->nc->mq, 1811 GNUNET_MQ_send (zm->nc->mq,
1617 env); 1812 env);
1813 /* mark iteration done */
1814 zm->in_first_iteration = GNUNET_NO;
1815 zm->iteration_cnt = 0;
1816 if ( (zm->limit > 0) &&
1817 (zm->sa_waiting) )
1818 monitor_unblock (zm);
1618} 1819}
1619 1820
1620 1821
1621/** 1822/**
1622 * Obtain the next datum during the zone monitor's zone intiial iteration. 1823 * Obtain the next datum during the zone monitor's zone initial iteration.
1623 * 1824 *
1624 * @param cls zone monitor that does its initial iteration 1825 * @param cls zone monitor that does its initial iteration
1625 */ 1826 */
1626static void 1827static void
1627monitor_next (void *cls); 1828monitor_iteration_next (void *cls);
1628 1829
1629 1830
1630/** 1831/**
@@ -1658,14 +1859,23 @@ monitor_iterate_cb (void *cls,
1658 "Monitor notifications sent", 1859 "Monitor notifications sent",
1659 1, 1860 1,
1660 GNUNET_NO); 1861 GNUNET_NO);
1862 zm->limit--;
1863 zm->iteration_cnt--;
1661 send_lookup_response (zm->nc, 1864 send_lookup_response (zm->nc,
1662 0, 1865 0,
1663 zone_key, 1866 zone_key,
1664 name, 1867 name,
1665 rd_count, 1868 rd_count,
1666 rd); 1869 rd);
1667 zm->task = GNUNET_SCHEDULER_add_now (&monitor_next, 1870 if ( (0 == zm->iteration_cnt) &&
1668 zm); 1871 (0 != zm->limit) )
1872 {
1873 /* We are done with the current iteration batch, AND the
1874 client would right now accept more, so go again! */
1875 GNUNET_assert (NULL == zm->task);
1876 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
1877 zm);
1878 }
1669} 1879}
1670 1880
1671 1881
@@ -1687,6 +1897,8 @@ handle_monitor_start (void *cls,
1687 zm = GNUNET_new (struct ZoneMonitor); 1897 zm = GNUNET_new (struct ZoneMonitor);
1688 zm->nc = nc; 1898 zm->nc = nc;
1689 zm->zone = zis_msg->zone; 1899 zm->zone = zis_msg->zone;
1900 zm->limit = 1;
1901 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
1690 GNUNET_CONTAINER_DLL_insert (monitor_head, 1902 GNUNET_CONTAINER_DLL_insert (monitor_head,
1691 monitor_tail, 1903 monitor_tail,
1692 zm); 1904 zm);
@@ -1694,8 +1906,8 @@ handle_monitor_start (void *cls,
1694 GNUNET_SERVICE_client_continue (nc->client); 1906 GNUNET_SERVICE_client_continue (nc->client);
1695 GNUNET_notification_context_add (monitor_nc, 1907 GNUNET_notification_context_add (monitor_nc,
1696 nc->mq); 1908 nc->mq);
1697 if (GNUNET_YES == ntohl (zis_msg->iterate_first)) 1909 if (zm->in_first_iteration)
1698 zm->task = GNUNET_SCHEDULER_add_now (&monitor_next, 1910 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
1699 zm); 1911 zm);
1700 else 1912 else
1701 monitor_sync (zm); 1913 monitor_sync (zm);
@@ -1708,12 +1920,17 @@ handle_monitor_start (void *cls,
1708 * @param cls zone monitor that does its initial iteration 1920 * @param cls zone monitor that does its initial iteration
1709 */ 1921 */
1710static void 1922static void
1711monitor_next (void *cls) 1923monitor_iteration_next (void *cls)
1712{ 1924{
1713 struct ZoneMonitor *zm = cls; 1925 struct ZoneMonitor *zm = cls;
1714 int ret; 1926 int ret;
1715 1927
1716 zm->task = NULL; 1928 zm->task = NULL;
1929 GNUNET_assert (0 == zm->iteration_cnt);
1930 if (zm->limit > 16)
1931 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
1932 else
1933 zm->iteration_cnt = zm->limit; /* use it all */
1717 ret = GSN_database->iterate_records (GSN_database->cls, 1934 ret = GSN_database->iterate_records (GSN_database->cls,
1718 (0 == memcmp (&zm->zone, 1935 (0 == memcmp (&zm->zone,
1719 &zero, 1936 &zero,
@@ -1721,7 +1938,7 @@ monitor_next (void *cls)
1721 ? NULL 1938 ? NULL
1722 : &zm->zone, 1939 : &zm->zone,
1723 zm->seq, 1940 zm->seq,
1724 1, 1941 zm->iteration_cnt,
1725 &monitor_iterate_cb, 1942 &monitor_iterate_cb,
1726 zm); 1943 zm);
1727 if (GNUNET_SYSERR == ret) 1944 if (GNUNET_SYSERR == ret)
@@ -1773,13 +1990,19 @@ handle_monitor_next (void *cls,
1773 return; 1990 return;
1774 } 1991 }
1775 zm->limit += inc; 1992 zm->limit += inc;
1776#if 0 1993 if ( (zm->in_first_iteration) &&
1777 if (GNUNET_YES == ntohl (zis_msg->iterate_first)) 1994 (zm->limit == inc) )
1778 zm->task = GNUNET_SCHEDULER_add_now (&monitor_next, 1995 {
1779 zm); 1996 /* We are still iterating, and the previous iteration must
1780 else 1997 have stopped due to the client's limit, so continue it! */
1781 monitor_sync (zm); 1998 GNUNET_assert (NULL == zm->task);
1782#endif 1999 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2000 zm);
2001 }
2002 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2003 if ( (zm->limit > zm->iteration_cnt) &&
2004 (zm->sa_waiting) )
2005 monitor_unblock (zm);
1783} 2006}
1784 2007
1785 2008