Logo AND Algorithmique Numérique Distribuée

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