GNUnet 0.22.2
gnunet-service-zonemaster.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 2017, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
26#include "platform.h"
27#include <pthread.h>
28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h"
33
34#define LOG_STRERROR_FILE(kind, syscall, \
35 filename) GNUNET_log_from_strerror_file (kind, "util", \
36 syscall, \
37 filename)
38
39
44#define PUBLISH_OPS_PER_EXPIRATION 4
45
51#define DELTA_INTERVAL 100
52
56#define NS_BLOCK_SIZE 1000
57
61#define JOB_QUEUE_LIMIT 5000
62
67#define NAMESTORE_MONITOR_QUEUE_LIMIT 5
68
73#define INITIAL_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS
74
79#define MAXIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_relative_multiply ( \
80 GNUNET_TIME_UNIT_MINUTES, 15)
81
86#define LATE_ITERATION_SPEEDUP_FACTOR 2
87
91#define DHT_GNS_REPLICATION_LEVEL 5
92
96static pthread_t * worker;
97
101static pthread_mutex_t sign_jobs_lock;
102
106static pthread_mutex_t sign_results_lock;
107
111static pthread_cond_t sign_jobs_cond;
112
117
122
127
132
134{
135
140
145
150
155
161
166
171
175 char *label;
176
181
186
191};
192
193
199
204
209
214
215
220
225
226
231{
236
241
246
247};
248
249
254
259
264
269
274
280
285
289static unsigned int job_queue_length;
290
294static unsigned long long num_public_records;
295
299static unsigned long long last_num_public_records;
300
305static unsigned long long put_cnt;
306
315
321
327
332
338
344
352
357
362static unsigned int ns_iteration_left;
363
368
373static int cache_keys;
374
379
384
385
386static void
388{
389 if (job->block != job->block_priv)
390 GNUNET_free (job->block_priv);
391 GNUNET_free (job->block);
392 if (NULL != job->label)
393 GNUNET_free (job->label);
395}
396
397
404static void
405shutdown_task (void *cls)
406{
407 struct CacheOperation *cop;
409
410 (void) cls;
413 "Shutting down!\n");
414 if (NULL != notification_pipe)
416 if (NULL != pipe_read_task)
418 while (NULL != (cop = cop_head))
419 {
421 "Aborting incomplete namecache operation\n");
424 GNUNET_free (cop);
425 }
426 GNUNET_assert (0 == pthread_mutex_lock (&sign_jobs_lock));
427 while (NULL != (job = sign_jobs_head))
428 {
430 "Removing incomplete jobs\n");
433 free_job (job);
434 }
435 GNUNET_assert (0 == pthread_mutex_unlock (&sign_jobs_lock));
436 GNUNET_assert (0 == pthread_mutex_lock (&sign_results_lock));
437 while (NULL != (job = sign_results_head))
438 {
440 "Removing incomplete jobs\n");
442 free_job (job);
443 }
444 GNUNET_assert (0 == pthread_mutex_unlock (&sign_results_lock));
445 while (NULL != (job = dht_jobs_head))
446 {
448 "Removing incomplete jobs\n");
450 if (NULL != job->ph)
452 free_job (job);
453 }
454 if (NULL != statistics)
455 {
457 GNUNET_NO);
458 statistics = NULL;
459 }
460 if (NULL != zone_publish_task)
461 {
463 zone_publish_task = NULL;
464 }
465 if (NULL != namestore_iter)
466 {
468 namestore_iter = NULL;
469 }
470 if (NULL != zmon)
471 {
473 zmon = NULL;
474 }
475 if (NULL != namestore_handle)
476 {
478 namestore_handle = NULL;
479 }
480 if (NULL != namecache)
481 {
483 namecache = NULL;
484 }
485 if (NULL != dht_handle)
486 {
488 dht_handle = NULL;
489 }
490}
491
492
500static void
501finish_cache_operation (void *cls, int32_t success, const char *emsg)
502{
503 struct CacheOperation *cop = cls;
504
505 if (NULL != emsg)
507 _ ("Failed to replicate block in namecache: %s\n"),
508 emsg);
509 else
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
512 GNUNET_free (cop);
513}
514
515
524static void
526{
527 struct CacheOperation *cop;
528
530 {
532 "Namecache updates skipped (NC disabled)",
533 1,
534 GNUNET_NO);
535 return;
536 }
537 GNUNET_assert (NULL != block);
538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Caching block in namecache\n");
540 "Namecache updates pushed",
541 1,
542 GNUNET_NO);
543 cop = GNUNET_new (struct CacheOperation);
546 block,
548 cop);
549}
550
551
557static void
559{
560 (void) cls;
561 zone_publish_task = NULL;
567}
568
569
575static void
576publish_zone_dht_start (void *cls);
577
578
582static void
584{
585 if (0 == num_public_records)
593 "No records in namestore database.\n");
594 }
595 else
596 {
608 }
613 "Minimum relative record expiration (in μs)",
615 GNUNET_NO);
617 "Zone publication time window (in μs)",
619 GNUNET_NO);
621 "Target zone iteration velocity (μs)",
623 GNUNET_NO);
624}
625
626
634static void
635update_velocity (unsigned int cnt)
636{
638 unsigned long long pct = 0;
639
640 if (0 == cnt)
641 return;
642 /* How fast were we really? */
644 delta.rel_value_us /= cnt;
646
647 /* calculate expected frequency */
650 {
652 "Last record count was lower than current record count. Reducing interval.\n");
656 }
658 "Desired global zone iteration interval is %s/record!\n",
661 GNUNET_YES));
662
663 /* Tell statistics actual vs. desired speed */
665 "Current zone iteration velocity (μs/record)",
667 GNUNET_NO);
668 /* update "sub_delta" based on difference, taking
669 previous sub_delta into account! */
671 {
672 /* We were too fast, reduce sub_delta! */
673 struct GNUNET_TIME_Relative corr;
674
676 delta);
678 {
679 /* Reduce sub_delta by corr */
681 corr);
682 }
683 else
684 {
685 /* We're doing fine with waiting the full time, this
686 should theoretically only happen if we run at
687 infinite speed. */
689 }
690 }
693 {
694 /* We were too slow, increase sub_delta! */
695 struct GNUNET_TIME_Relative corr;
696
700 corr);
703 {
704 /* CPU overload detected, we cannot go at desired speed,
705 as this would mean using a negative delay. */
706 /* compute how much faster we would want to be for
707 the desired velocity */
709 pct = UINT64_MAX; /* desired speed is infinity ... */
710 else
715 }
716 }
718 "# dispatched jobs",
720 GNUNET_NO);
722 "% speed increase needed for target velocity",
723 pct,
724 GNUNET_NO);
726 "# records processed in current iteration",
728 GNUNET_NO);
729}
730
731
736static void
738{
739 struct GNUNET_TIME_Relative delay;
740
741 if (0 != ns_iteration_left)
742 return; /* current NAMESTORE iteration not yet done */
744 {
746 "Job queue length exceeded (%u/%u). Pausing namestore iteration.\n",
749 return;
750 }
752 put_cnt = 0;
754 sub_delta);
755 /* We delay *once* per #NS_BLOCK_SIZE, so we need to multiply the
756 per-record delay calculated so far with the #NS_BLOCK_SIZE */
758 "Current artificial NAMESTORE delay (μs/record)",
759 delay.rel_value_us,
760 GNUNET_NO);
761 delay = GNUNET_TIME_relative_multiply (delay,
763 /* make sure we do not overshoot because of the #NS_BLOCK_SIZE factor */
765 delay);
766 /* no delays on first iteration */
768 delay = GNUNET_TIME_UNIT_ZERO;
772 ,
773 NULL);
774}
775
776
777static void
779{
780
781 if (NULL == zone_publish_task)
784 {
786 {
788 "Job queue emptied (%u/%u). Resuming monitor.\n",
793 }
794 }
796 free_job (job);
797}
798
799
804static void
806{
807 struct RecordPublicationJob *job = cls;
808
810 "PUT complete; Pending jobs: %u\n", job_queue_length - 1);
811 /* When we just fall under the limit, trigger monitor/iterator again
812 * if halted. We can only safely trigger one, prefer iterator. */
815 job);
817}
818
819
830static void
832 const char *label,
833 const struct GNUNET_GNSRECORD_Data *rd,
834 unsigned int rd_count,
835 const struct GNUNET_TIME_Absolute expire)
836{
837 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
838 struct GNUNET_GNSRECORD_Block *block;
839 struct GNUNET_GNSRECORD_Block *block_priv;
840 struct GNUNET_TIME_Absolute expire_pub;
842 size_t block_size;
843 unsigned int rd_public_count = 0;
844 char *emsg;
845
846 if (GNUNET_OK !=
848 rd,
849 rd_count,
850 rd_public,
851 &rd_public_count,
852 &expire_pub,
854 &emsg))
855 {
857 "%s\n", emsg);
858 GNUNET_free (emsg);
859 }
860
863 label,
864 rd_public,
865 rd_public_count,
866 &block));
867 if (NULL == block)
868 {
869 GNUNET_break (0);
870 return; /* whoops */
871 }
872 if (rd_count != rd_public_count)
874 expire,
875 label,
876 rd,
877 rd_count,
878 &
879 block_priv));
880 else
883 GNUNET_assert (0 == pthread_mutex_lock (&sign_jobs_lock));
885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Public record count: %d\n",
886 rd_public_count);
887 job->have_public_records = (rd_public_count > 0);
888 job->block = block;
889 job->block_size = block_size;
890 job->block_priv = block_priv;
891 job->zone = *key;
892 job->label = GNUNET_strdup (label);
893 job->expire_pub = expire_pub;
895 GNUNET_assert (0 == pthread_cond_signal (&sign_jobs_cond));
896 GNUNET_assert (0 == pthread_mutex_unlock (&sign_jobs_lock));
898 "Creating job with %u record(s) for label `%s', expiration `%s'\n",
899 rd_public_count,
900 label,
903 return;
904}
905
906
907static void
908notification_pipe_cb (void *cls);
909
910static void
912{
913 struct GNUNET_HashCode query;
915 const struct GNUNET_DISK_FileHandle *np_fh;
916 char buf[100];
917 ssize_t nf_count;
918
919 pipe_read_task = NULL;
925 np_fh,
927 NULL);
928 /* empty queue */
929 nf_count = GNUNET_DISK_file_read (np_fh, buf, sizeof (buf));
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %lld notifications from pipe\n",
931 (long long) nf_count);
932 while (true)
933 {
934 GNUNET_assert (0 == pthread_mutex_lock (&sign_results_lock));
935 if (NULL == sign_results_head)
936 {
938 "No more results. Back to sleep.\n");
939 GNUNET_assert (0 == pthread_mutex_unlock (&sign_results_lock));
940 return;
941 }
944 GNUNET_assert (0 == pthread_mutex_unlock (&sign_results_lock));
946 job->label,
947 &query);
948 // It is possible that the public block size is 0 (no public blocks)
949 // Do not bother with the DHT in that case
950 if (job->have_public_records)
951 {
953 &query,
957 job->block_size,
958 job->block,
959 job->expire_pub,
961 job);
962 if (NULL == job->ph)
963 {
965 "Could not perform DHT PUT, is the DHT running?\n");
966 free_job (job);
967 return;
968 }
970 "DHT put operations initiated",
971 1,
972 GNUNET_NO);
974 "Storing record(s) for label `%s' in DHT under key %s\n",
975 job->label,
976 GNUNET_h2s (&query));
977 refresh_block (job->block_priv);
979 }
980 else
981 {
982 // Private blocks may still be available and must be updated
983 // in the cache
984 refresh_block (job->block_priv);
986 }
987 }
988}
989
990
996static void
998{
999 (void) cls;
1001 "Got disconnected from namestore database, retrying.\n");
1002 namestore_iter = NULL;
1003 /* We end up here on error/disconnect/shutdown, so potentially
1004 while a zone publish task or a DHT put is still running; hence
1005 we need to cancel those. */
1006 if (NULL != zone_publish_task)
1007 {
1009 zone_publish_task = NULL;
1010 }
1012 NULL);
1013}
1014
1015
1021static void
1023{
1024 (void) cls;
1025 /* we're done with one iteration, calculate when to do the next one */
1026 namestore_iter = NULL;
1031 /* reset for next iteration */
1035 "Zone iteration finished. Adjusted zone iteration interval to %s\n",
1038 GNUNET_YES));
1040 "Target zone iteration velocity (μs)",
1042 GNUNET_NO);
1044 "Number of public records in DHT",
1046 GNUNET_NO);
1048 if (0 == last_num_public_records)
1049 {
1053 NULL);
1054 }
1055 else
1056 {
1058 NULL);
1059 }
1060}
1061
1062
1072static void
1073handle_record (void *cls,
1074 const struct GNUNET_CRYPTO_PrivateKey *key,
1075 const char *label,
1076 unsigned int rd_count,
1077 const struct GNUNET_GNSRECORD_Data *rd,
1079{
1080 (void) cls;
1082 if (0 == rd_count)
1083 {
1085 "Record set empty, moving to next record set\n");
1087 return;
1088 }
1089 for (unsigned int i = 0; i < rd_count; i++)
1090 {
1091 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1092 {
1093 /* GNUNET_GNSRECORD_block_create will convert to absolute time;
1094 we just need to adjust our iteration frequency */
1096 GNUNET_MIN (rd[i].expiration_time,
1098 }
1099 }
1100
1101
1102 /* We got a set of records to publish */
1104 "Starting DHT PUT\n");
1105 put_cnt++;
1106 if (0 == put_cnt % DELTA_INTERVAL)
1109 label,
1110 rd,
1111 rd_count,
1112 expire);
1115}
1116
1117
1123static void
1125{
1126 (void) cls;
1127 zone_publish_task = NULL;
1129 "Full zone iterations launched",
1130 1,
1131 GNUNET_NO);
1133 "Starting DHT zone update!\n");
1134 /* start counting again */
1136 GNUNET_assert (NULL == namestore_iter);
1140 NULL, /* All zones */
1142 NULL,
1144 NULL,
1146 NULL,
1148 GNUNET_assert (NULL != namestore_iter);
1149}
1150
1151
1160static void
1162 const char *label,
1163 const struct GNUNET_GNSRECORD_Data *rd,
1164 unsigned int rd_count,
1166{
1167 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
1168 struct GNUNET_GNSRECORD_Block *block;
1169 struct GNUNET_GNSRECORD_Block *block_priv;
1170 struct GNUNET_TIME_Absolute expire_pub;
1171 struct RecordPublicationJob *job;
1172 size_t block_size;
1173 unsigned int rd_public_count = 0;
1174 char *emsg;
1175
1176 if (GNUNET_OK !=
1178 rd,
1179 rd_count,
1180 rd_public,
1181 &rd_public_count,
1182 &expire_pub,
1184 &emsg))
1185 {
1187 "%s\n", emsg);
1188 GNUNET_free (emsg);
1189 }
1190
1192 expire_pub,
1193 label,
1194 rd_public,
1195 rd_public_count,
1196 &block));
1197 if (NULL == block)
1198 {
1199 GNUNET_break (0);
1200 return; /* whoops */
1201 }
1202 if (rd_count != rd_public_count)
1204 expire,
1205 label,
1206 rd,
1207 rd_count,
1208 &
1209 block_priv));
1210 else
1211 block_priv = block;
1213 GNUNET_assert (0 == pthread_mutex_lock (&sign_jobs_lock));
1215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Public record count: %d\n",
1216 rd_public_count);
1217 job->have_public_records = (rd_public_count > 0);
1218 job->block = block;
1219 job->block_size = block_size;
1220 job->block_priv = block_priv;
1221 job->zone = *key;
1222 job->label = GNUNET_strdup (label);
1223 job->expire_pub = expire_pub;
1225 GNUNET_assert (0 == pthread_cond_signal (&sign_jobs_cond));
1226 GNUNET_assert (0 == pthread_mutex_unlock (&sign_jobs_lock));
1227}
1228
1229
1241static void
1243 const struct GNUNET_CRYPTO_PrivateKey *zone,
1244 const char *label,
1245 unsigned int rd_count,
1246 const struct GNUNET_GNSRECORD_Data *rd,
1248{
1249 (void) cls;
1251 "Namestore monitor events received",
1252 1,
1253 GNUNET_NO);
1255 "Received %u records for label `%s' via namestore monitor\n",
1256 rd_count,
1257 label);
1258 if (0 == rd_count)
1259 {
1261 1);
1262 return; /* nothing to do */
1263 }
1265 label,
1266 rd,
1267 rd_count,
1268 expire);
1271 {
1273 "Job queue length exceeded (%u/%u). Halting monitor.\n",
1277 return;
1278 }
1280 1);
1281}
1282
1283
1290static void
1292{
1293 (void) cls;
1295 "Namestore monitor errors encountered",
1296 1,
1297 GNUNET_NO);
1298}
1299
1300
1301static void*
1302sign_worker (void *cls)
1303{
1304 struct RecordPublicationJob *job;
1305 const struct GNUNET_DISK_FileHandle *fh;
1306
1308 while (GNUNET_YES != in_shutdown)
1309 {
1310 GNUNET_assert (0 == pthread_mutex_lock (&sign_jobs_lock));
1311 while (NULL == sign_jobs_head)
1312 GNUNET_assert (0 == pthread_cond_wait (&sign_jobs_cond, &sign_jobs_lock));
1313 if (GNUNET_YES == in_shutdown)
1314 {
1315 GNUNET_assert (0 == pthread_mutex_unlock (&sign_jobs_lock));
1316 return NULL;
1317 }
1319 "Taking on Job for %s\n", sign_jobs_head->label);
1322 GNUNET_assert (0 == pthread_mutex_unlock (&sign_jobs_lock));
1323 GNUNET_GNSRECORD_block_sign (&job->zone, job->label, job->block);
1324 if (job->block != job->block_priv)
1325 GNUNET_GNSRECORD_block_sign (&job->zone, job->label, job->block_priv);
1326 GNUNET_assert (0 == pthread_mutex_lock (&sign_results_lock));
1328 GNUNET_assert (0 == pthread_mutex_unlock (&sign_results_lock));
1330 "Done, notifying main thread through pipe!\n");
1331 GNUNET_DISK_file_write (fh, "!", 1);
1332 }
1333 return NULL;
1334}
1335
1336
1337static void
1339{
1341 "Received wake up notification through pipe, checking results\n");
1343}
1344
1345
1353static void
1354run (void *cls,
1355 const struct GNUNET_CONFIGURATION_Handle *c,
1357{
1358 unsigned long long max_parallel_bg_queries = 128;
1359 const struct GNUNET_DISK_FileHandle *np_fh;
1360
1361 (void) cls;
1362 (void) service;
1363 pthread_mutex_init (&sign_jobs_lock, NULL);
1364 pthread_mutex_init (&sign_results_lock, NULL);
1365 pthread_cond_init (&sign_jobs_cond, NULL);
1366 last_put_100 = GNUNET_TIME_absolute_get (); /* first time! */
1371 if (NULL == namestore_handle)
1372 {
1374 _ ("Failed to connect to the namestore!\n"));
1376 return;
1377 }
1379 "namecache",
1380 "DISABLE");
1382 {
1384 if (NULL == namecache)
1385 {
1387 _ ("Failed to connect to the namecache!\n"));
1389 return;
1390 }
1391 }
1393 "namestore",
1394 "CACHE_KEYS");
1396 if (GNUNET_OK ==
1398 "zonemaster",
1399 "ZONE_PUBLISH_TIME_WINDOW",
1401 {
1403 "Time window for zone iteration: %s\n",
1406 GNUNET_YES));
1407 }
1409 if (GNUNET_OK ==
1411 "zonemaster",
1412 "MAX_PARALLEL_BACKGROUND_QUERIES",
1413 &max_parallel_bg_queries))
1414 {
1416 "Number of allowed parallel background queries: %llu\n",
1417 max_parallel_bg_queries);
1418 }
1419 if (0 == max_parallel_bg_queries)
1420 max_parallel_bg_queries = 1;
1422 (unsigned int) max_parallel_bg_queries);
1423 if (NULL == dht_handle)
1424 {
1426 _ ("Could not connect to DHT!\n"));
1428 NULL);
1429 return;
1430 }
1431
1432 /* Schedule periodic put for our records. */
1434 statistics = GNUNET_STATISTICS_create ("zonemaster",
1435 c);
1437 "Target zone iteration velocity (μs)",
1439 GNUNET_NO);
1441 NULL);
1443 NULL,
1444 GNUNET_NO,
1446 NULL,
1448 NULL,
1449 NULL /* sync_cb */,
1450 NULL,
1454 GNUNET_break (NULL != zmon);
1455
1457 NULL);
1458
1460 np_fh = GNUNET_DISK_pipe_handle (
1464 np_fh,
1465 notification_pipe_cb, NULL);
1466
1467 {
1468 long long unsigned int worker_count = 1;
1469 if (GNUNET_OK !=
1471 "zonemaster",
1472 "WORKER_COUNT",
1473 &worker_count))
1474 {
1476 "Number of workers not defined falling back to 1\n");
1477 }
1478 worker = GNUNET_malloc (sizeof (pthread_t) * worker_count);
1480 for (int i = 0; i < worker_count; i++)
1481 {
1482 if (0 !=
1483 pthread_create (&worker[i],
1484 NULL,
1485 &sign_worker,
1486 NULL))
1487 {
1489 "pthread_create");
1491 }
1493 "Workers running",
1494 1,
1495 GNUNET_NO);
1496 }
1497 }
1498}
1499
1500
1506 "zonemaster",
1508 &run,
1509 NULL,
1510 NULL,
1511 NULL,
1513
1514
1515/* end of gnunet-service-zonemaster.c */
static struct GNUNET_SCHEDULER_Task * job
Task for main job.
Definition: gnunet-cadet.c:137
struct GNUNET_HashCode key
The key used in the DHT.
static char * expire
DID Document expiration Date Attribute String.
Definition: gnunet-did.c:97
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static pthread_mutex_t sign_results_lock
Lock for the DHT put jobs queue.
#define PUBLISH_OPS_PER_EXPIRATION
How often should we (re)publish each record before it expires?
static int disable_namecache
Use the namecache? Doing so creates additional cryptographic operations whenever we touch a record.
static struct CacheOperation * cop_head
Head of cop DLL.
static struct RecordPublicationJob * sign_results_tail
See above.
static void zone_iteration_finished(void *cls)
Zone iteration is completed.
static unsigned int ns_iteration_left
How many more values are left for the current query before we need to explicitly ask the namestore fo...
static void notification_pipe_cb(void *cls)
static void refresh_block(const struct GNUNET_GNSRECORD_Block *block)
Refresh the (encrypted) block in the namecache.
static struct GNUNET_TIME_Relative target_iteration_velocity_per_record
What is the frequency at which we currently would like to perform DHT puts (per record)?...
static void cleanup_job(struct RecordPublicationJob *job)
static unsigned long long put_cnt
Number of successful put operations performed in the current measurement cycle (as measured in check_...
static struct GNUNET_NAMECACHE_Handle * namecache
Our handle to the namecache service.
static unsigned long long last_num_public_records
Last seen record count.
static unsigned int job_queue_length
Number of entries in the job queue #jobs_head.
static void handle_monitor_event(void *cls, const struct GNUNET_CRYPTO_PrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, struct GNUNET_TIME_Absolute expire)
Process a record that was stored in the namestore (invoked by the monitor).
static void check_zone_namestore_next()
Check if the current zone iteration needs to be continued by calling publish_zone_namestore_next(),...
static struct RecordPublicationJob * sign_results_head
The DLL for workers to place jobs that are signed.
static struct GNUNET_TIME_Relative sub_delta
By how much should we try to increase our per-record iteration speed (over the desired speed calculat...
static struct GNUNET_TIME_Relative zone_publish_time_window
Time window for zone iteration, adjusted based on relative record expiration times in our zone.
#define DELTA_INTERVAL
How often do we measure the delta between desired zone iteration speed and actual speed,...
static void initiate_put_from_pipe_trigger(void *cls)
static struct RecordPublicationJob * dht_jobs_tail
See above.
static void handle_monitor_error(void *cls)
The zone monitor encountered an IPC error trying to to get in sync.
static void calculate_put_interval()
Calculate target_iteration_velocity_per_record.
#define NAMESTORE_MONITOR_QUEUE_LIMIT
How many events may the namestore give us before it has to wait for us to keep up?
static void publish_zone_namestore_next(void *cls)
Method called periodically that triggers iteration over authoritative records.
static struct CacheOperation * cop_tail
Tail of cop DLL.
static void finish_cache_operation(void *cls, int32_t success, const char *emsg)
Cache operation complete, clean up.
static void handle_record(void *cls, const struct GNUNET_CRYPTO_PrivateKey *key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, struct GNUNET_TIME_Absolute expire)
Function used to put all records successively into the DHT.
static struct GNUNET_NAMESTORE_Handle * namestore_handle
Our handle to the namestore service.
static int in_shutdown
For threads to know we are shutting down.
static void shutdown_task(void *cls)
Task run during shutdown.
#define NS_BLOCK_SIZE
How many records do we fetch in one shot from the namestore?
static struct GNUNET_TIME_Relative min_relative_record_time
Minimum relative expiration time of records seem during the current zone iteration.
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
static struct GNUNET_DISK_PipeHandle * notification_pipe
Our notification pipe.
static struct GNUNET_DHT_Handle * dht_handle
Our handle to the DHT.
#define LATE_ITERATION_SPEEDUP_FACTOR
The factor the current zone iteration interval is divided by for each additional new record.
static int monitor_halted
Monitor halted?
static void publish_zone_dht_start(void *cls)
Periodically iterate over our zone and store everything in dht.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Perform zonemaster duties: watch namestore, publish records.
#define JOB_QUEUE_LIMIT
How many open jobs (and with it maximum amount of pending DHT operations) do we allow at most.
static unsigned long long num_public_records
Useful for zone update for DHT put.
static struct RecordPublicationJob * dht_jobs_head
The DLL for jobs currently in the process of being dispatched into the DHT.
#define INITIAL_ZONE_ITERATION_INTERVAL
The initial interval in milliseconds btween puts in a zone iteration.
static void dispatch_job_monitor(const struct GNUNET_CRYPTO_PrivateKey *key, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count, struct GNUNET_TIME_Absolute expire)
Store GNS records in the DHT.
static int first_zone_iteration
GNUNET_YES if zone has never been published before
static int cache_keys
Optimize block insertion by caching map of private keys to public keys in memory?
static struct GNUNET_TIME_Absolute last_put_100
When did we last start measuring the DELTA_INTERVAL successful DHT puts? Used for velocity calculatio...
static struct GNUNET_SCHEDULER_Task * zone_publish_task
zone publish task
static void * sign_worker(void *cls)
static struct GNUNET_SCHEDULER_Task * pipe_read_task
Pipe read task.
static struct GNUNET_NAMESTORE_ZoneIterator * namestore_iter
Handle to iterate over our authoritative zone in namestore.
static void free_job(struct RecordPublicationJob *job)
static struct GNUNET_TIME_Relative zone_publish_time_window_default
Default time window for zone iteration.
#define DHT_GNS_REPLICATION_LEVEL
What replication level do we use for DHT PUT operations?
static pthread_t * worker
Our workers.
static struct RecordPublicationJob * sign_jobs_head
The DLL for workers to retrieve open jobs that require signing of blocks.
static struct GNUNET_TIME_Relative last_min_relative_record_time
Minimum relative expiration time of records seem during the last zone iteration.
static void update_velocity(unsigned int cnt)
Re-calculate our velocity and the desired velocity.
static pthread_cond_t sign_jobs_cond
Wait condition on new sign jobs.
static void dht_put_continuation(void *cls)
Continuation called from DHT once the PUT operation is done.
static struct GNUNET_NAMESTORE_ZoneMonitor * zmon
Handle to monitor namestore changes to instant propagation.
static struct RecordPublicationJob * sign_jobs_tail
See above.
static void dispatch_job(const struct GNUNET_CRYPTO_PrivateKey *key, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count, const struct GNUNET_TIME_Absolute expire)
Store GNS records in the DHT.
#define MAXIMUM_ZONE_ITERATION_INTERVAL
The upper bound for the zone iteration interval (per record).
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "zonemaster", GNUNET_SERVICE_OPTION_NONE, &run, NULL, NULL, NULL, GNUNET_MQ_handler_end())
Define "main" method using service macro.
static pthread_mutex_t sign_jobs_lock
Lock for the sign jobs queue.
static void zone_iteration_error(void *cls)
We encountered an error in our zone iteration.
API to the DHT service.
API that can be used to store naming information on a GNUnet node.
API that can be used to store naming information on a GNUnet node;.
API to create, modify and access statistics.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
void GNUNET_DHT_put_cancel(struct GNUNET_DHT_PutHandle *ph)
Cancels a DHT PUT operation.
Definition: dht_api.c:1144
struct GNUNET_DHT_PutHandle * GNUNET_DHT_put(struct GNUNET_DHT_Handle *handle, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, size_t size, const void *data, struct GNUNET_TIME_Absolute exp, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Perform a PUT operation storing data in the DHT.
Definition: dht_api.c:1081
struct GNUNET_DHT_Handle * GNUNET_DHT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int ht_len)
Initialize the connection with the DHT service.
Definition: dht_api.c:1030
#define GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY
Default republication frequency for stored data in the DHT.
void GNUNET_DHT_disconnect(struct GNUNET_DHT_Handle *handle)
Shutdown connection with the DHT service.
Definition: dht_api.c:1053
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition: disk.c:1602
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:682
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1425
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1572
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:646
@ GNUNET_DISK_PF_NONE
No special options, use non-blocking read/write operations.
@ GNUNET_DISK_PIPE_END_WRITE
The writing-end of a pipe.
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_create_unsigned(const struct GNUNET_CRYPTO_PrivateKey *key, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count, struct GNUNET_GNSRECORD_Block **result)
Create name and records but do not sign! Sign later with GNUNET_GNSRECORD_block_sign().
void GNUNET_GNSRECORD_query_from_private_key(const struct GNUNET_CRYPTO_PrivateKey *zone, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_sign(const struct GNUNET_CRYPTO_PrivateKey *key, const char *label, struct GNUNET_GNSRECORD_Block *block)
Sign a block create with GNUNET_GNSRECORD_block_create_unsigned.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_normalize_record_set(const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *rd_public, unsigned int *rd_count_public, struct GNUNET_TIME_Absolute *min_expiry, enum GNUNET_GNSRECORD_Filter filter, char **emsg)
Normalize namestore records: Check for consistency and expirations.
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
@ GNUNET_GNSRECORD_FILTER_NONE
No filter flags set.
@ GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE
Filter private records.
#define GNUNET_log(kind,...)
#define GNUNET_MIN(a, b)
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
struct GNUNET_NAMECACHE_Handle * GNUNET_NAMECACHE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namecache service.
void GNUNET_NAMECACHE_disconnect(struct GNUNET_NAMECACHE_Handle *h)
Disconnect from the namecache service (and free associated resources).
void GNUNET_NAMECACHE_cancel(struct GNUNET_NAMECACHE_QueueEntry *qe)
Cancel a namecache operation.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_block_cache(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_GNSRECORD_Block *block, GNUNET_NAMECACHE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namecache.
struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start2(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *zone, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordSetMonitor proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls, enum GNUNET_GNSRECORD_Filter filter)
Starts a new zone iteration (used to periodically PUT all of our records into our DHT).
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
void GNUNET_NAMESTORE_zone_iterator_next(struct GNUNET_NAMESTORE_ZoneIterator *it, uint64_t limit)
Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start for the next record.
void GNUNET_NAMESTORE_zone_monitor_stop(struct GNUNET_NAMESTORE_ZoneMonitor *zm)
Stop monitoring a zone for changes.
struct GNUNET_NAMESTORE_ZoneMonitor * GNUNET_NAMESTORE_zone_monitor_start2(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_PrivateKey *zone, int iterate_first, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordSetMonitor monitor, void *monitor_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, enum GNUNET_GNSRECORD_Filter filter)
Begin monitoring a zone for changes.
void GNUNET_NAMESTORE_zone_monitor_next(struct GNUNET_NAMESTORE_ZoneMonitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_NAMESTORE_zone_monitor_start for the next record(s).
struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
void GNUNET_NAMESTORE_zone_iteration_stop(struct GNUNET_NAMESTORE_ZoneIterator *it)
Stops iteration and releases the namestore handle for further calls.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1661
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1277
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:344
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:438
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:579
struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Subtract relative timestamp from the other.
Definition: time.c:605
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:587
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:486
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:552
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:640
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
@ GNUNET_BLOCK_TYPE_GNS_NAMERECORD
Block for storing GNS record data.
Pending operation on the namecache.
struct CacheOperation * next
Kept in a DLL.
struct GNUNET_NAMECACHE_QueueEntry * qe
Handle to namecache queue.
struct CacheOperation * prev
Kept in a DLL.
A private key for an identity as per LSD0001.
Connection to the DHT service.
Definition: dht_api.c:235
Handle to a PUT request.
Definition: dht_api.c:43
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:69
A 512-bit hashcode.
Connection to the NAMECACHE service.
Definition: namecache_api.c:93
An QueueEntry used to store information for a pending NAMECACHE record operation.
Definition: namecache_api.c:46
Connection to the NAMESTORE service.
Handle for a zone iterator operation.
Handle for a monitoring activity.
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle to a service.
Definition: service.c:116
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
struct RecordPublicationJob * next
DLL.
struct GNUNET_DHT_PutHandle * ph
Handle for the DHT PUT operation.
struct GNUNET_CRYPTO_PrivateKey zone
The zone key to sign the block with.
struct GNUNET_TIME_Absolute start_date
When was this PUT initiated?
int have_public_records
Do we have any public records at all?
struct RecordPublicationJob * prev
DLL.
struct GNUNET_GNSRECORD_Block * block
The block to sign.
char * label
The label of the block needed for signing.
size_t block_size
The size of the public block for the DHT put.
struct GNUNET_TIME_Absolute expire_pub
The expiration time of the public block for the DHT put.
struct GNUNET_GNSRECORD_Block * block_priv
The private block to sign, may point to block in case the public and private blocks are the same.