diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-05-09 17:33:04 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-05-09 17:33:04 +0200 |
commit | 8bb475af99260f1d107dbc8908268ae93960aa83 (patch) | |
tree | 1a7a1fc03424df841a6f977b137482439b09bc9f /src/namestore/gnunet-service-namestore.c | |
parent | 1f80a11e90ee982bffaae4685e281f75ee1c225d (diff) | |
download | gnunet-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.c | 501 |
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 | */ | ||
242 | struct 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 | */ |
217 | static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero; | 292 | static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero; |
@@ -262,6 +337,16 @@ static struct ZoneMonitor *monitor_head; | |||
262 | static struct ZoneMonitor *monitor_tail; | 337 | static struct ZoneMonitor *monitor_tail; |
263 | 338 | ||
264 | /** | 339 | /** |
340 | * Head of DLL of monitor-blocked store activities. | ||
341 | */ | ||
342 | static struct StoreActivity *sa_head; | ||
343 | |||
344 | /** | ||
345 | * Tail of DLL of monitor-blocked store activities. | ||
346 | */ | ||
347 | static struct StoreActivity *sa_tail; | ||
348 | |||
349 | /** | ||
265 | * Notification context shared by all monitors. | 350 | * Notification context shared by all monitors. |
266 | */ | 351 | */ |
267 | static struct GNUNET_NotificationContext *monitor_nc; | 352 | static 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 | */ |
336 | static void | 418 | static void |
337 | client_disconnect_cb (void *cls, | 419 | free_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 | */ | ||
388 | static void * | ||
389 | client_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 | */ | ||
828 | static void | ||
829 | continue_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 | */ | ||
906 | static void | ||
907 | client_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 | */ | ||
972 | static void * | ||
973 | client_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 | */ |
800 | struct RecordLookupContext | 993 | struct 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 | */ | ||
1779 | static void | ||
1780 | monitor_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 | */ |
1626 | static void | 1827 | static void |
1627 | monitor_next (void *cls); | 1828 | monitor_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 | */ |
1710 | static void | 1922 | static void |
1711 | monitor_next (void *cls) | 1923 | monitor_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 | ||