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