Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
2492711101c6ac2dd44a5e2d66daae54f969d5dc
[simgrid.git] / examples / c / app-bittorrent / tracker.c
1 /* Copyright (c) 2012-2020. 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
9 #include "simgrid/actor.h"
10 #include "simgrid/comm.h"
11 #include "simgrid/engine.h"
12 #include "xbt/log.h"
13
14 XBT_LOG_NEW_DEFAULT_CATEGORY(bittorrent_tracker, "Messages specific for the tracker");
15
16 void tracker_answer_free(void* data)
17 {
18   tracker_answer_t a = (tracker_answer_t)data;
19   xbt_dynar_free(&a->peers);
20   free(a);
21 }
22
23 static int is_in_list(const_xbt_dynar_t peers, int id)
24 {
25   return xbt_dynar_member(peers, &id);
26 }
27
28 /**
29  * Tracker main function
30  * @param argc number of arguments
31  * @param argv arguments
32  */
33 void tracker(int argc, char* argv[])
34 {
35   // Checking arguments
36   xbt_assert(argc == 2, "Wrong number of arguments for the tracker.");
37   // Retrieving end time
38   double deadline = xbt_str_parse_double(argv[1], "Invalid deadline: %s");
39   xbt_assert(deadline > 0, "Wrong deadline supplied");
40
41   // Building peers array
42   xbt_dynar_t peers_list = xbt_dynar_new(sizeof(int), NULL);
43
44   sg_mailbox_t mailbox = sg_mailbox_by_name(TRACKER_MAILBOX);
45
46   XBT_INFO("Tracker launched.");
47   sg_comm_t comm_received = NULL;
48   void* received          = NULL;
49
50   while (simgrid_get_clock() < deadline) {
51     if (comm_received == NULL)
52       comm_received = sg_mailbox_get_async(mailbox, &received);
53
54     if (sg_comm_test(comm_received)) {
55       // Retrieve the data sent by the peer.
56       xbt_assert(received != NULL);
57       tracker_query_t tq = (tracker_query_t)received;
58
59       // Add the peer to our peer list.
60       if (!is_in_list(peers_list, tq->peer_id))
61         xbt_dynar_push_as(peers_list, int, tq->peer_id);
62
63       // Sending peers to the requesting peer
64       tracker_answer_t ta = tracker_answer_new(TRACKER_QUERY_INTERVAL);
65       int next_peer;
66       int peers_length = xbt_dynar_length(peers_list);
67       for (int i = 0; i < MAXIMUM_PEERS && i < peers_length; i++) {
68         do {
69           next_peer = xbt_dynar_get_as(peers_list, rand() % peers_length, int);
70         } while (is_in_list(ta->peers, next_peer));
71         xbt_dynar_push_as(ta->peers, int, next_peer);
72       }
73       // sending the task back to the peer.
74       sg_comm_t answer = sg_mailbox_put_init(tq->return_mailbox, ta, TRACKER_COMM_SIZE);
75       sg_comm_detach(answer, tracker_answer_free);
76
77       xbt_free(tq);
78       comm_received = NULL;
79       received      = NULL;
80     } else {
81       sg_actor_sleep_for(1);
82     }
83   }
84   // Free the remaining communication if any
85   if (comm_received)
86     sg_comm_unref(comm_received);
87   // Free the peers list
88   xbt_dynar_free(&peers_list);
89
90   XBT_INFO("Tracker is leaving");
91 }
92
93 tracker_query_t tracker_query_new(int peer_id, sg_mailbox_t return_mailbox)
94 {
95   tracker_query_t tq = xbt_new(s_tracker_query_t, 1);
96   tq->peer_id        = peer_id;
97   tq->return_mailbox = return_mailbox;
98   return tq;
99 }
100
101 tracker_answer_t tracker_answer_new(int interval)
102 {
103   tracker_answer_t ta = xbt_new(s_tracker_answer_t, 1);
104   ta->interval        = interval;
105   ta->peers           = xbt_dynar_new(sizeof(int), NULL);
106   ;
107   return ta;
108 }
109
110 /**
111  * Build a new task for the tracker.
112  * @param issuer_host_name Hostname of the issuer. For debugging purposes
113  */
114 // tracker_task_data_t tracker_task_data_new(const char* issuer_host_name, sg_mailbox_t mailbox, int peer_id, int
115 // uploaded,
116 //                                          int downloaded, int left)
117 //{
118 //  tracker_task_data_t task = xbt_new(s_tracker_task_data_t, 1);
119 //
120 //  task->type             = TRACKER_TASK_QUERY;
121 //  task->issuer_host_name = issuer_host_name;
122 //  task->mailbox          = mailbox;
123 //  task->peer_id          = peer_id;
124 //  task->uploaded         = uploaded;
125 //  task->downloaded       = downloaded;
126 //  task->left             = left;
127 //
128 //  task->peers = xbt_dynar_new(sizeof(int), NULL);
129 //
130 //  return task;
131 //}
132 //
133 ///**
134 // * Free the data structure of a tracker task.
135 // * @param task data to free
136 // */
137 // void tracker_task_data_free(tracker_task_data_t task)
138 //{
139 //  xbt_dynar_free(&task->peers);
140 //  xbt_free(task);
141 //}
142 //