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