Janitor.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "crypto/random/Random.h"
  16. #include "dht/Address.h"
  17. #include "dht/dhtcore/Janitor.h"
  18. #include "dht/dhtcore/Node.h"
  19. #include "dht/dhtcore/NodeList.h"
  20. #include "dht/dhtcore/RumorMill.h"
  21. #include "dht/dhtcore/RouterModule.h"
  22. #include "dht/dhtcore/SearchRunner.h"
  23. #include "dht/dhtcore/ReplySerializer.h"
  24. #include "benc/Object.h"
  25. #include "memory/Allocator.h"
  26. #include "util/AddrTools.h"
  27. #include "util/AverageRoller.h"
  28. #include "util/Bits.h"
  29. #include "util/events/EventBase.h"
  30. #include "util/Hex.h"
  31. #include "util/events/Timeout.h"
  32. #include "util/events/Time.h"
  33. #include "util/Defined.h"
  34. #include <stdint.h>
  35. #include <stdbool.h>
  36. #define MAX_SEARCHES 10
  37. /**
  38. * The goal of this is to run searches in the local area of this node.
  39. * it searches for hashes every localMaintainenceSearchPeriod milliseconds.
  40. * it runs searches by picking hashes at random, if a hash is chosen and there is a
  41. * non-zero-reach node which services that space, it stops. This way it will run many
  42. * searches early on but as the number of known nodes increases, it begins to taper off.
  43. */
  44. struct Janitor
  45. {
  46. struct RouterModule* routerModule;
  47. struct NodeStore* nodeStore;
  48. struct SearchRunner* searchRunner;
  49. // Externally accessible RumorMill.
  50. // Used for direct peers and search results that are closer than the responder.
  51. struct RumorMill* rumorMill;
  52. // High priority RumorMill.
  53. // Used to discover new links to nodes we already know about.
  54. struct RumorMill* linkMill;
  55. // Low priority RumorMill.
  56. // Used to discover new nodes.
  57. struct RumorMill* nodeMill;
  58. // Just used to keep track of nodes that we need to check on for DHT health.
  59. struct RumorMill* dhtMill;
  60. struct Timeout* timeout;
  61. struct Log* logger;
  62. uint64_t globalMaintainenceMilliseconds;
  63. uint64_t timeOfNextGlobalMaintainence;
  64. uint64_t localMaintainenceMilliseconds;
  65. struct Allocator* allocator;
  66. uint64_t timeOfNextSearchRepeat;
  67. uint64_t searchRepeatMilliseconds;
  68. struct EventBase* eventBase;
  69. struct Random* rand;
  70. /** Number of concurrent searches taking place. */
  71. int searches;
  72. Identity
  73. };
  74. struct Janitor_Search
  75. {
  76. struct Janitor* janitor;
  77. struct Address best;
  78. uint8_t target[16];
  79. struct Allocator* alloc;
  80. Identity
  81. };
  82. static void responseCallback(struct RouterModule_Promise* promise,
  83. uint32_t lagMilliseconds,
  84. struct Address* from,
  85. Dict* result)
  86. {
  87. struct Janitor_Search* search = Identity_check((struct Janitor_Search*)promise->userData);
  88. if (from) {
  89. Bits_memcpyConst(&search->best, from, sizeof(struct Address));
  90. return;
  91. }
  92. search->janitor->searches--;
  93. if (!search->best.path) {
  94. Log_debug(search->janitor->logger, "Search completed with no nodes found");
  95. }
  96. Allocator_free(search->alloc);
  97. }
  98. static void search(uint8_t target[16], struct Janitor* janitor)
  99. {
  100. if (janitor->searches >= MAX_SEARCHES) {
  101. Log_debug(janitor->logger, "Skipping search because 20 are in progress");
  102. return;
  103. }
  104. #ifdef Log_DEBUG
  105. uint8_t targetStr[40];
  106. AddrTools_printIp(targetStr, target);
  107. Log_debug(janitor->logger, "Beginning search for [%s]", targetStr);
  108. #endif
  109. struct Allocator* searchAlloc = Allocator_child(janitor->allocator);
  110. struct RouterModule_Promise* rp =
  111. SearchRunner_search(target, janitor->searchRunner, searchAlloc);
  112. if (!rp) {
  113. Log_debug(janitor->logger, "SearchRunner_search() returned NULL, probably full.");
  114. Allocator_free(searchAlloc);
  115. return;
  116. }
  117. janitor->searches++;
  118. struct Janitor_Search* search = Allocator_clone(rp->alloc, (&(struct Janitor_Search) {
  119. .janitor = janitor,
  120. .alloc = searchAlloc,
  121. }));
  122. Identity_set(search);
  123. Bits_memcpyConst(search->target, target, 16);
  124. rp->callback = responseCallback;
  125. rp->userData = search;
  126. }
  127. static void searchNoDupe(uint8_t target[Address_SEARCH_TARGET_SIZE], struct Janitor* janitor)
  128. {
  129. // See if we're already searching for this address.
  130. struct Allocator* seachListAlloc = Allocator_child(janitor->allocator);
  131. struct SearchRunner_SearchData* searchData;
  132. for (int i = 0; i < SearchRunner_DEFAULT_MAX_CONCURRENT_SEARCHES; i++) {
  133. searchData = SearchRunner_showActiveSearch(janitor->searchRunner,
  134. i,
  135. seachListAlloc);
  136. if (!searchData) { continue; }
  137. if (!Bits_memcmp(searchData->target, target, Address_SEARCH_TARGET_SIZE)) {
  138. // Already have a search going for this address, so nothing to do.
  139. Allocator_free(seachListAlloc);
  140. return;
  141. }
  142. }
  143. Allocator_free(seachListAlloc);
  144. // There's no search running for this address, so we start one.
  145. search(target, janitor);
  146. #ifdef Log_DEBUG
  147. uint8_t addrStr[40];
  148. AddrTools_printIp(addrStr, target);
  149. Log_debug(janitor->logger, "No active search for [%s], starting one.", addrStr);
  150. #endif
  151. }
  152. static void dhtResponseCallback(struct RouterModule_Promise* promise,
  153. uint32_t lagMilliseconds,
  154. struct Address* from,
  155. Dict* result)
  156. {
  157. struct Janitor* janitor = Identity_check((struct Janitor*)promise->userData);
  158. if (!from) { return; }
  159. struct Address_List* addresses =
  160. ReplySerializer_parse(from, result, janitor->logger, promise->alloc);
  161. struct Node_Two* parent = NodeStore_nodeForAddr(janitor->nodeStore, from->ip6.bytes);
  162. if (!parent) { return; }
  163. struct Address* selfAddr = janitor->nodeStore->selfAddress;
  164. for (int i = 0; addresses && i < addresses->length; i++) {
  165. if (Address_closest(selfAddr, from, &addresses->elems[i]) < 0) {
  166. // Address is further from us than the node we asked. Skip it.
  167. continue;
  168. }
  169. // Possibly interesting for dht reasons.
  170. RumorMill_addNode(janitor->dhtMill, &addresses->elems[i]);
  171. }
  172. }
  173. /**
  174. * For a Distributed Hash Table to work, each node must know a valid next hop for every possible
  175. * lookup, unless no such node exists in the network (i.e. the final hop is either us or offline).
  176. *
  177. * This function queries other nodes to find valid next hops for any address.
  178. */
  179. static void keyspaceMaintenance(struct Janitor* janitor)
  180. {
  181. struct Address addr;
  182. struct Address* selfAddr = janitor->nodeStore->selfAddress;
  183. if (!RumorMill_getNode(janitor->dhtMill, &addr)) {
  184. // Try to fill the dhtMill for next time.
  185. for (uint8_t bucket = 0; bucket < NodeStore_bucketNumber ; bucket++) {
  186. // Check if there's a valid next hop for this bit in keyspace.
  187. struct Address target = NodeStore_addrForBucket(selfAddr, bucket);
  188. struct Node_Two* node = NodeStore_getBest(janitor->nodeStore, target.ip6.bytes);
  189. if (!node) { continue; }
  190. // There's a valid next hop.
  191. // TODO(arceliar): Ask for the NodeStore_bucketSize best nodes?
  192. // By best I mean, of the nodes that are closer, those with highest reach.
  193. // (Not the closest.)
  194. RumorMill_addNode(janitor->dhtMill, &node->address);
  195. }
  196. return;
  197. }
  198. if (NodeStore_nodeForAddr(janitor->nodeStore, addr.ip6.bytes)) {
  199. // Address falls in our N'th bucket.
  200. // Ask for nodes from their N'th bucket.
  201. // Responses are good for our N+1'th or later bucket.
  202. uint8_t bucket = NodeStore_bucketForAddr(selfAddr, &addr);
  203. struct Address target = NodeStore_addrForBucket(&addr, bucket);
  204. struct RouterModule_Promise* rp = RouterModule_findNode(&addr,
  205. target.ip6.bytes,
  206. 0,
  207. janitor->routerModule,
  208. janitor->allocator);
  209. rp->callback = dhtResponseCallback;
  210. rp->userData = janitor;
  211. #ifdef Log_DEBUG
  212. uint8_t addrStr[60];
  213. Address_print(addrStr, &addr);
  214. Log_debug(janitor->logger, "Sending findNode to [%s] from "
  215. "dht-checking RumorMill", addrStr);
  216. #endif
  217. } else {
  218. // Node not already in our routing table.
  219. // Ping them. If they're good, we'll ask them to findNodes our next round.
  220. RouterModule_pingNode(&addr, 0, janitor->routerModule, janitor->allocator);
  221. #ifdef Log_DEBUG
  222. uint8_t addrStr[60];
  223. Address_print(addrStr, &addr);
  224. Log_debug(janitor->logger, "Pinging possible node [%s] from "
  225. "dht-checking RumorMill", addrStr);
  226. #endif
  227. }
  228. return;
  229. searchNoDupe(addr.ip6.bytes, janitor); // The last search, unaccessible.
  230. }
  231. static void peersResponseCallback(struct RouterModule_Promise* promise,
  232. uint32_t lagMilliseconds,
  233. struct Address* from,
  234. Dict* result)
  235. {
  236. struct Janitor* janitor = Identity_check((struct Janitor*)promise->userData);
  237. if (!from) { return; }
  238. struct Address_List* addresses =
  239. ReplySerializer_parse(from, result, janitor->logger, promise->alloc);
  240. struct Node_Two* parent = NodeStore_nodeForAddr(janitor->nodeStore, from->ip6.bytes);
  241. if (!parent) { return; }
  242. int loopCount = 0;
  243. for (int i = 0; addresses && i < addresses->length; i++) {
  244. // they're telling us about themselves, how helpful...
  245. if (!Bits_memcmp(addresses->elems[i].key, from->key, 32)) { continue; }
  246. struct Node_Link* nl = NodeStore_linkForPath(janitor->nodeStore, addresses->elems[i].path);
  247. if (!nl || Bits_memcmp(nl->child->address.ip6.bytes,
  248. addresses->elems[i].ip6.bytes,
  249. Address_SEARCH_TARGET_SIZE))
  250. {
  251. struct Node_Two* node = NodeStore_nodeForAddr(janitor->nodeStore,
  252. addresses->elems[i].ip6.bytes);
  253. if (node) {
  254. RumorMill_addNode(janitor->linkMill, &addresses->elems[i]);
  255. } else {
  256. RumorMill_addNode(janitor->nodeMill, &addresses->elems[i]);
  257. }
  258. } else if (!Address_isSameIp(&addresses->elems[i], &nl->child->address)) {
  259. if (nl->parent != parent) {
  260. #ifdef Log_INFO
  261. uint8_t newAddr[60];
  262. Address_print(newAddr, from);
  263. uint8_t labelStr[20];
  264. AddrTools_printPath(labelStr, nl->cannonicalLabel);
  265. Log_info(janitor->logger, "Apparently [%s] reported [%s] as it's peer",
  266. newAddr, labelStr);
  267. #endif
  268. continue;
  269. }
  270. #ifdef Log_INFO
  271. uint8_t newAddr[60];
  272. Address_print(newAddr, from);
  273. Log_info(janitor->logger, "Apparently [%s] has renumbered it's switch", newAddr);
  274. #endif
  275. struct Node_Link* link = NodeStore_nextLink(parent, NULL);
  276. while (link) {
  277. struct Node_Link* nextLink = NodeStore_nextLink(parent, link);
  278. NodeStore_unlinkNodes(janitor->nodeStore, link);
  279. link = nextLink;
  280. // restart from the beginning...
  281. i = 0;
  282. Assert_true(!loopCount);
  283. }
  284. Assert_true(!NodeStore_nextLink(parent, NULL));
  285. loopCount++;
  286. }
  287. }
  288. }
  289. static void checkPeers(struct Janitor* janitor, struct Node_Two* n)
  290. {
  291. // Lets check for non-one-hop links at each node along the path between us and this node.
  292. uint64_t path = n->address.path;
  293. struct Node_Link* link = NULL;
  294. for (;;) {
  295. link = NodeStore_firstHopInPath(janitor->nodeStore, path, &path, link);
  296. if (!link) { return; }
  297. if (link->parent == janitor->nodeStore->selfNode) { continue; }
  298. struct Node_Link* l = NULL;
  299. do {
  300. l = NodeStore_nextLink(link->child, l);
  301. if (l && (!Node_isOneHopLink(l) || Node_getReach(link->parent) == 0)) {
  302. struct RouterModule_Promise* rp =
  303. RouterModule_getPeers(&link->parent->address, l->cannonicalLabel, 0,
  304. janitor->routerModule, janitor->allocator);
  305. rp->callback = peersResponseCallback;
  306. rp->userData = janitor;
  307. // Only send max 1 getPeers req per second.
  308. return;
  309. }
  310. } while (l);
  311. }
  312. }
  313. // Iterate over all nodes in the table. Try to split any split-able links.
  314. static void splitLinks(struct Janitor* janitor)
  315. {
  316. //return; // TODO(cjd): Enabled until we figure out if it's still needed.
  317. struct Node_Two* node = NodeStore_getNextNode(janitor->nodeStore, NULL);
  318. while (node) {
  319. struct Node_Link* bestParent = Node_getBestParent(node);
  320. if (bestParent) {
  321. struct Node_Link* link = NodeStore_nextLink(node, NULL);
  322. while (link) {
  323. if (!Node_isOneHopLink(link)) {
  324. RumorMill_addNode(janitor->linkMill, &node->address);
  325. break;
  326. }
  327. link = NodeStore_nextLink(node, link);
  328. }
  329. }
  330. node = NodeStore_getNextNode(janitor->nodeStore, node);
  331. }
  332. }
  333. static struct Node_Two* getRandomNode(struct Random* rand, struct NodeStore* store)
  334. {
  335. uint32_t index = Random_uint32(rand) % (store->nodeCount);
  336. struct Node_Two* node = NULL;
  337. do {
  338. node = NodeStore_getNextNode(store, node);
  339. } while (index--);
  340. // there's always the self node
  341. Assert_true(node);
  342. return node;
  343. }
  344. static void getPeersMill(struct Janitor* janitor, struct Address* addr)
  345. {
  346. // If we have a node in the store and we ping the same path with a different address
  347. // it can cause an error packet which causes the *good* link to be destroyed.
  348. // Therefore we will always ping the node which we believe to be at the end of the
  349. // path and if there is an error, we will flush the link rediscover the path later.
  350. struct Node_Link* nl = NodeStore_linkForPath(janitor->nodeStore, addr->path);
  351. if (nl) {
  352. addr = &nl->child->address;
  353. }
  354. struct RouterModule_Promise* rp =
  355. RouterModule_getPeers(addr,
  356. Random_uint32(janitor->rand),
  357. 0,
  358. janitor->routerModule,
  359. janitor->allocator);
  360. rp->callback = peersResponseCallback;
  361. rp->userData = janitor;
  362. }
  363. #define debugAddr(janitor, msg, addr) \
  364. if (Defined(Log_DEBUG)) { \
  365. uint8_t addrStr[60]; \
  366. Address_print(addrStr, (addr)); \
  367. Log_debug((janitor)->logger, "%s [%s]", (msg), addrStr); \
  368. } \
  369. do { } while (0)
  370. // CHECKFILES_IGNORE expecting a { or ;
  371. static bool tryExistingNode(struct Janitor* janitor)
  372. {
  373. struct Node_Two* node = getRandomNode(janitor->rand, janitor->nodeStore);
  374. while (node && (node->address.path == UINT64_MAX || node->address.path == 1)) {
  375. node = NodeStore_getNextNode(janitor->nodeStore, node);
  376. }
  377. if (node) {
  378. getPeersMill(janitor, &node->address);
  379. debugAddr(janitor, "Pinging existing node", &node->address);
  380. return true;
  381. }
  382. return false;
  383. }
  384. static bool tryNodeMill(struct Janitor* janitor)
  385. {
  386. struct Address addr = { .protocolVersion = 0 };
  387. if (RumorMill_getNode(janitor->nodeMill, &addr)) {
  388. // ping a node from the low-priority ping queue
  389. getPeersMill(janitor, &addr);
  390. debugAddr(janitor, "Pinging possible node from node-finding RumorMill", &addr);
  391. return true;
  392. }
  393. return false;
  394. }
  395. static bool tryExternalMill(struct Janitor* janitor)
  396. {
  397. struct Address addr = { .protocolVersion = 0 };
  398. if (RumorMill_getNode(janitor->rumorMill, &addr)) {
  399. // ping a node from the externally accessible queue
  400. getPeersMill(janitor, &addr);
  401. debugAddr(janitor, "Pinging possible node from external RumorMill", &addr);
  402. return true;
  403. }
  404. return false;
  405. }
  406. static bool tryLinkMill(struct Janitor* janitor)
  407. {
  408. struct Address addr = { .protocolVersion = 0 };
  409. if (RumorMill_getNode(janitor->linkMill, &addr)) {
  410. // ping a node from the externally accessible queue
  411. getPeersMill(janitor, &addr);
  412. debugAddr(janitor, "Pinging possible node from link-finding RumorMill", &addr);
  413. return true;
  414. }
  415. return false;
  416. }
  417. static bool tryRandomLink(struct Janitor* janitor)
  418. {
  419. // There's not an obvious way to get a random link directly, so first get a random node.
  420. struct Node_Two* node = getRandomNode(janitor->rand, janitor->nodeStore);
  421. // Count the number of links leading from this node.
  422. struct Node_Link* link = NodeStore_nextLink(node, NULL);
  423. uint32_t linkCount = 0;
  424. while (link) {
  425. linkCount++;
  426. link = NodeStore_nextLink(node, link);
  427. }
  428. if (linkCount) {
  429. // Now pick one of these links at random.
  430. uint32_t randLinkIndex = Random_uint32(janitor->rand) % linkCount;
  431. link = NodeStore_nextLink(node, NULL);
  432. linkCount = 0;
  433. while (linkCount < randLinkIndex) {
  434. linkCount++;
  435. link = NodeStore_nextLink(node, link);
  436. }
  437. }
  438. if (link && link->parent != link->child) {
  439. struct Address addr = link->child->address;
  440. uint64_t path = NodeStore_getRouteLabel(janitor->nodeStore,
  441. link->parent->address.path,
  442. link->cannonicalLabel);
  443. if (path != NodeStore_getRouteLabel_PARENT_NOT_FOUND &&
  444. path != NodeStore_getRouteLabel_CHILD_NOT_FOUND)
  445. {
  446. addr.path = path;
  447. }
  448. if (addr.path < UINT64_MAX) {
  449. getPeersMill(janitor, &addr);
  450. #ifdef Log_DEBUG
  451. uint8_t addrStr[60];
  452. Address_print(addrStr, &addr);
  453. Log_debug(janitor->logger, "Pinging random node link [%s] for maintenance.",
  454. addrStr);
  455. #endif
  456. return true;
  457. }
  458. }
  459. return false;
  460. }
  461. static void maintanenceCycle(void* vcontext)
  462. {
  463. struct Janitor* const janitor = Identity_check((struct Janitor*) vcontext);
  464. uint64_t now = Time_currentTimeMilliseconds(janitor->eventBase);
  465. uint64_t nextTimeout = (janitor->localMaintainenceMilliseconds / 2);
  466. nextTimeout += Random_uint32(janitor->rand) % (nextTimeout * 2);
  467. Timeout_resetTimeout(janitor->timeout, nextTimeout);
  468. if (janitor->nodeStore->nodeCount == 0 && janitor->rumorMill->count == 0) {
  469. if (now > janitor->timeOfNextGlobalMaintainence) {
  470. Log_warn(janitor->logger,
  471. "No nodes in routing table, check network connection and configuration.");
  472. janitor->timeOfNextGlobalMaintainence += janitor->globalMaintainenceMilliseconds;
  473. }
  474. return;
  475. }
  476. struct Address addr = { .protocolVersion = 0 };
  477. if (tryExternalMill(janitor)) {
  478. // always try the external mill first, this is low-traffic.
  479. } else if (Random_uint8(janitor->rand) < janitor->nodeStore->linkedNodes &&
  480. tryExistingNode(janitor))
  481. {
  482. // up to 50% of the time, try to ping an existing node or find a new one.
  483. } else if (!(Random_uint8(janitor->rand) % 4) && tryLinkMill(janitor)) {
  484. // 25% of the time, try to optimize a link
  485. } else if (Random_uint8(janitor->rand) % 4 && tryRandomLink(janitor)) {
  486. // 75% of the time, ping a random link from a random node.
  487. } else if (tryNodeMill(janitor)) {
  488. // the rest of the time, try to find a new node.
  489. } else {
  490. Log_debug(janitor->logger, "Could not find anything to do");
  491. }
  492. // random search
  493. Random_bytes(janitor->rand, addr.ip6.bytes, 16);
  494. // Make this a valid address.
  495. addr.ip6.bytes[0] = 0xfc;
  496. struct Node_Two* n = NodeStore_getBest(janitor->nodeStore, addr.ip6.bytes);
  497. // If the best next node doesn't exist or has 0 reach, run a local maintenance search.
  498. if (n == NULL || Node_getReach(n) == 0) {
  499. //search(addr.ip6.bytes, janitor);
  500. //plugLargestKeyspaceHole(janitor, true);
  501. //return;
  502. } else {
  503. checkPeers(janitor, n);
  504. }
  505. keyspaceMaintenance(janitor);
  506. Log_debug(janitor->logger,
  507. "Global Mean Response Time: %u nodes [%d] links [%d]",
  508. RouterModule_globalMeanResponseTime(janitor->routerModule),
  509. janitor->nodeStore->nodeCount,
  510. janitor->nodeStore->linkCount);
  511. if (now > janitor->timeOfNextGlobalMaintainence) {
  512. //search(addr.ip6.bytes, janitor);
  513. splitLinks(janitor);
  514. janitor->timeOfNextGlobalMaintainence += janitor->globalMaintainenceMilliseconds;
  515. }
  516. }
  517. struct Janitor* Janitor_new(uint64_t localMaintainenceMilliseconds,
  518. uint64_t globalMaintainenceMilliseconds,
  519. struct RouterModule* routerModule,
  520. struct NodeStore* nodeStore,
  521. struct SearchRunner* searchRunner,
  522. struct RumorMill* rumorMill,
  523. struct Log* logger,
  524. struct Allocator* allocator,
  525. struct EventBase* eventBase,
  526. struct Random* rand)
  527. {
  528. struct Allocator* alloc = Allocator_child(allocator);
  529. struct Janitor* janitor = Allocator_clone(alloc, (&(struct Janitor) {
  530. .eventBase = eventBase,
  531. .routerModule = routerModule,
  532. .nodeStore = nodeStore,
  533. .searchRunner = searchRunner,
  534. .rumorMill = rumorMill,
  535. .logger = logger,
  536. .globalMaintainenceMilliseconds = globalMaintainenceMilliseconds,
  537. .localMaintainenceMilliseconds = localMaintainenceMilliseconds,
  538. .allocator = alloc,
  539. .rand = rand
  540. }));
  541. Identity_set(janitor);
  542. janitor->linkMill = RumorMill_new(alloc, nodeStore->selfAddress, 64, logger, "linkMill");
  543. janitor->nodeMill = RumorMill_new(alloc, nodeStore->selfAddress, 64, logger, "nodeMill");
  544. janitor->dhtMill = RumorMill_new(alloc, nodeStore->selfAddress, 64, logger, "dhtMill");
  545. janitor->timeOfNextGlobalMaintainence = Time_currentTimeMilliseconds(eventBase);
  546. janitor->timeout = Timeout_setTimeout(maintanenceCycle,
  547. janitor,
  548. localMaintainenceMilliseconds,
  549. eventBase,
  550. alloc);
  551. return janitor;
  552. }