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