Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add bittorrent example
[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         int i, key_elm;
21         char *key;
22         void *data_p;
23
24         RngStream stream = RngStream_CreateStream("tracker");
25
26         //Checking arguments
27         xbt_assert(argc == 2, "Wrong number of arguments for the tracker.");
28         //Retrieving end time
29         double deadline = atof(argv[1]);
30         xbt_assert(deadline > 0, "Wrong deadline supplied");
31         //Building peers array
32         xbt_dynar_t peers_list = xbt_dynar_new(sizeof(int), NULL);
33
34         XBT_INFO("Tracker launched.");
35
36         msg_comm_t comm_received = NULL;
37         msg_task_t task_received = NULL;
38
39         while (MSG_get_clock() < deadline) {
40                 if (comm_received == NULL) {
41                         comm_received = MSG_task_irecv(&task_received,TRACKER_MAILBOX);
42                 }
43                 if (MSG_comm_test(comm_received)) {
44                         //Check for correct status
45                         if (MSG_comm_get_status(comm_received) == MSG_OK) {
46                                 //Retrieve the data sent by the peer.
47                                 tracker_task_data_t data = MSG_task_get_data(task_received);
48                                 //Add the peer to our peer list.
49                                 if (!is_in_list(peers_list,data->peer_id)) {
50                                         xbt_dynar_push_as(peers_list, int, data->peer_id);
51                                 }
52                                 //Sending peers to the peer
53                                 int nb_peers = 0, next_peer;
54                                 int peers_length = xbt_dynar_length(peers_list);
55                                 for (i = 0; i < MAXIMUM_PAIRS && i < peers_length; i++) {
56                                         do {
57                                                 next_peer = xbt_dynar_get_as(peers_list,RngStream_RandInt(stream, 0, peers_length - 1),int);
58                                         } while (is_in_list(data->peers, next_peer));
59                                         xbt_dynar_push_as(data->peers,int,next_peer);
60                                 }
61                                 //setting the interval
62                                 data->interval = TRACKER_QUERY_INTERVAL;
63                                 //sending the task back to the peer.
64                                 MSG_task_dsend(task_received,data->mailbox, task_free);
65                                 //destroy the communication.
66                         }
67                         MSG_comm_destroy(comm_received);
68                         comm_received = NULL;
69                         task_received = NULL;
70                 }
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         //Free the RngStream object.
82         RngStream_DeleteStream(&stream);
83
84         XBT_INFO("Tracker is leaving");
85
86         return 0;
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, const char *mailbox, int peer_id, int uploaded, int downloaded, int left) {
93         tracker_task_data_t task = xbt_new(s_tracker_task_data_t, 1);
94
95         task->type = TRACKER_TASK_QUERY;
96         task->issuer_host_name = issuer_host_name;
97         task->mailbox = mailbox;
98         task->peer_id = peer_id;
99         task->uploaded = uploaded;
100         task->downloaded = downloaded;
101         task->left = left;
102
103         task->peers = xbt_dynar_new(sizeof(int),NULL);
104
105         return task;
106 }
107 /**
108  * Free a tracker task that has not succefully been sent.
109  * @param data Task to free
110  */
111 static void task_free(void *data) {
112         tracker_task_data_t task_data = MSG_task_get_data(data);
113         tracker_task_data_free(task_data);
114         MSG_task_destroy(data);
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         xbt_dynar_free(&task->peers);
122         xbt_free(task);
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         int i, elm;
131         xbt_dynar_foreach(peers, i, elm ) {
132                 if (elm == id) {
133                         return 1;
134                 }
135         }
136         return 0;
137 }