Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Endgame mode is always enabled, remove option.
[simgrid.git] / teshsuite / msg / app-bittorrent / tracker.c
1 /* Copyright (c) 2012-2019. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7 #include "tracker.h"
8 #include <simgrid/msg.h>
9
10 static void task_free(void* data);
11
12 XBT_LOG_NEW_DEFAULT_CATEGORY(msg_tracker, "Messages specific for the tracker");
13 /**
14  * Tracker main function
15  * @param argc number of arguments
16  * @param argv arguments
17  */
18 int tracker(int argc, char* argv[])
19 {
20   // Checking arguments
21   xbt_assert(argc == 2, "Wrong number of arguments for the tracker.");
22   // Retrieving end time
23   double deadline = xbt_str_parse_double(argv[1], "Invalid deadline: %s");
24   xbt_assert(deadline > 0, "Wrong deadline supplied");
25
26   // Building peers array
27   xbt_dynar_t peers_list = xbt_dynar_new(sizeof(int), NULL);
28
29   XBT_INFO("Tracker launched.");
30
31   msg_comm_t comm_received = NULL;
32   msg_task_t task_received = NULL;
33
34   while (MSG_get_clock() < deadline) {
35     if (comm_received == NULL) {
36       comm_received = MSG_task_irecv(&task_received, TRACKER_MAILBOX);
37     }
38     if (MSG_comm_test(comm_received)) {
39       // Check for correct status
40       if (MSG_comm_get_status(comm_received) == MSG_OK) {
41         // Retrieve the data sent by the peer.
42         tracker_task_data_t data = MSG_task_get_data(task_received);
43         // Add the peer to our peer list.
44         if (is_in_list(peers_list, data->peer_id) == 0) {
45           xbt_dynar_push_as(peers_list, int, data->peer_id);
46         }
47         // Sending peers to the peer
48         int next_peer;
49         int peers_length = xbt_dynar_length(peers_list);
50         for (int i = 0; i < MAXIMUM_PEERS && i < peers_length; i++) {
51           do {
52             next_peer = xbt_dynar_get_as(peers_list, rand() % peers_length, int);
53           } while (is_in_list(data->peers, next_peer));
54           xbt_dynar_push_as(data->peers, int, next_peer);
55         }
56         // setting the interval
57         data->interval = TRACKER_QUERY_INTERVAL;
58         // sending the task back to the peer.
59         MSG_task_dsend(task_received, data->mailbox, task_free);
60         // destroy the communication.
61       }
62       MSG_comm_destroy(comm_received);
63       comm_received = NULL;
64       task_received = NULL;
65     } else {
66       MSG_process_sleep(1);
67     }
68   }
69   // Free the remaining communication if any
70   if (comm_received) {
71     MSG_comm_destroy(comm_received);
72   }
73   // Free the peers list
74   xbt_dynar_free(&peers_list);
75
76   XBT_INFO("Tracker is leaving");
77
78   return 0;
79 }
80
81 /**
82  * Build a new task for the tracker.
83  * @param issuer_host_name Hostname of the issuer. For debugging purposes
84  */
85 tracker_task_data_t tracker_task_data_new(const char* issuer_host_name, const char* mailbox, int peer_id, int uploaded,
86                                           int downloaded, int left)
87 {
88   tracker_task_data_t task = xbt_new(s_tracker_task_data_t, 1);
89
90   task->type             = TRACKER_TASK_QUERY;
91   task->issuer_host_name = issuer_host_name;
92   task->mailbox          = mailbox;
93   task->peer_id          = peer_id;
94   task->uploaded         = uploaded;
95   task->downloaded       = downloaded;
96   task->left             = left;
97
98   task->peers = xbt_dynar_new(sizeof(int), NULL);
99
100   return task;
101 }
102
103 /**
104  * Free a tracker task that has not successfully been sent.
105  * @param data Task to free
106  */
107 static void task_free(void* data)
108 {
109   tracker_task_data_t task_data = MSG_task_get_data(data);
110   tracker_task_data_free(task_data);
111   MSG_task_destroy(data);
112 }
113
114 /**
115  * Free the data structure of a tracker task.
116  * @param task data to free
117  */
118 void tracker_task_data_free(tracker_task_data_t task)
119 {
120   xbt_dynar_free(&task->peers);
121   xbt_free(task);
122 }
123
124 /**
125  * Returns if the given id is in the peers lsit
126  * @param peers dynar containing the peers
127  * @param id identifier of the peer to test
128  */
129 int is_in_list(xbt_dynar_t peers, int id)
130 {
131   return xbt_dynar_member(peers, &id);
132 }