sensor: towards profiler
[oweals/gnunet.git] / src / sensor / gnunet-sensor-profiler.c
1 /*
2      This file is part of GNUnet.
3      (C)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * TODO:
23  * - Run X peers
24  * - Rewrite interval time (optional)
25  * - Run 1 dashboard
26  * - Monitor dashboard records
27  * - Prompt for anomalies when ready:
28  *  -- Cut Y peers (remove their connections to other X-Y peers but not the connections among themselves)
29  */
30
31 /**
32  * @file sensor/gnunet-sensor-profiler.c
33  * @brief Profiler for the sensor service
34  * @author Omar Tarabai
35  */
36 #include "platform.h"
37 #include "gnunet_util_lib.h"
38 #include "gnunet_testbed_service.h"
39
40 /**
41  * Information about a single peer
42  */
43 struct PeerInfo
44 {
45
46   /**
47    * Peer Identity
48    */
49   struct GNUNET_PeerIdentity peer_id;
50
51   /**
52    * Testbed peer handle
53    */
54   struct GNUNET_TESTBED_Peer *testbed_peer;
55
56 };
57
58 /**
59  * Number of peers to run
60  */
61 static unsigned int num_peers;
62
63 /**
64  * Return value of the program
65  */
66 static int ok = 1;
67
68 /**
69  * Array of peer info for all peers
70  */
71 static struct PeerInfo *all_peers_info;
72
73 /**
74  * Number of peers that we already collected and start their info
75  */
76 static int peers_known = 0;
77
78 /**
79  * Name of the configuration file used
80  */
81 static char *cfg_filename = "gnunet-sensor-profiler.conf";
82
83
84 /**
85  * Do clean up and shutdown scheduler
86  */
87 static void
88 do_shutdown ()                  // TODO: schedule timeout shutdown
89 {
90   if (NULL != all_peers_info)
91   {
92     GNUNET_free (all_peers_info);
93     all_peers_info = NULL;
94   }
95   GNUNET_SCHEDULER_shutdown ();
96 }
97
98
99 /**
100  * Callback to be called when the requested peer information is available
101  *
102  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
103  * @param op the operation this callback corresponds to
104  * @param pinfo the result; will be NULL if the operation has failed
105  * @param emsg error message if the operation has failed; will be NULL if the
106  *          operation is successfull
107  */
108 static void
109 peer_info_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
110               const struct GNUNET_TESTBED_PeerInformation *pinfo,
111               const char *emsg)
112 {
113   struct GNUNET_TESTBED_Peer *testbed_peer = cb_cls;
114   struct PeerInfo *peer = &all_peers_info[peers_known];
115
116   peer->testbed_peer = testbed_peer;
117   GNUNET_CRYPTO_get_peer_identity (pinfo->result.cfg, &peer->peer_id);
118   peers_known++;
119   if (peers_known == num_peers) //TODO: remove
120   {
121     do_shutdown ();
122   }
123 }
124
125
126 /**
127  * Signature of a main function for a testcase.
128  *
129  * @param cls closure
130  * @param h the run handle
131  * @param num number of peers in 'peers'
132  * @param peers handle to peers run in the testbed.  NULL upon timeout (see
133  *          GNUNET_TESTBED_test_run()).
134  * @param links_succeeded the number of overlay link connection attempts that
135  *          succeeded
136  * @param links_failed the number of overlay link connection attempts that
137  *          failed
138  * @see GNUNET_TESTBED_test_run()
139  */
140 static void
141 test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num,
142              struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded,
143              unsigned int links_failed)
144 {
145   int i;
146
147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148               "%d peers started. %d links succeeded. %d links failed.\n",
149               num_peers, links_succeeded, links_failed);
150   GNUNET_assert (num == num_peers);
151   GNUNET_assert (0 == links_failed);
152   /* Collect peer information */
153   all_peers_info = GNUNET_new_array (num_peers, struct PeerInfo);
154
155   for (i = 0; i < num_peers; i++)
156   {
157     GNUNET_TESTBED_peer_get_information (peers[i],
158                                          GNUNET_TESTBED_PIT_CONFIGURATION,
159                                          &peer_info_cb, peers[i]);
160   }
161 }
162
163
164 /**
165  * Verify that the user passed correct CL args
166  *
167  * @return #GNUNET_OK if arguments are valid, #GNUNET_SYSERR otherwise
168  */
169 static int
170 verify_args ()
171 {
172   if (num_peers < 3)
173   {
174     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
175                 _
176                 ("Invalid or missing number of peers. Set at least 3 peers.\n"));
177     return GNUNET_SYSERR;
178   }
179   return GNUNET_OK;
180 }
181
182
183 /**
184  * Actual main function.
185  *
186  * @param cls unused
187  * @param args remaining args, unused
188  * @param cfgfile name of the configuration
189  * @param cfg configuration handle
190  */
191 static void
192 run (void *cls, char *const *args, const char *cf,
193      const struct GNUNET_CONFIGURATION_Handle *c)
194 {
195   struct GNUNET_CONFIGURATION_Handle *cfg;
196   double links;
197
198   if (GNUNET_OK != verify_args ())
199   {
200     do_shutdown ();
201     return;
202   }
203   cfg = GNUNET_CONFIGURATION_create ();
204   GNUNET_CONFIGURATION_load (cfg, cfg_filename);
205   links = log (num_peers) * log (num_peers) * num_peers / 2;
206   GNUNET_CONFIGURATION_set_value_number ((struct GNUNET_CONFIGURATION_Handle *)
207                                          cfg, "TESTBED", "OVERLAY_RANDOM_LINKS",
208                                          (unsigned long long int) links);
209   GNUNET_TESTBED_run (NULL, cfg, num_peers, 0, NULL, NULL, &test_master, NULL);
210 }
211
212
213 /**
214  * Main function.
215  *
216  * @return 0 on success
217  */
218 int
219 main (int argc, char *const *argv)
220 {
221   static struct GNUNET_GETOPT_CommandLineOption options[] = {
222     {'p', "peers", "COUNT", gettext_noop ("Number of peers to run"), GNUNET_YES,
223      &GNUNET_GETOPT_set_uint, &num_peers},
224     GNUNET_GETOPT_OPTION_END
225   };
226
227   return (GNUNET_OK ==
228           GNUNET_PROGRAM_run (argc, argv, "gnunet-sensor-profiler",
229                               gettext_noop ("Profiler for sensor service"),
230                               options, &run, NULL)) ? ok : 1;
231 }
232
233 /* end of gnunet-sensor-profiler.c */