added statistics support
[oweals/gnunet.git] / src / experimentation / test_experimentation_clique.c
1 /*
2   This file is part of GNUnet
3   (C) 2008--2013 Christian Grothoff (and other contributing authors)
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  * @file src/testbed/test_testbed_api_topology.c
23  * @brief test case to connect experimentation daemons in a clique
24  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
25  * @author Matthias Wachs
26  */
27
28 #include "platform.h"
29 #include "gnunet_common.h"
30 #include "gnunet_testbed_service.h"
31
32
33 /**
34  * Number of peers we want to start
35  */
36 #define NUM_PEERS 5
37
38 /**
39  * Array of peers
40  */
41 static struct GNUNET_TESTBED_Peer **peers;
42
43 /**
44  * Operation handle
45  */
46 static struct GNUNET_TESTBED_Operation *op;
47
48 /**
49  * Shutdown task
50  */
51 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
52
53 /**
54  * Testing result
55  */
56 static int result;
57
58 /**
59  * Counter for counting overlay connections
60  */
61 static unsigned int overlay_connects;
62
63 /**
64  * Information we track for a peer in the testbed.
65  */
66 struct ExperimentationPeer
67 {
68   /**
69    * Handle with testbed.
70    */
71   struct GNUNET_TESTBED_Peer *daemon;
72
73   /**
74    * Testbed operation to connect to statistics service
75    */
76   struct GNUNET_TESTBED_Operation *stat_op;
77
78   /**
79    * Handle to the statistics service
80    */
81   struct GNUNET_STATISTICS_Handle *sh;
82 };
83
84 struct ExperimentationPeer ph[NUM_PEERS];
85
86 /**
87  * Shutdown nicely
88  *
89  * @param cls NULL
90  * @param tc the task context
91  */
92 static void
93 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
94 {
95   unsigned int peer;
96         shutdown_task = GNUNET_SCHEDULER_NO_TASK;
97
98   for (peer = 0; peer < NUM_PEERS; peer++)
99   {
100         if (NULL != ph[peer].stat_op)
101                 GNUNET_TESTBED_operation_done (ph[peer].stat_op);
102         ph[peer].stat_op = NULL;
103   }
104
105   if (NULL != op)
106   {
107     GNUNET_TESTBED_operation_done (op);
108     op = NULL;
109   }
110   GNUNET_SCHEDULER_shutdown ();
111 }
112
113 /**
114  * Controller event callback
115  *
116  * @param cls NULL
117  * @param event the controller event
118  */
119 static void
120 controller_event_cb (void *cls,
121                      const struct GNUNET_TESTBED_EventInformation *event)
122 {
123   switch (event->type)
124   {
125   case GNUNET_TESTBED_ET_CONNECT:
126     overlay_connects++;
127     if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects)
128     {
129       result = GNUNET_OK;
130       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers connected \n", NUM_PEERS);
131
132       //GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
133     }
134     break;
135   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
136     break;
137   default:
138     GNUNET_break (0);
139     result = GNUNET_SYSERR;
140     GNUNET_SCHEDULER_cancel (shutdown_task);
141     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
142   }
143 }
144
145
146 /**
147  * Callback function to process statistic values.
148  *
149  * @param cls struct StatsContext
150  * @param subsystem name of subsystem that created the statistic
151  * @param name the name of the datum
152  * @param value the current value
153  * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
154  * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
155  */
156 static int
157 stat_iterator (void *cls, const char *subsystem, const char *name,
158                      uint64_t value, int is_persistent)
159 {
160         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "STATS `%s' %s %llu\n", subsystem, name, value);
161         return GNUNET_OK;
162 }
163
164 /**
165  * Called after successfully opening a connection to a peer's statistics
166  * service; we register statistics monitoring here.
167  *
168  * @param cls the callback closure from functions generating an operation
169  * @param op the operation that has been finished
170  * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
171  * @param emsg error message in case the operation has failed; will be NULL if
172  *          operation has executed successfully.
173  */
174 static void
175 stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
176               void *ca_result, const char *emsg )
177 {
178   struct GNUNET_STATISTICS_Handle *sh = ca_result;
179   struct ExperimentationPeer *peer = cls;
180
181   if (NULL != emsg)
182   {
183     GNUNET_break (0);
184     return;
185   }
186
187   GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
188                 (sh, "experimentation", "# nodes active",
189                  stat_iterator, peer));
190   GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
191                 (sh, "experimentation", "# nodes inactive",
192                  stat_iterator, peer));
193   GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
194                 (sh, "experimentation", "# nodes requested",
195                  stat_iterator, peer));
196 }
197
198 /**
199  * Called to open a connection to the peer's statistics
200  *
201  * @param cls peer context
202  * @param cfg configuration of the peer to connect to; will be available until
203  *          GNUNET_TESTBED_operation_done() is called on the operation returned
204  *          from GNUNET_TESTBED_service_connect()
205  * @return service handle to return in 'op_result', NULL on error
206  */
207 static void *
208 stat_connect_adapter (void *cls,
209                       const struct GNUNET_CONFIGURATION_Handle *cfg)
210 {
211   struct ExperimentationPeer *peer = cls;
212   peer->sh = GNUNET_STATISTICS_create ("experimentation", cfg);
213   if (NULL == peer->sh)
214     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create statistics \n");
215   return peer->sh;
216 }
217
218
219 /**
220  * Called to disconnect from peer's statistics service
221  *
222  * @param cls peer context
223  * @param op_result service handle returned from the connect adapter
224  */
225 static void
226 stat_disconnect_adapter (void *cls, void *op_result)
227 {
228   struct ExperimentationPeer *peer = cls;
229
230   GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
231                 (peer->sh, "experimentation", "# nodes active",
232                  stat_iterator, peer));
233   GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
234                 (peer->sh, "experimentation", "# nodes inactive",
235                  stat_iterator, peer));
236   GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
237                 (peer->sh, "experimentation", "# nodes requested",
238                  stat_iterator, peer));
239   GNUNET_STATISTICS_destroy (op_result, GNUNET_NO);
240   peer->sh = NULL;
241 }
242
243
244
245 /**
246  * Signature of a main function for a testcase.
247  *
248  * @param cls closure
249  * @param num_peers number of peers in 'peers'
250  * @param peers_ handle to peers run in the testbed
251  * @param links_succeeded the number of overlay link connection attempts that
252  *          succeeded
253  * @param links_failed the number of overlay link connection attempts that
254  *          failed
255  */
256 static void
257 test_master (void *cls, unsigned int num_peers,
258              struct GNUNET_TESTBED_Peer **peers_,
259              unsigned int links_succeeded,
260              unsigned int links_failed)
261 {
262   unsigned int peer;
263
264   GNUNET_assert (NULL == cls);
265   GNUNET_assert (NUM_PEERS == num_peers);
266   GNUNET_assert (NULL != peers_);
267   for (peer = 0; peer < num_peers; peer++)
268   {
269     GNUNET_assert (NULL != peers_[peer]);
270     /* Connect to peer's statistic service */
271     ph[peer].stat_op = GNUNET_TESTBED_service_connect (NULL,
272                                                                                                                                 peers_[peer], "statistics",
273                                                                                                                                 &stat_comp_cb, &ph[peer],
274                                     &stat_connect_adapter,
275                                     &stat_disconnect_adapter,
276                                     &ph[peer]);
277
278   }
279   peers = peers_;
280   overlay_connects = 0;
281   op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL,
282                                                   NULL,
283                                                   NULL,
284                                                   GNUNET_TESTBED_TOPOLOGY_CLIQUE,
285                                                   /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */
286                                                   /* NUM_PEERS, */
287                                                   GNUNET_TESTBED_TOPOLOGY_OPTION_END);
288   GNUNET_assert (NULL != op);
289   shutdown_task =
290       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
291                                     (GNUNET_TIME_UNIT_SECONDS, 20),
292                                     do_shutdown, NULL);
293 }
294
295
296 /**
297  * Main function
298  */
299 int
300 main (int argc, char **argv)
301 {
302   uint64_t event_mask;
303
304   result = GNUNET_SYSERR;
305   event_mask = 0;
306   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
307   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
308   (void) GNUNET_TESTBED_test_run ("test_experimentation_clique",
309                                   "test_experimentation_clique.conf", NUM_PEERS,
310                                   event_mask, &controller_event_cb, NULL,
311                                   &test_master, NULL);
312   if (GNUNET_OK != result)
313     return 1;
314   return 0;
315 }
316
317 /* end of test_testbed_api_topology.c */