some documentation and bugfix in testcase
[oweals/gnunet.git] / src / datastore / perf_datastore_api_iterators.c
1 /*
2      This file is part of GNUnet.
3      (C) 2004, 2005, 2006, 2007, 2009 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 2, 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  * @file perf_datastore_api_iterators.c
22  * @brief Profile database plugin directly, focusing on iterators.
23  * @author Christian Grothoff
24  */
25
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "plugin_datastore.h"
30
31 /**
32  * Target datastore size (in bytes).  Realistic sizes are
33  * more like 16 GB (not the default of 16 MB); however,
34  * those take too long to run them in the usual "make check"
35  * sequence.  Hence the value used for shipping is tiny.
36  */
37 #define MAX_SIZE 1024LL * 1024 * 128
38
39 #define ITERATIONS 10
40
41 /**
42  * Number of put operations equivalent to 1/10th of MAX_SIZE
43  */
44 #define PUT_10 (MAX_SIZE / 32 / 1024 / ITERATIONS)
45
46 static unsigned long long stored_bytes;
47
48 static unsigned long long stored_entries;
49
50 static unsigned long long stored_ops;
51
52 static struct GNUNET_CONFIGURATION_Handle *cfg;
53
54 static struct GNUNET_SCHEDULER_Handle *sched;
55
56 static int ok;
57
58              
59 static int
60 putValue (struct GNUNET_DATASTORE_PluginFunctions * api, int i, int k)
61 {
62   char value[65536];
63   size_t size;
64   static GNUNET_HashCode key;
65   static int ic;
66   char *msg;
67
68   /* most content is 32k */
69   size = 32 * 1024;
70
71   if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16) == 0)  /* but some of it is less! */
72     size = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 32 * 1024);
73   size = size - (size & 7);     /* always multiple of 8 */
74
75   /* generate random key */
76   key.bits[0] = (unsigned int) GNUNET_TIME_absolute_get ().value;
77   GNUNET_CRYPTO_hash (&key, sizeof (GNUNET_HashCode), &key);
78   memset (value, i, size);
79   if (i > 255)
80     memset (value, i - 255, size / 2);
81   value[0] = k;
82   msg = NULL;
83   if (GNUNET_OK != api->put (api->cls,
84                              &key, 
85                              size,
86                              value,
87                              i,
88                              GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100),
89                              i,
90                              GNUNET_TIME_relative_to_absolute 
91                              (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
92                                                              60 * 60 * 60 * 1000 +
93                                                              GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000))),
94                              &msg));
95     {
96       fprintf (stderr, "E: `%s'", msg);
97       GNUNET_free_non_null (msg);
98       return GNUNET_SYSERR;
99     }
100   ic++;
101   stored_bytes += size;
102   stored_ops++;
103   stored_entries++;
104   GNUNET_free (value);
105   return GNUNET_OK;
106 }
107
108
109 static int
110 iterateDummy (void *cls,
111               void *next_cls,
112               const GNUNET_HashCode * key,
113               uint32_t size,
114               const void *data,
115               uint32_t type,
116               uint32_t priority,
117               uint32_t anonymity,
118               struct GNUNET_TIME_Absolute
119               expiration, 
120               uint64_t uid)
121 {
122   return GNUNET_OK;
123 }
124
125 static int
126 test (struct GNUNET_DATASTORE_PluginFunctions * api)
127 {  
128   int i;
129   int j;
130   struct GNUNET_TIME_Absolute start;
131   struct GNUNET_TIME_Absolute end;
132
133   /* FIXME: CPS the loop! */
134   for (i = 0; i < ITERATIONS; i++)
135     {
136       /* insert data equivalent to 1/10th of MAX_SIZE */
137       start = GNUNET_TIME_absolute_get ();
138       for (j = 0; j < PUT_10; j++)
139         {
140           if (GNUNET_OK != putValue (api, j, i))
141             break;
142         }
143       end = GNUNET_TIME_absolute_get ();
144       printf ("%3u insertion              took %20llums\n", i, end.value - start.value);
145       start = end;
146       api->iter_low_priority (api->cls, 0, &iterateDummy, api);
147       end = GNUNET_TIME_absolute_get ();
148       printf ("%3u low priority iteration took %20llums\n", i,
149               end.value - start.value);
150       start = end;
151       api->iter_ascending_expiration (api->cls, 0, &iterateDummy, api);
152       end = GNUNET_TIME_absolute_get ();
153       printf ("%3u expiration t iteration took %20llums\n", i,
154               end.value - start.value);
155       start = end;
156       api->iter_zero_anonymity (api->cls, 0, &iterateDummy, api);
157       end = GNUNET_TIME_absolute_get ();
158       printf ("%3u non anonymou iteration took %20llums\n", i,
159               end.value - start.value);
160       start = end;
161       api->iter_migration_order (api->cls, 0, &iterateDummy, api);
162       end = GNUNET_TIME_absolute_get ();
163       printf ("%3u migration or iteration took %20llums\n", i,
164               end.value - start.value);
165       start = end;
166       api->iter_all_now (api->cls, 0, &iterateDummy, api);
167       end = GNUNET_TIME_absolute_get ();
168       printf ("%3u all now      iteration took %20llums\n", i,
169               end.value - start.value);
170     }
171   api->drop (api->cls);
172   return GNUNET_OK;
173 }
174
175
176 /**
177  * Load the datastore plugin.
178  */
179 static struct GNUNET_DATASTORE_PluginFunctions *
180 load_plugin ()
181 {
182   static struct GNUNET_DATASTORE_PluginEnvironment env;
183   struct GNUNET_DATASTORE_PluginFunctions * ret; 
184   char *name;
185   char *libname;
186
187   if (GNUNET_OK !=
188       GNUNET_CONFIGURATION_get_value_string (cfg,
189                                              "DATASTORE", "DATABASE", &name))
190     {
191       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
192                   _("No `%s' specified for `%s' in configuration!\n"),
193                   "DATABASE",
194                   "DATASTORE");
195       return NULL;
196     }
197   env.cfg = cfg;
198   env.sched = sched;  
199   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
200               _("Loading `%s' datastore plugin\n"), name);
201   GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", name);
202   GNUNET_assert (NULL != (ret = GNUNET_PLUGIN_load (libname, &env)));
203   GNUNET_free (libname);
204   GNUNET_free (name);
205   return ret;
206 }
207
208
209 /**
210  * Function called when the service shuts
211  * down.  Unloads our datastore plugin.
212  *
213  * @param api api to unload
214  */
215 static void
216 unload_plugin (struct GNUNET_DATASTORE_PluginFunctions * api)
217 {
218   char *name;
219   char *libname;
220
221   if (GNUNET_OK !=
222       GNUNET_CONFIGURATION_get_value_string (cfg,
223                                              "DATASTORE", "DATABASE", &name))
224     {
225       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
226                   _("No `%s' specified for `%s' in configuration!\n"),
227                   "DATABASE",
228                   "DATASTORE");
229       return;
230     }
231   GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", name);
232   GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api));
233   GNUNET_free (libname);
234   GNUNET_free (name);
235 }
236
237
238
239 /**
240  * Last task run during shutdown.  Disconnects us from
241  * the transport and core.
242  */
243 static void
244 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
245 {
246   struct GNUNET_DATASTORE_PluginFunctions *api = cls;
247
248   unload_plugin (api);
249 }
250
251
252
253 static void
254 run (void *cls,
255      struct GNUNET_SCHEDULER_Handle *s,
256      char *const *args,
257      const char *cfgfile, struct GNUNET_CONFIGURATION_Handle *c)
258 {
259   struct GNUNET_DATASTORE_PluginFunctions *api;
260
261   cfg = c;
262   sched = s;
263   api = load_plugin ();
264   test(api);
265   GNUNET_SCHEDULER_add_delayed (sched,
266                                 GNUNET_YES,
267                                 GNUNET_SCHEDULER_PRIORITY_IDLE,
268                                 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
269                                 GNUNET_TIME_UNIT_FOREVER_REL,
270                                 &cleaning_task, api);
271 }
272
273
274 static int
275 check ()
276 {
277   char *const argv[] = { "perf-datastore-api-iterators",
278     "-c",
279     "test_datastore_api_data.conf",
280 #if VERBOSE
281     "-L", "DEBUG",
282 #endif
283     NULL
284   };
285   struct GNUNET_GETOPT_CommandLineOption options[] = {
286     GNUNET_GETOPT_OPTION_END
287   };
288   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
289                       argv, "perf-datastore-api-iterators", "nohelp",
290                       options, &run, NULL);
291   if (ok != 0)
292     fprintf (stderr, "Missed some testcases: %u\n", ok);
293   return ok;
294 }
295
296
297 int
298 main (int argc, char *argv[])
299 {
300   int ret;
301
302   GNUNET_log_setup ("perf-datastore-api-iterators",
303 #if VERBOSE
304                     "DEBUG",
305 #else
306                     "WARNING",
307 #endif
308                     NULL);
309   ret = check ();
310
311   return ret;
312 }
313
314
315 /* end of perf_datastore_api_iterators.c */
316
317