- Initializing head, tail in datacache struct get_context
[oweals/gnunet.git] / src / dht / gnunet_dht_profiler.c
1 /*
2      This file is part of GNUnet.
3      (C) 2014 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 dht/gnunet_dht_profiler.c
23  * @brief Profiler for GNUnet DHT
24  * @author Sree Harsha Totakura <sreeharsha@totakura.in> 
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_testbed_service.h"
30
31 /**
32  * Number of peers which should perform a PUT out of 100 peers
33  */
34 #define PUT_PROBABILITY 50
35
36 /**
37  * Configuration
38  */
39 static struct GNUNET_CONFIGURATION_Handle *cfg;
40
41 /**
42  * Name of the file with the hosts to run the test over
43  */
44 static char *hosts_file;
45
46 /**
47  * Number of peers
48  */
49 static unsigned int num_peers;
50
51 /**
52  * Context to hold data of peer
53  */
54 struct Context
55 {
56   /**
57    * Testbed operation acting on this peer
58    */
59   struct GNUNET_TESTBED_Operation *op;
60
61   /**
62    * Delay task
63    */
64   struct GNUNET_SCHEDULER_TaskIdentifier delay_task;
65 };
66
67
68 /**
69  * Context for the data we put into DHT
70  */
71 struct DataContext
72 {
73   /**
74    * next ptr for the DLL
75    */
76   struct Data *next;
77
78   /**
79    * prev ptr for the DLL
80    */
81   struct Data *prev;
82
83   /**
84    * The size of the data
85    */
86   size_t size;
87
88   /**
89    * The data follows here
90    */
91 };
92
93
94 /**
95  * An array of contexts.  The size of this array should be equal to @a num_peers
96  */
97 struct Context *a_ctx;
98
99
100 /**
101  * Shutdown task.  Cleanup all resources and operations
102  *
103  * @param cls NULL
104  * @param tc scheduler task context
105  */
106 static void
107 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
108 {
109   unsigned int cnt;
110   
111   if (NULL != a_ctx)
112   {
113     for (cnt=0; cnt < num_peers, cnt++)
114     {
115       if (NULL == a_ctx[cnt].op)
116         continue;
117       GNUNET_TESTBED_operation_done (a_ctx[cnt].op);
118       a_ctx[cnt].op = NULL;
119     }
120     GNUNET_free (a_ctx);
121     a_ctx = NULL;
122   }
123 }
124
125
126 /**
127  * Callback called when DHT service on the peer is started
128  *
129  * @param cls the context
130  * @param op the operation that has been finished
131  * @param emsg error message in case the operation has failed; will be NULL if
132  *          operation has executed successfully.
133  */
134 static void
135 service_started (void *cls,
136                  struct GNUNET_TESTBED_Operation *op,
137                  const char *emsg)
138 {
139   struct Context *ctx = cls;
140
141   GNUNET_assert (NULL != ctx);
142   GNUNET_assert (NULL != ctx->op);
143   GNUNET_TESTBED_operation_done (ctx->op);
144   ctx->op = NULL;
145   if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100)
146       >= PUT_PROBABILITY)
147     return;
148   /* FIXME: connect to the DHT service and wait initwait before starting a PUT */
149 }
150
151
152 /**
153  * Signature of a main function for a testcase.
154  *
155  * @param cls closure
156  * @param h the run handle
157  * @param num_peers number of peers in 'peers'
158  * @param peers handle to peers run in the testbed
159  * @param links_succeeded the number of overlay link connection attempts that
160  *          succeeded
161  * @param links_failed the number of overlay link
162  */
163 static void
164 test_run (void *cls,
165           struct GNUNET_TESTBED_RunHandle *h,
166           unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers,
167           unsigned int links_succeeded,
168           unsigned int links_failed)
169 {
170   int cnt;
171
172   if (NULL == peers)
173   {
174     /* exit */
175     GNUNET_assert (0);
176   }
177   a_ctx = GNUNET_malloc (sizeof (struct Context) * num_peers);
178   for (cnt = 0; cnt < num_peers, cnt++)
179   {
180     a_ctx[cnt].op = GNUNET_TESTBED_peer_manage_service (&a_ctx[cnt],
181                                                         peers[cnt],
182                                                         "dht",
183                                                         &service_started,
184                                                         &a_ctx[cnt],
185                                                         1);
186   }
187 }
188
189
190 /**
191  * Main function that will be run by the scheduler.
192  *
193  * @param cls closure
194  * @param args remaining command-line arguments
195  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
196  * @param config configuration
197  */
198 static void
199 run (void *cls, char *const *args, const char *cfgfile,
200      const struct GNUNET_CONFIGURATION_Handle *config)
201 {
202   uint64_t event_mask;
203   
204   if (0 == num_peers)
205   {
206     LOG (GNUNET_ERROR_TYPE_ERROR, _("Exiting as the number of peers is %u\n"),
207          num_peers);
208     return;
209   }
210   cfg = GNUNET_CONFIGURATION_dup (config);
211   event_mask = 0;
212   GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, NULL,
213                       NULL, &test_run, NULL);
214   abort_task =
215       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_abort,
216                                     NULL);
217 }
218
219
220 /**
221  * Main function.
222  *
223  * @return 0 on success
224  */
225 int
226 main (int argc, char *const *argv)
227 {
228   static struct GNUNET_GETOPT_CommandLineOption options[] = {
229     {'n', "peers", "COUNT",
230      gettext_noop ("number of peers to start"),
231      1, &GNUNET_GETOPT_set_uint, &num_peers},
232     {'H', "hosts", "FILENAME",
233      gettext_noop ("name of the file with the login information for the testbed"),
234      1, &GNUNET_GETOPT_set_string, &hosts_file},
235     {'d', "initwait", "DELAY",
236      gettext_noop ("delay to allow DHT to stabilize after starting the peers"),
237      1, &GNUNET_GETOPT_set_relative_time, &init_wait},
238     {'w', "wait", "DELAY",
239      gettext_noop ("delay between rounds"),
240      1, &GNUNET_GETOPT_set_relative_time, &wait_time},
241     GNUNET_GETOPT_OPTION_END
242   };
243
244   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
245     return 2;
246   if (GNUNET_OK !=
247       GNUNET_PROGRAM_run (argc, argv, "dht-profiler",
248                           gettext_noop
249                           ("Measure quality and performance of the DHT service."),
250                           options, &run, NULL))
251     ok = 1;
252   return ok;
253 }