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