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