Logo AND Algorithmique Numérique Distribuée

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