1 /* Copyright (c) 2012-2023. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "simgrid/actor.h"
10 #include "simgrid/comm.h"
11 #include "simgrid/engine.h"
14 XBT_LOG_NEW_DEFAULT_CATEGORY(bittorrent_tracker, "Messages specific for the tracker");
16 void tracker_answer_free(void* data)
18 tracker_answer_t a = (tracker_answer_t)data;
19 xbt_dynar_free(&a->peers);
23 static int is_in_list(const_xbt_dynar_t peers, int id)
25 return xbt_dynar_member(peers, &id);
28 void tracker_run(int argc, char* argv[])
31 xbt_assert(argc == 2, "Wrong number of arguments for the tracker.");
32 // Retrieving end time
33 double deadline = xbt_str_parse_double(argv[1], "Invalid deadline");
34 xbt_assert(deadline > 0, "Wrong deadline supplied");
36 unsigned* seedp = sg_host_get_data(sg_host_self());
37 // Building peers array
38 xbt_dynar_t peers_list = xbt_dynar_new(sizeof(int), NULL);
40 sg_mailbox_t mailbox = sg_mailbox_by_name(TRACKER_MAILBOX);
42 XBT_INFO("Tracker launched.");
43 sg_comm_t comm_received = NULL;
44 void* received = NULL;
46 while (simgrid_get_clock() < deadline) {
47 if (comm_received == NULL)
48 comm_received = sg_mailbox_get_async(mailbox, &received);
50 if (sg_comm_test(comm_received)) {
51 // Retrieve the data sent by the peer.
52 xbt_assert(received != NULL);
53 tracker_query_t tq = (tracker_query_t)received;
55 // Add the peer to our peer list.
56 if (!is_in_list(peers_list, tq->peer_id))
57 xbt_dynar_push_as(peers_list, int, tq->peer_id);
59 // Sending peers to the requesting peer
60 tracker_answer_t ta = tracker_answer_new(TRACKER_QUERY_INTERVAL);
62 int peers_length = (int)xbt_dynar_length(peers_list);
63 for (int i = 0; i < MAXIMUM_PEERS && i < peers_length; i++) {
65 next_peer = xbt_dynar_get_as(peers_list, rand_r(seedp) % peers_length, int);
66 } while (is_in_list(ta->peers, next_peer));
67 xbt_dynar_push_as(ta->peers, int, next_peer);
69 // sending the task back to the peer.
70 sg_comm_t answer = sg_mailbox_put_init(tq->return_mailbox, ta, TRACKER_COMM_SIZE);
71 sg_comm_detach(answer, tracker_answer_free);
77 sg_actor_sleep_for(1);
80 // Free the remaining communication if any
82 sg_comm_unref(comm_received);
83 // Free the peers list
84 xbt_dynar_free(&peers_list);
86 XBT_INFO("Tracker is leaving");
89 tracker_query_t tracker_query_new(int peer_id, sg_mailbox_t return_mailbox)
91 tracker_query_t tq = xbt_new(s_tracker_query_t, 1);
92 tq->peer_id = peer_id;
93 tq->return_mailbox = return_mailbox;
97 tracker_answer_t tracker_answer_new(int interval)
99 tracker_answer_t ta = xbt_new(s_tracker_answer_t, 1);
100 ta->interval = interval;
101 ta->peers = xbt_dynar_new(sizeof(int), NULL);