make insert trial easier to not screw up
[oweals/gnunet.git] / src / dht / plugin_dhtlog_mysql_dump_load.c
1 /*
2      This file is part of GNUnet.
3      (C) 2006 - 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 /**
22  * @file src/dht/plugin_dhtlog_mysql_dump_load.c
23  * @brief MySQL logging plugin to record DHT operations to MySQL server,
24  *        but write all queries to file instead of the actual server
25  *        so that they can be imported later.  Since the first attempt
26  *        (writing out SQL queries) seemed rather time consuming on insert,
27  *        this plugin writes out tab separated values instead.
28  *
29  * @author Nathan Evans
30  *
31  * Database: MySQL
32  */
33
34 #include "platform.h"
35 #include "gnunet_util_lib.h"
36 #include "dhtlog.h"
37
38
39 #define DEBUG_DHTLOG GNUNET_NO
40
41 /**
42  * Maximum number of supported parameters for a prepared
43  * statement.  Increase if needed.
44  */
45 #define MAX_PARAM 32
46
47
48 static unsigned long max_varchar_len;
49
50 /**
51  * The configuration the DHT service is running with
52  */
53 static const struct GNUNET_CONFIGURATION_Handle *cfg;
54
55 #define DATE_STR_SIZE 50
56
57 static unsigned int topology_count;
58
59 /**
60  * File(s) to dump all sql statements to.
61  */
62 FILE *outfile;
63 FILE *generic_stat_outfile;
64 FILE *stat_outfile;
65 FILE *node_outfile;
66 FILE *query_outfile;
67 FILE *route_outfile;
68 FILE *dhtkey_outfile;
69 FILE *extended_topology_outfile;
70
71 static char *
72 get_sql_time()
73 {
74   static char date[DATE_STR_SIZE];
75   time_t timetmp;
76   struct tm *tmptr;
77
78   time (&timetmp);
79   memset (date, 0, DATE_STR_SIZE);
80   tmptr = localtime (&timetmp);
81   if (NULL != tmptr)
82     strftime (date, DATE_STR_SIZE, "%Y-%m-%d %H:%M:%S", tmptr);
83   else
84     strcpy (date, "");
85
86   return date;
87 }
88
89 /*
90  * Records the current topology (number of connections, time, trial)
91  *
92  * @param num_connections how many connections are in the topology
93  *
94  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
95  */
96 int
97 add_topology (int num_connections)
98 {
99   int ret;
100   if (outfile == NULL)
101     return GNUNET_SYSERR;
102
103   ret = fprintf(outfile, "insert into topology (trialuid, date, connections) values (@temp_trial, \"%s\", %d);\n", get_sql_time(), num_connections);
104   if (ret < 0)
105     return GNUNET_SYSERR;
106   ret = fprintf(outfile, "select max(topology_uid) from topology into @temp_topology;\n");
107   if (ret >= 0)
108     return GNUNET_OK;
109   return GNUNET_SYSERR;
110 }
111
112 /*
113  * Records a connection between two peers in the current topology
114  *
115  * @param first one side of the connection
116  * @param second other side of the connection
117  *
118  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
119  */
120 int
121 add_extended_topology (const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second)
122 {
123   int ret;
124   if (outfile == NULL)
125     return GNUNET_SYSERR;
126
127   ret = fprintf(extended_topology_outfile, "insert into extended_topology (topology_uid, uid_first, uid_second) values (%u, %s,", topology_count, GNUNET_h2s_full(&first->hashPubKey));
128   if (ret < 0)
129     return GNUNET_SYSERR;
130   ret = fprintf(extended_topology_outfile, "%s);\n", GNUNET_h2s_full(&second->hashPubKey));
131
132   if (ret >= 0)
133     return GNUNET_OK;
134   return GNUNET_SYSERR;
135 }
136
137
138 /*
139  * Inserts the specified trial into the dhttests.trials table
140  *
141  * @param trial_info struct containing the data to insert about this trial
142  *
143  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
144  */
145 int add_trial (struct GNUNET_DHTLOG_TrialInfo *trial_info)
146 {
147   int ret;
148   trial_info->trialuid = 0;
149   if (outfile == NULL)
150     return GNUNET_SYSERR;
151
152   ret = fprintf(outfile, "INSERT INTO trials "
153                          "(starttime, other_trial_identifier, numnodes, topology,"
154                            "blacklist_topology, connect_topology, connect_topology_option,"
155                            "connect_topology_option_modifier, topology_percentage, topology_probability,"
156                            "puts, gets, "
157                            "concurrent, settle_time, num_rounds, malicious_getters,"
158                            "malicious_putters, malicious_droppers, malicious_get_frequency,"
159                            "malicious_put_frequency, stop_closest, stop_found, strict_kademlia, "
160                            "gets_succeeded, message) "
161                            "VALUES (\"%s\", %u, %u, %u, %u, %u, %u, %f, %f, %f, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, \"%s\");\n",
162                            get_sql_time(), trial_info->other_identifier, trial_info->num_nodes, trial_info->topology,
163                            trial_info->blacklist_topology, trial_info->connect_topology,
164                            trial_info->connect_topology_option, trial_info->connect_topology_option_modifier,
165                            trial_info->topology_percentage, trial_info->topology_probability,
166                            trial_info->puts, trial_info->gets, trial_info->concurrent, trial_info->settle_time,
167                            trial_info->num_rounds, trial_info->malicious_getters, trial_info->malicious_putters,
168                            trial_info->malicious_droppers, trial_info->malicious_get_frequency, trial_info->malicious_put_frequency,
169                            trial_info->stop_closest, trial_info->stop_found, trial_info->strict_kademlia, trial_info->gets_succeeded, trial_info->message);
170
171   if (ret < 0)
172     return GNUNET_SYSERR;
173
174   ret = fprintf(outfile, "SELECT MAX( trialuid ) FROM trials into @temp_trial;\n");
175
176   if (ret >= 0)
177     return GNUNET_OK;
178   else
179     return GNUNET_SYSERR;
180 }
181
182
183 /*
184  * Inserts the specified stats into the dhttests.generic_stats table
185  *
186  * @param peer the peer inserting the statistic
187  * @param name the name of the statistic
188  * @param section the section of the statistic
189  * @param value the value of the statistic
190  *
191  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
192  */
193 int
194 add_generic_stat (const struct GNUNET_PeerIdentity *peer,
195                   const char *name,
196                   const char *section, uint64_t value)
197 {
198   if (outfile == NULL)
199     return GNUNET_SYSERR;
200
201   if (peer != NULL)
202     fprintf(generic_stat_outfile, "TRIALUID\t%s\t%s\t%s\t%llu\n", GNUNET_h2s_full(&peer->hashPubKey), section, name, (unsigned long long)value);
203
204   return GNUNET_OK;
205 }
206
207
208 /*
209  * Inserts the specified stats into the dhttests.node_statistics table
210  *
211  * @param peer the peer inserting the statistic
212  * @param route_requests route requests seen
213  * @param route_forwards route requests forwarded
214  * @param result_requests route result requests seen
215  * @param client_requests client requests initiated
216  * @param result_forwards route results forwarded
217  * @param gets get requests handled
218  * @param puts put requests handle
219  * @param data_inserts data inserted at this node
220  * @param find_peer_requests find peer requests seen
221  * @param find_peers_started find peer requests initiated at this node
222  * @param gets_started get requests initiated at this node
223  * @param puts_started put requests initiated at this node
224  * @param find_peer_responses_received find peer responses received locally
225  * @param get_responses_received get responses received locally
226  * @param find_peer_responses_sent find peer responses sent from this node
227  * @param get_responses_sent get responses sent from this node
228  *
229  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
230  */
231 int
232 add_stat (const struct GNUNET_PeerIdentity *peer, unsigned int route_requests,
233           unsigned int route_forwards, unsigned int result_requests,
234           unsigned int client_requests, unsigned int result_forwards,
235           unsigned int gets, unsigned int puts,
236           unsigned int data_inserts, unsigned int find_peer_requests,
237           unsigned int find_peers_started, unsigned int gets_started,
238           unsigned int puts_started, unsigned int find_peer_responses_received,
239           unsigned int get_responses_received, unsigned int find_peer_responses_sent,
240           unsigned int get_responses_sent)
241 {
242   int ret;
243   if (outfile == NULL)
244     return GNUNET_SYSERR;
245
246   if (peer != NULL)
247     ret = fprintf(stat_outfile, "TRIALUID\t%s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\n",
248                                 GNUNET_h2s_full(&peer->hashPubKey),
249                                 route_requests, route_forwards, result_requests,
250                                 client_requests, result_forwards, gets, puts,
251                                 data_inserts, find_peer_requests, find_peers_started,
252                                 gets_started, puts_started, find_peer_responses_received,
253                                 get_responses_received, find_peer_responses_sent,
254                                 get_responses_sent);
255
256   else
257     return GNUNET_SYSERR;
258
259   if (ret >= 0)
260     return GNUNET_OK;
261   else
262     return GNUNET_SYSERR;
263 }
264 /*
265  * Inserts the specified dhtkey into the dhttests.dhtkeys table,
266  * stores return value of dhttests.dhtkeys.dhtkeyuid into dhtkeyuid
267  *
268  * @param dhtkeyuid return value
269  * @param dhtkey hashcode of key to insert
270  *
271  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
272  */
273 int
274 add_dhtkey (unsigned long long *dhtkeyuid, const GNUNET_HashCode * dhtkey)
275 {
276   int ret;
277   if (dhtkeyuid != NULL)
278     *dhtkeyuid = 0;
279
280   if ((dhtkey_outfile == NULL) || (dhtkey == NULL))
281     return GNUNET_SYSERR;
282
283   ret = fprintf(dhtkey_outfile, "TRIALUID\t%s\n", GNUNET_h2s_full(dhtkey));
284
285   if (ret >= 0)
286     return GNUNET_OK;
287   else
288     return GNUNET_SYSERR;
289 }
290
291 /*
292  * Inserts the specified node into the dhttests.nodes table
293  *
294  * @param nodeuid the inserted node uid
295  * @param node the node to insert
296  *
297  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
298  */
299 int
300 add_node (unsigned long long *nodeuid, struct GNUNET_PeerIdentity * node)
301 {
302   int ret;
303
304   if ((node == NULL) || (node_outfile == NULL))
305     return GNUNET_SYSERR;
306
307   ret = fprintf(node_outfile, "TRIALUID\t%s\n", GNUNET_h2s_full(&node->hashPubKey));
308
309   if (ret >= 0)
310     return GNUNET_OK;
311   return GNUNET_SYSERR;
312 }
313
314 /*
315  * Update dhttests.trials table with current server time as end time
316  *
317  * @param trialuid trial to update
318  * @param gets_succeeded how many gets did the testcase report as successful
319  *
320  * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
321  */
322 int
323 update_trials (unsigned long long trialuid,
324                unsigned int gets_succeeded)
325 {
326   int ret;
327 #if DEBUG_DHTLOG
328   if (trialuid != current_trial)
329     {
330       fprintf (stderr,
331                _("Trialuid to update is not equal to current_trial\n"));
332     }
333 #endif
334
335   if (outfile == NULL)
336     return GNUNET_SYSERR;
337
338   ret = fprintf(outfile, "update trials set endtime=\"%s\", gets_succeeded=%u where trialuid = @temp_trial;\n", get_sql_time(), gets_succeeded);
339
340   if (ret >= 0)
341     return GNUNET_OK;
342   else
343     return GNUNET_SYSERR;
344 }
345
346
347 /*
348  * Update dhttests.nodes table setting the identified
349  * node as a malicious dropper.
350  *
351  * @param peer the peer that was set to be malicious
352  *
353  * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
354  */
355 int
356 set_malicious (struct GNUNET_PeerIdentity *peer)
357 {
358   int ret;
359
360   if (outfile == NULL)
361     return GNUNET_SYSERR;
362
363   ret = fprintf(outfile, "update nodes set malicious_dropper = 1 where trialuid = @temp_trial and nodeid = \"%s\";\n", GNUNET_h2s_full(&peer->hashPubKey));
364
365   if (ret >= 0)
366     return GNUNET_OK;
367   else
368     return GNUNET_SYSERR;
369 }
370
371
372 /*
373  * Update dhttests.trials table with total connections information
374  *
375  * @param trialuid the trialuid to update
376  * @param totalConnections the number of connections
377  *
378  * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
379  */
380 int
381 add_connections (unsigned long long trialuid, unsigned int totalConnections)
382 {
383   int ret;
384 #if DEBUG_DHTLOG
385   if (trialuid != current_trial)
386     {
387       fprintf (stderr,
388                _("Trialuid to update is not equal to current_trial(!)(?)\n"));
389     }
390 #endif
391   if (outfile == NULL)
392     return GNUNET_SYSERR;
393
394   ret = fprintf(outfile, "update trials set totalConnections = %u where trialuid = @temp_trial;\n", totalConnections);
395
396   if (ret >= 0)
397     return GNUNET_OK;
398   else
399     return GNUNET_SYSERR;
400 }
401
402
403 /*
404  * Update dhttests.topology table with total connections information
405  *
406  * @param connections the number of connections
407  *
408  * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
409  */
410 int
411 update_topology (unsigned int connections)
412 {
413   int ret;
414   if (outfile == NULL)
415     return GNUNET_SYSERR;
416
417   ret = fprintf(outfile, "update topology set connections = %u where topology_uid = @temp_topology;\n", connections);
418   topology_count++;
419   if (ret >= 0)
420     return GNUNET_OK;
421   else
422     return GNUNET_SYSERR;
423 }
424
425 /*
426  * Inserts the specified query into the dhttests.queries table
427  *
428  * @param sqlqueruid inserted query uid
429  * @param queryid dht query id
430  * @param type type of the query
431  * @param hops number of hops query traveled
432  * @param succeeded whether or not query was successful
433  * @param node the node the query hit
434  * @param key the key of the query
435  *
436  * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
437  */
438 int
439 add_query (unsigned long long *sqlqueryuid, unsigned long long queryid,
440            unsigned int type, unsigned int hops, int succeeded,
441            const struct GNUNET_PeerIdentity * node, const GNUNET_HashCode * key)
442 {
443   int ret;
444
445   if ((outfile == NULL) || (node == NULL) || (key == NULL))
446     return GNUNET_SYSERR;
447
448   if (sqlqueryuid != NULL)
449     *sqlqueryuid = 0;
450
451   ret = fprintf(query_outfile, "TRIALUID\t%s\t", GNUNET_h2s_full(key));
452
453   if (ret < 0)
454     return GNUNET_SYSERR;
455
456   ret = fprintf(query_outfile, "%s\t%llu\t%u\t%u\t%u\n", GNUNET_h2s_full(&node->hashPubKey), queryid, type, hops, succeeded);
457
458   if (ret >= 0)
459     return GNUNET_OK;
460   else
461     return GNUNET_SYSERR;
462 }
463
464 /*
465  * Inserts the specified route information into the dhttests.routes table
466  *
467  * @param sqlqueruid inserted query uid
468  * @param queryid dht query id
469  * @param type type of the query
470  * @param hops number of hops query traveled
471  * @param succeeded whether or not query was successful
472  * @param node the node the query hit
473  * @param key the key of the query
474  * @param from_node the node that sent the message to node
475  * @param to_node next node to forward message to
476  *
477  * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
478  */
479 int
480 add_route (unsigned long long *sqlqueryuid, unsigned long long queryid,
481            unsigned int type, unsigned int hops,
482            int succeeded, const struct GNUNET_PeerIdentity * node,
483            const GNUNET_HashCode * key, const struct GNUNET_PeerIdentity * from_node,
484            const struct GNUNET_PeerIdentity * to_node)
485 {
486   int ret;
487
488   if ((outfile == NULL) || (node == NULL) || (key == NULL))
489     return GNUNET_SYSERR;
490
491   if (sqlqueryuid != NULL)
492     *sqlqueryuid = 0;
493
494   ret = fprintf(route_outfile, "TRIALUID\t%s\t", GNUNET_h2s_full(key));
495   if (ret < 0)
496     return GNUNET_SYSERR;
497
498   ret = fprintf(route_outfile, "%s\t", GNUNET_h2s_full(&node->hashPubKey));
499   if (ret < 0)
500     return GNUNET_SYSERR;
501   if (from_node == NULL)
502     ret = fprintf(route_outfile, "0\t");
503   else
504     ret = fprintf(route_outfile, "%s\t", GNUNET_h2s_full(&from_node->hashPubKey));
505   if (ret < 0)
506     return GNUNET_SYSERR;
507
508   if (to_node == NULL)
509     ret = fprintf(route_outfile, "0\t%llu\t%u\t%u\t%d\n", queryid, type, hops, succeeded);
510   else
511     ret = fprintf(route_outfile, "%s\t%llu\t%u\t%u\t%d\n", GNUNET_h2s_full(&to_node->hashPubKey), queryid, type, hops, succeeded);
512
513   if (ret >= 0)
514     return GNUNET_OK;
515   else
516     return GNUNET_SYSERR;
517 }
518
519 /*
520  * Provides the dhtlog api
521  *
522  * @param c the configuration to use to connect to a server
523  *
524  * @return the handle to the server, or NULL on error
525  */
526 void *
527 libgnunet_plugin_dhtlog_mysql_dump_load_init (void * cls)
528 {
529   struct GNUNET_DHTLOG_Plugin *plugin = cls;
530   char *outfile_name;
531   char *outfile_path;
532   char *fn;
533   int dirwarn;
534
535   cfg = plugin->cfg;
536   max_varchar_len = 255;
537
538   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MySQL (DUMP) DHT Logger: initializing\n");
539
540   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
541                                                          "MYSQLDUMP", "PATH",
542                                                          &outfile_path))
543     {
544       outfile_path = GNUNET_strdup("");
545     }
546
547   GNUNET_asprintf (&outfile_name,
548                    "%s%s-%d",
549                    outfile_path,
550                    "mysqldump",
551                    getpid());
552
553   fn = GNUNET_STRINGS_filename_expand (outfile_name);
554
555   if (fn == NULL)
556     {
557       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to get full path for `%s'\n"), outfile_name);
558       GNUNET_free(outfile_path);
559       GNUNET_free(outfile_name);
560       return NULL;
561     }
562
563   dirwarn = (GNUNET_OK !=  GNUNET_DISK_directory_create_for_file (fn));
564   outfile = FOPEN (fn, "w");
565
566   if (outfile == NULL)
567     {
568       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
569       if (dirwarn)
570         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
571                     _("Failed to create or access directory for log file `%s'\n"),
572                     fn);
573       GNUNET_free(outfile_path);
574       GNUNET_free(outfile_name);
575       GNUNET_free (fn);
576       return NULL;
577     }
578
579   GNUNET_asprintf (&outfile_name,
580                    "%s%s-%d",
581                    outfile_path,
582                    "mysqldump_nodes",
583                    getpid());
584
585   fn = GNUNET_STRINGS_filename_expand (outfile_name);
586
587   if (fn == NULL)
588     {
589       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to get full path for `%s'\n"), outfile_name);
590       GNUNET_free(outfile_path);
591       GNUNET_free(outfile_name);
592       return NULL;
593     }
594
595   dirwarn = (GNUNET_OK !=  GNUNET_DISK_directory_create_for_file (fn));
596   node_outfile = FOPEN (fn, "w");
597
598   if (node_outfile == NULL)
599     {
600       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
601       if (dirwarn)
602         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
603                     _("Failed to create or access directory for log file `%s'\n"),
604                     fn);
605       GNUNET_free(outfile_path);
606       GNUNET_free(outfile_name);
607       GNUNET_free (fn);
608       return NULL;
609     }
610
611   GNUNET_asprintf (&outfile_name,
612                    "%s%s-%d",
613                    outfile_path,
614                    "mysqldump_routes",
615                    getpid());
616
617   fn = GNUNET_STRINGS_filename_expand (outfile_name);
618
619   if (fn == NULL)
620     {
621       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to get full path for `%s'\n"), outfile_name);
622       GNUNET_free(outfile_path);
623       GNUNET_free(outfile_name);
624       return NULL;
625     }
626
627   dirwarn = (GNUNET_OK !=  GNUNET_DISK_directory_create_for_file (fn));
628   route_outfile = FOPEN (fn, "w");
629
630   if (route_outfile == NULL)
631     {
632       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
633       if (dirwarn)
634         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
635                     _("Failed to create or access directory for log file `%s'\n"),
636                     fn);
637       GNUNET_free(outfile_path);
638       GNUNET_free(outfile_name);
639       GNUNET_free (fn);
640       return NULL;
641     }
642
643   GNUNET_asprintf (&outfile_name,
644                    "%s%s-%d",
645                    outfile_path,
646                    "mysqldump_queries",
647                    getpid());
648
649   fn = GNUNET_STRINGS_filename_expand (outfile_name);
650
651   if (fn == NULL)
652     {
653       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to get full path for `%s'\n"), outfile_name);
654       GNUNET_free(outfile_path);
655       GNUNET_free(outfile_name);
656       return NULL;
657     }
658
659   dirwarn = (GNUNET_OK !=  GNUNET_DISK_directory_create_for_file (fn));
660   query_outfile = FOPEN (fn, "w");
661
662   if (query_outfile == NULL)
663     {
664       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
665       if (dirwarn)
666         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
667                     _("Failed to create or access directory for log file `%s'\n"),
668                     fn);
669       GNUNET_free(outfile_path);
670       GNUNET_free(outfile_name);
671       GNUNET_free (fn);
672       return NULL;
673     }
674
675   GNUNET_asprintf (&outfile_name,
676                    "%s%s-%d",
677                    outfile_path,
678                    "mysqldump_stats",
679                    getpid());
680
681   fn = GNUNET_STRINGS_filename_expand (outfile_name);
682
683   if (fn == NULL)
684     {
685       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to get full path for `%s'\n"), outfile_name);
686       GNUNET_free(outfile_path);
687       GNUNET_free(outfile_name);
688       return NULL;
689     }
690
691   dirwarn = (GNUNET_OK !=  GNUNET_DISK_directory_create_for_file (fn));
692   stat_outfile = FOPEN (fn, "w");
693
694   if (stat_outfile == NULL)
695     {
696       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
697       if (dirwarn)
698         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
699                     _("Failed to create or access directory for log file `%s'\n"),
700                     fn);
701       GNUNET_free(outfile_path);
702       GNUNET_free(outfile_name);
703       GNUNET_free (fn);
704       return NULL;
705     }
706
707   GNUNET_asprintf (&outfile_name,
708                    "%s%s-%d",
709                    outfile_path,
710                    "mysqldump_generic_stats",
711                    getpid());
712
713   fn = GNUNET_STRINGS_filename_expand (outfile_name);
714
715   if (fn == NULL)
716     {
717       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to get full path for `%s'\n"), outfile_name);
718       GNUNET_free(outfile_path);
719       GNUNET_free(outfile_name);
720       return NULL;
721     }
722
723   dirwarn = (GNUNET_OK !=  GNUNET_DISK_directory_create_for_file (fn));
724   generic_stat_outfile = FOPEN (fn, "w");
725
726   if (generic_stat_outfile == NULL)
727     {
728       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
729       if (dirwarn)
730         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
731                     _("Failed to create or access directory for log file `%s'\n"),
732                     fn);
733       GNUNET_free(outfile_path);
734       GNUNET_free(outfile_name);
735       GNUNET_free (fn);
736       return NULL;
737     }
738
739   GNUNET_asprintf (&outfile_name,
740                    "%s%s-%d",
741                    outfile_path,
742                    "mysqldump_dhtkey",
743                    getpid());
744
745   fn = GNUNET_STRINGS_filename_expand (outfile_name);
746
747   if (fn == NULL)
748     {
749       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to get full path for `%s'\n"), outfile_name);
750       GNUNET_free(outfile_path);
751       GNUNET_free(outfile_name);
752       return NULL;
753     }
754
755   dirwarn = (GNUNET_OK !=  GNUNET_DISK_directory_create_for_file (fn));
756   dhtkey_outfile = FOPEN (fn, "w");
757
758   if (dhtkey_outfile == NULL)
759     {
760       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
761       if (dirwarn)
762         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
763                     _("Failed to create or access directory for log file `%s'\n"),
764                     fn);
765       GNUNET_free(outfile_path);
766       GNUNET_free(outfile_name);
767       GNUNET_free (fn);
768       return NULL;
769     }
770
771   GNUNET_asprintf (&outfile_name,
772                    "%s%s-%d",
773                    outfile_path,
774                    "mysqldump_extended_topology",
775                    getpid());
776
777   fn = GNUNET_STRINGS_filename_expand (outfile_name);
778
779   if (fn == NULL)
780     {
781       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to get full path for `%s'\n"), outfile_name);
782       GNUNET_free(outfile_path);
783       GNUNET_free(outfile_name);
784       return NULL;
785     }
786
787   dirwarn = (GNUNET_OK !=  GNUNET_DISK_directory_create_for_file (fn));
788   extended_topology_outfile = FOPEN (fn, "w");
789
790   if (extended_topology_outfile == NULL)
791     {
792       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
793       if (dirwarn)
794         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
795                     _("Failed to create or access directory for log file `%s'\n"),
796                     fn);
797       GNUNET_free(outfile_path);
798       GNUNET_free(outfile_name);
799       GNUNET_free (fn);
800       return NULL;
801     }
802
803   GNUNET_free (outfile_path);
804   GNUNET_free (outfile_name);
805   GNUNET_free (fn);
806
807   GNUNET_assert(plugin->dhtlog_api == NULL);
808   plugin->dhtlog_api = GNUNET_malloc(sizeof(struct GNUNET_DHTLOG_Handle));
809   plugin->dhtlog_api->insert_trial = &add_trial;
810   plugin->dhtlog_api->insert_stat = &add_stat;
811   plugin->dhtlog_api->insert_query = &add_query;
812   plugin->dhtlog_api->update_trial = &update_trials;
813   plugin->dhtlog_api->insert_route = &add_route;
814   plugin->dhtlog_api->insert_node = &add_node;
815   plugin->dhtlog_api->insert_dhtkey = &add_dhtkey;
816   plugin->dhtlog_api->update_connections = &add_connections;
817   plugin->dhtlog_api->insert_topology = &add_topology;
818   plugin->dhtlog_api->insert_extended_topology = &add_extended_topology;
819   plugin->dhtlog_api->update_topology = &update_topology;
820   plugin->dhtlog_api->set_malicious = &set_malicious;
821   plugin->dhtlog_api->add_generic_stat = &add_generic_stat;
822
823   return plugin;
824 }
825
826 /**
827  * Shutdown the plugin.
828  */
829 void *
830 libgnunet_plugin_dhtlog_mysql_dump_load_done (void * cls)
831 {
832   struct GNUNET_DHTLOG_Handle *dhtlog_api = cls;
833   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
834               "MySQL DHT Logger: database shutdown\n");
835   GNUNET_assert(dhtlog_api != NULL);
836
837   fclose(outfile);
838   fclose(node_outfile);
839   fclose(query_outfile);
840   fclose(route_outfile);
841   fclose(stat_outfile);
842   fclose(generic_stat_outfile);
843   fclose(extended_topology_outfile);
844   GNUNET_free(dhtlog_api);
845   return NULL;
846 }
847
848 /* end of plugin_dhtlog_mysql_dump_load.c */