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