1 /* Copyright (c) 2012-2020. 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);
29 * Tracker main function
30 * @param argc number of arguments
31 * @param argv arguments
33 void tracker(int argc, char* argv[])
36 xbt_assert(argc == 2, "Wrong number of arguments for the tracker.");
37 // Retrieving end time
38 double deadline = xbt_str_parse_double(argv[1], "Invalid deadline: %s");
39 xbt_assert(deadline > 0, "Wrong deadline supplied");
41 // Building peers array
42 xbt_dynar_t peers_list = xbt_dynar_new(sizeof(int), NULL);
44 sg_mailbox_t mailbox = sg_mailbox_by_name(TRACKER_MAILBOX);
46 XBT_INFO("Tracker launched.");
47 sg_comm_t comm_received = NULL;
48 void* received = NULL;
50 while (simgrid_get_clock() < deadline) {
51 if (comm_received == NULL)
52 comm_received = sg_mailbox_get_async(mailbox, &received);
54 if (sg_comm_test(comm_received)) {
55 // Retrieve the data sent by the peer.
56 xbt_assert(received != NULL);
57 tracker_query_t tq = (tracker_query_t)received;
59 // Add the peer to our peer list.
60 if (!is_in_list(peers_list, tq->peer_id))
61 xbt_dynar_push_as(peers_list, int, tq->peer_id);
63 // Sending peers to the requesting peer
64 tracker_answer_t ta = tracker_answer_new(TRACKER_QUERY_INTERVAL);
66 int peers_length = xbt_dynar_length(peers_list);
67 for (int i = 0; i < MAXIMUM_PEERS && i < peers_length; i++) {
69 next_peer = xbt_dynar_get_as(peers_list, rand() % peers_length, int);
70 } while (is_in_list(ta->peers, next_peer));
71 xbt_dynar_push_as(ta->peers, int, next_peer);
73 // sending the task back to the peer.
74 sg_comm_t answer = sg_mailbox_put_init(tq->return_mailbox, ta, TRACKER_COMM_SIZE);
75 sg_comm_detach(answer, tracker_answer_free);
81 sg_actor_sleep_for(1);
84 // Free the remaining communication if any
86 sg_comm_unref(comm_received);
87 // Free the peers list
88 xbt_dynar_free(&peers_list);
90 XBT_INFO("Tracker is leaving");
93 tracker_query_t tracker_query_new(int peer_id, sg_mailbox_t return_mailbox)
95 tracker_query_t tq = xbt_new(s_tracker_query_t, 1);
96 tq->peer_id = peer_id;
97 tq->return_mailbox = return_mailbox;
101 tracker_answer_t tracker_answer_new(int interval)
103 tracker_answer_t ta = xbt_new(s_tracker_answer_t, 1);
104 ta->interval = interval;
105 ta->peers = xbt_dynar_new(sizeof(int), NULL);
111 * Build a new task for the tracker.
112 * @param issuer_host_name Hostname of the issuer. For debugging purposes
114 // tracker_task_data_t tracker_task_data_new(const char* issuer_host_name, sg_mailbox_t mailbox, int peer_id, int
116 // int downloaded, int left)
118 // tracker_task_data_t task = xbt_new(s_tracker_task_data_t, 1);
120 // task->type = TRACKER_TASK_QUERY;
121 // task->issuer_host_name = issuer_host_name;
122 // task->mailbox = mailbox;
123 // task->peer_id = peer_id;
124 // task->uploaded = uploaded;
125 // task->downloaded = downloaded;
126 // task->left = left;
128 // task->peers = xbt_dynar_new(sizeof(int), NULL);
134 // * Free the data structure of a tracker task.
135 // * @param task data to free
137 // void tracker_task_data_free(tracker_task_data_t task)
139 // xbt_dynar_free(&task->peers);