Logo AND Algorithmique Numérique Distribuée

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