2 This file is part of GNUnet.
3 (C) 2006 - 2009 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file src/dht/plugin_dhtlog_mysql.c
23 * @brief MySQL logging plugin to record DHT operations to MySQL server
24 * @author Nathan Evans
30 #include "gnunet_util_lib.h"
32 #include <mysql/mysql.h>
35 #define DEBUG_DHTLOG GNUNET_NO
38 * Maximum number of supported parameters for a prepared
39 * statement. Increase if needed.
44 * A generic statement handle to use
45 * for prepared statements. This way,
46 * once the statement is initialized
49 struct StatementHandle
54 MYSQL_STMT *statement;
62 * Whether or not the handle is valid
68 * Type of a callback that will be called for each
69 * data set returned from MySQL.
71 * @param cls user-defined argument
72 * @param num_values number of elements in values
73 * @param values values returned by MySQL
74 * @return GNUNET_OK to continue iterating, GNUNET_SYSERR to abort
76 typedef int (*GNUNET_MysqlDataProcessor) (void *cls,
77 unsigned int num_values,
80 static unsigned long max_varchar_len;
83 * The configuration the DHT service is running with
85 static const struct GNUNET_CONFIGURATION_Handle *cfg;
87 static unsigned long long current_trial = 0; /* I like to assign 0, just to remember */
90 * Connection to the MySQL Server.
94 #define INSERT_QUERIES_STMT "INSERT INTO queries (trialuid, querytype, hops, dhtkeyuid, dhtqueryid, succeeded, nodeuid) "\
95 "VALUES (?, ?, ?, ?, ?, ?, ?)"
96 static struct StatementHandle *insert_query;
98 #define INSERT_ROUTES_STMT "INSERT INTO routes (trialuid, querytype, hops, dhtkeyuid, dhtqueryid, succeeded, nodeuid, from_node, to_node) "\
99 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
100 static struct StatementHandle *insert_route;
102 #define INSERT_NODES_STMT "INSERT INTO nodes (trialuid, nodeid, nodebits) "\
104 static struct StatementHandle *insert_node;
106 #define INSERT_TRIALS_STMT "INSERT INTO trials"\
107 "(starttime, numnodes, topology,"\
108 "topology_percentage, topology_probability,"\
109 "blacklist_topology, connect_topology, connect_topology_option,"\
110 "connect_topology_option_modifier, puts, gets, "\
111 "concurrent, settle_time, num_rounds, malicious_getters,"\
112 "malicious_putters, malicious_droppers, malicious_get_frequency,"\
113 "malicious_put_frequency, stop_closest, stop_found, strict_kademlia, "\
114 "gets_succeeded, message) "\
115 "VALUES (NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
117 static struct StatementHandle *insert_trial;
119 #define INSERT_STAT_STMT "INSERT INTO node_statistics"\
120 "(trialuid, nodeuid, route_requests,"\
121 "route_forwards, result_requests,"\
122 "client_results, result_forwards, gets,"\
123 "puts, data_inserts, find_peer_requests, "\
124 "find_peers_started, gets_started, puts_started, find_peer_responses_received,"\
125 "get_responses_received, find_peer_responses_sent, get_responses_sent) "\
126 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
128 static struct StatementHandle *insert_stat;
130 #define INSERT_GENERIC_STAT_STMT "INSERT INTO generic_stats" \
131 "(trialuid, nodeuid, section, name, value)"\
132 "VALUES (?, ?, ?, ?, ?)"
133 static struct StatementHandle *insert_generic_stat;
135 #define INSERT_DHTKEY_STMT "INSERT INTO dhtkeys (dhtkey, trialuid, keybits) "\
137 static struct StatementHandle *insert_dhtkey;
139 #define UPDATE_TRIALS_STMT "UPDATE trials set endtime=NOW(), gets_succeeded = ? where trialuid = ?"
140 static struct StatementHandle *update_trial;
142 #define UPDATE_CONNECTIONS_STMT "UPDATE trials set totalConnections = ? where trialuid = ?"
143 static struct StatementHandle *update_connection;
145 #define GET_TRIAL_STMT "SELECT MAX( trialuid ) FROM trials"
146 static struct StatementHandle *get_trial;
148 #define GET_TOPOLOGY_STMT "SELECT MAX( topology_uid ) FROM topology"
149 static struct StatementHandle *get_topology;
151 #define GET_DHTKEYUID_STMT "SELECT dhtkeyuid FROM dhtkeys where dhtkey = ? and trialuid = ?"
152 static struct StatementHandle *get_dhtkeyuid;
154 #define GET_NODEUID_STMT "SELECT nodeuid FROM nodes where trialuid = ? and nodeid = ?"
155 static struct StatementHandle *get_nodeuid;
157 #define INSERT_TOPOLOGY_STMT "INSERT INTO topology (trialuid, date, connections) "\
158 "VALUES (?, NOW(), ?)"
159 static struct StatementHandle *insert_topology;
161 #define EXTEND_TOPOLOGY_STMT "INSERT INTO extended_topology (topology_uid, uid_first, uid_second) "\
163 static struct StatementHandle *extend_topology;
165 #define SET_MALICIOUS_STMT "update nodes set malicious_dropper = 1 where trialuid = ? and nodeid = ?"
166 static struct StatementHandle *update_node_malicious;
168 #define UPDATE_TOPOLOGY_STMT "update topology set connections = ? where topology_uid = ?"
169 static struct StatementHandle *update_topology;
172 * Run a query (not a select statement)
174 * @return GNUNET_OK if executed, GNUNET_SYSERR if an error occurred
177 run_statement (const char *statement)
179 mysql_query (conn, statement);
180 if (mysql_error (conn)[0])
182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
184 return GNUNET_SYSERR;
190 * Creates tables if they don't already exist for dht logging
195 #define MRUNS(a) (GNUNET_OK != run_statement (a) )
197 if (MRUNS ("CREATE TABLE IF NOT EXISTS `dhtkeys` ("
198 "dhtkeyuid int(10) unsigned NOT NULL auto_increment COMMENT 'Unique Key given to each query',"
199 "`dhtkey` varchar(255) NOT NULL COMMENT 'The ASCII value of the key being searched for',"
200 "trialuid int(10) unsigned NOT NULL,"
201 "keybits blob NOT NULL,"
202 "UNIQUE KEY `dhtkeyuid` (`dhtkeyuid`)"
203 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
204 return GNUNET_SYSERR;
206 if (MRUNS ("CREATE TABLE IF NOT EXISTS `nodes` ("
207 "`nodeuid` int(10) unsigned NOT NULL auto_increment,"
208 "`trialuid` int(10) unsigned NOT NULL,"
209 "`nodeid` varchar(255) NOT NULL,"
210 "`nodebits` blob NOT NULL,"
211 "PRIMARY KEY (`nodeuid`)"
212 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
213 return GNUNET_SYSERR;
215 if (MRUNS ("CREATE TABLE IF NOT EXISTS `queries` ("
216 "`trialuid` int(10) unsigned NOT NULL,"
217 "`queryuid` int(10) unsigned NOT NULL auto_increment,"
218 "`dhtqueryid` bigint(20) NOT NULL,"
219 "`querytype` enum('1','2','3','4','5') NOT NULL,"
220 "`hops` int(10) unsigned NOT NULL,"
221 "`succeeded` tinyint NOT NULL,"
222 "`nodeuid` int(10) unsigned NOT NULL,"
223 "`time` timestamp NOT NULL default CURRENT_TIMESTAMP,"
224 "`dhtkeyuid` int(10) unsigned NOT NULL,"
225 "PRIMARY KEY (`queryuid`)"
226 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
227 return GNUNET_SYSERR;
229 if (MRUNS ("CREATE TABLE IF NOT EXISTS `routes` ("
230 "`trialuid` int(10) unsigned NOT NULL,"
231 "`queryuid` int(10) unsigned NOT NULL auto_increment,"
232 "`dhtqueryid` bigint(20) NOT NULL,"
233 "`querytype` enum('1','2','3','4','5') NOT NULL,"
234 "`hops` int(10) unsigned NOT NULL,"
235 "`succeeded` tinyint NOT NULL,"
236 "`nodeuid` int(10) unsigned NOT NULL,"
237 "`time` timestamp NOT NULL default CURRENT_TIMESTAMP,"
238 "`dhtkeyuid` int(10) unsigned NOT NULL,"
239 "`from_node` int(10) unsigned NOT NULL,"
240 "`to_node` int(10) unsigned NOT NULL,"
241 "PRIMARY KEY (`queryuid`)"
242 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
243 return GNUNET_SYSERR;
245 if (MRUNS ("CREATE TABLE IF NOT EXISTS `trials` ("
246 "`trialuid` int(10) unsigned NOT NULL auto_increment,"
247 "`numnodes` int(10) unsigned NOT NULL,"
248 "`topology` int(10) NOT NULL,"
249 "`starttime` datetime NOT NULL,"
250 "`endtime` datetime NOT NULL,"
251 "`puts` int(10) unsigned NOT NULL,"
252 "`gets` int(10) unsigned NOT NULL,"
253 "`concurrent` int(10) unsigned NOT NULL,"
254 "`settle_time` int(10) unsigned NOT NULL,"
255 "`totalConnections` int(10) unsigned NOT NULL,"
256 "`message` text NOT NULL,"
257 "`num_rounds` int(10) unsigned NOT NULL,"
258 "`malicious_getters` int(10) unsigned NOT NULL,"
259 "`malicious_putters` int(10) unsigned NOT NULL,"
260 "`malicious_droppers` int(10) unsigned NOT NULL,"
261 "`totalMessagesDropped` int(10) unsigned NOT NULL,"
262 "`totalBytesDropped` int(10) unsigned NOT NULL,"
263 "`topology_modifier` double NOT NULL,"
264 "`logNMultiplier` double NOT NULL,"
265 "`maxnetbps` bigint(20) unsigned NOT NULL,"
266 "`unknownPeers` int(10) unsigned NOT NULL,"
267 "PRIMARY KEY (`trialuid`),"
268 "UNIQUE KEY `trialuid` (`trialuid`)"
269 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
270 return GNUNET_SYSERR;
272 if (MRUNS ("CREATE TABLE IF NOT EXISTS `topology` ("
273 "`topology_uid` int(10) unsigned NOT NULL AUTO_INCREMENT,"
274 "`trialuid` int(10) unsigned NOT NULL,"
275 "`date` datetime NOT NULL,"
276 "`connections` int(10) unsigned NOT NULL,"
277 "PRIMARY KEY (`topology_uid`)) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
278 return GNUNET_SYSERR;
280 if (MRUNS ("CREATE TABLE IF NOT EXISTS `extended_topology` ("
281 "`extended_uid` int(10) unsigned NOT NULL AUTO_INCREMENT,"
282 "`topology_uid` int(10) unsigned NOT NULL,"
283 "`uid_first` int(10) unsigned NOT NULL,"
284 "`uid_second` int(10) unsigned NOT NULL,"
285 "PRIMARY KEY (`extended_uid`)"
286 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
287 return GNUNET_SYSERR;
289 if (MRUNS ("CREATE TABLE IF NOT EXISTS `node_statistics` ("
290 "`stat_uid` int(10) unsigned NOT NULL AUTO_INCREMENT,"
291 "`trialuid` int(10) unsigned NOT NULL,"
292 "`nodeuid` int(10) unsigned NOT NULL,"
293 "`route_requests` int(10) unsigned NOT NULL,"
294 "`route_forwards` int(10) unsigned NOT NULL,"
295 "`result_requests` int(10) unsigned NOT NULL,"
296 "`client_results` int(10) unsigned NOT NULL,"
297 "`result_forwards` int(10) unsigned NOT NULL,"
298 "`gets` int(10) unsigned NOT NULL,"
299 "`puts` int(10) unsigned NOT NULL,"
300 "`data_inserts` int(10) unsigned NOT NULL,"
301 "`find_peer_requests` int(10) unsigned NOT NULL,"
302 "`find_peers_started` int(10) unsigned NOT NULL,"
303 "`gets_started` int(10) unsigned NOT NULL,"
304 "`puts_started` int(10) unsigned NOT NULL,"
305 "`find_peer_responses_received` int(10) unsigned NOT NULL,"
306 "`get_responses_received` int(10) unsigned NOT NULL,"
307 "`find_peer_responses_sent` int(10) unsigned NOT NULL,"
308 "`get_responses_sent` int(10) unsigned NOT NULL,"
309 "PRIMARY KEY (`stat_uid`)"
310 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;"))
311 return GNUNET_SYSERR;
313 if (MRUNS ("SET AUTOCOMMIT = 1"))
314 return GNUNET_SYSERR;
321 * Create a prepared statement.
323 * @return NULL on error
325 struct StatementHandle *
326 prepared_statement_create (const char *statement)
328 struct StatementHandle *ret;
330 ret = GNUNET_malloc (sizeof (struct StatementHandle));
331 ret->query = GNUNET_strdup (statement);
336 * Close a prepared statement.
338 * @return NULL on error
341 prepared_statement_close (struct StatementHandle *s)
348 GNUNET_free_non_null(s->query);
350 if (s->valid == GNUNET_YES)
351 mysql_stmt_close(s->statement);
356 * Initialize the prepared statements for use with dht test logging
359 iopen (struct GNUNET_DHTLOG_Plugin *plugin)
363 unsigned int timeout;
368 unsigned long long port;
370 conn = mysql_init (NULL);
372 return GNUNET_SYSERR;
374 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
378 database = GNUNET_strdup("gnunet");
381 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
382 "MYSQL", "USER", &user))
384 user = GNUNET_strdup("dht");
387 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
388 "MYSQL", "PASSWORD", &password))
390 password = GNUNET_strdup("dhttest**");
393 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
394 "MYSQL", "SERVER", &server))
396 server = GNUNET_strdup("localhost");
399 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (plugin->cfg,
400 "MYSQL", "MYSQL_PORT", &port))
405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to mysql with: user %s, pass %s, server %s, database %s, port %d\n",
406 user, password, server, database, port);
409 timeout = 60; /* in seconds */
410 mysql_options (conn, MYSQL_OPT_RECONNECT, &reconnect);
412 MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout);
413 mysql_options(conn, MYSQL_SET_CHARSET_NAME, "UTF8");
414 mysql_options (conn, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout);
415 mysql_options (conn, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout);
416 mysql_real_connect (conn, server, user, password,
417 database, (unsigned int) port, NULL, CLIENT_IGNORE_SIGPIPE);
419 GNUNET_free_non_null(server);
420 GNUNET_free_non_null(password);
421 GNUNET_free_non_null(user);
422 GNUNET_free_non_null(database);
424 if (mysql_error (conn)[0])
426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
427 "mysql_real_connect");
428 return GNUNET_SYSERR;
432 db = GNUNET_MYSQL_database_open (coreAPI->ectx, coreAPI->cfg);
434 return GNUNET_SYSERR;
439 #define PINIT(a,b) (NULL == (a = prepared_statement_create(b)))
440 if (PINIT (insert_query, INSERT_QUERIES_STMT) ||
441 PINIT (insert_route, INSERT_ROUTES_STMT) ||
442 PINIT (insert_trial, INSERT_TRIALS_STMT) ||
443 PINIT (insert_stat, INSERT_STAT_STMT) ||
444 PINIT (insert_generic_stat, INSERT_GENERIC_STAT_STMT) ||
445 PINIT (insert_node, INSERT_NODES_STMT) ||
446 PINIT (insert_dhtkey, INSERT_DHTKEY_STMT) ||
447 PINIT (update_trial, UPDATE_TRIALS_STMT) ||
448 PINIT (get_dhtkeyuid, GET_DHTKEYUID_STMT) ||
449 PINIT (get_nodeuid, GET_NODEUID_STMT) ||
450 PINIT (update_connection, UPDATE_CONNECTIONS_STMT) ||
451 PINIT (get_trial, GET_TRIAL_STMT) ||
452 PINIT (get_topology, GET_TOPOLOGY_STMT) ||
453 PINIT (insert_topology, INSERT_TOPOLOGY_STMT) ||
454 PINIT (update_topology, UPDATE_TOPOLOGY_STMT) ||
455 PINIT (extend_topology, EXTEND_TOPOLOGY_STMT) ||
456 PINIT (update_node_malicious, SET_MALICIOUS_STMT) )
458 return GNUNET_SYSERR;
466 return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values)
472 * Prepare a statement for running.
474 * @return GNUNET_OK on success
477 prepare_statement (struct StatementHandle *ret)
479 if (GNUNET_YES == ret->valid)
482 ret->statement = mysql_stmt_init (conn);
483 if (ret->statement == NULL)
484 return GNUNET_SYSERR;
486 if (mysql_stmt_prepare (ret->statement, ret->query, strlen (ret->query)))
488 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
489 "mysql_stmt_prepare `%s', %s", ret->query, mysql_error(conn));
490 mysql_stmt_close (ret->statement);
491 ret->statement = NULL;
492 return GNUNET_SYSERR;
494 ret->valid = GNUNET_YES;
499 * Bind the parameters for the given MySQL statement
502 * @param s statement to bind and run
503 * @param ap arguments for the binding
504 * @return GNUNET_SYSERR on error, GNUNET_OK on success
507 init_params (struct StatementHandle *s, va_list ap)
509 MYSQL_BIND qbind[MAX_PARAM];
512 enum enum_field_types ft;
514 pc = mysql_stmt_param_count (s->statement);
517 /* increase internal constant! */
519 return GNUNET_SYSERR;
521 memset (qbind, 0, sizeof (qbind));
524 while ((pc > 0) && (-1 != (ft = va_arg (ap, enum enum_field_types))))
526 qbind[off].buffer_type = ft;
529 case MYSQL_TYPE_FLOAT:
530 qbind[off].buffer = va_arg (ap, float *);
532 case MYSQL_TYPE_LONGLONG:
533 qbind[off].buffer = va_arg (ap, unsigned long long *);
534 qbind[off].is_unsigned = va_arg (ap, int);
536 case MYSQL_TYPE_LONG:
537 qbind[off].buffer = va_arg (ap, unsigned int *);
538 qbind[off].is_unsigned = va_arg (ap, int);
540 case MYSQL_TYPE_VAR_STRING:
541 case MYSQL_TYPE_STRING:
542 case MYSQL_TYPE_BLOB:
543 qbind[off].buffer = va_arg (ap, void *);
544 qbind[off].buffer_length = va_arg (ap, unsigned long);
545 qbind[off].length = va_arg (ap, unsigned long *);
548 /* unsupported type */
550 return GNUNET_SYSERR;
555 if (!((pc == 0) && (ft != -1) && (va_arg (ap, int) == -1)))
558 return GNUNET_SYSERR;
560 if (mysql_stmt_bind_param (s->statement, qbind))
562 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
563 _("`%s' failed at %s:%d with error: %s\n"),
564 "mysql_stmt_bind_param",
565 __FILE__, __LINE__, mysql_stmt_error (s->statement));
566 return GNUNET_SYSERR;
569 if (mysql_stmt_execute (s->statement))
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 _("`%s' failed at %s:%d with error: %s\n"),
573 "mysql_stmt_execute",
574 __FILE__, __LINE__, mysql_stmt_error (s->statement));
575 return GNUNET_SYSERR;
582 * Run a prepared SELECT statement.
584 * @param result_size number of elements in results array
585 * @param results pointer to already initialized MYSQL_BIND
586 * array (of sufficient size) for passing results
587 * @param processor function to call on each result
588 * @param processor_cls extra argument to processor
589 * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective
590 * values (size + buffer-reference for pointers); terminated
592 * @return GNUNET_SYSERR on error, otherwise
593 * the number of successfully affected (or queried) rows
596 prepared_statement_run_select (struct StatementHandle
597 *s, unsigned int result_size,
598 MYSQL_BIND * results,
599 GNUNET_MysqlDataProcessor
600 processor, void *processor_cls,
608 if (GNUNET_OK != prepare_statement (s))
611 return GNUNET_SYSERR;
613 va_start (ap, processor_cls);
614 if (GNUNET_OK != init_params (s, ap))
618 return GNUNET_SYSERR;
621 rsize = mysql_stmt_field_count (s->statement);
622 if (rsize > result_size)
625 return GNUNET_SYSERR;
627 if (mysql_stmt_bind_result (s->statement, results))
629 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
630 _("`%s' failed at %s:%d with error: %s\n"),
631 "mysql_stmt_bind_result",
632 __FILE__, __LINE__, mysql_stmt_error (s->statement));
633 return GNUNET_SYSERR;
639 ret = mysql_stmt_fetch (s->statement);
640 if (ret == MYSQL_NO_DATA)
644 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
645 _("`%s' failed at %s:%d with error: %s\n"),
647 __FILE__, __LINE__, mysql_stmt_error (s->statement));
648 return GNUNET_SYSERR;
650 if (processor != NULL)
651 if (GNUNET_OK != processor (processor_cls, rsize, results))
655 mysql_stmt_reset (s->statement);
661 get_node_uid (unsigned long long *nodeuid, const GNUNET_HashCode * peerHash)
664 struct GNUNET_CRYPTO_HashAsciiEncoded encPeer;
665 unsigned long long p_len;
668 memset (rbind, 0, sizeof (rbind));
669 rbind[0].buffer_type = MYSQL_TYPE_LONGLONG;
670 rbind[0].buffer = nodeuid;
671 rbind[0].is_unsigned = GNUNET_YES;
673 GNUNET_CRYPTO_hash_to_enc (peerHash, &encPeer);
674 p_len = strlen ((char *) &encPeer);
676 if (1 != (ret = prepared_statement_run_select (get_nodeuid,
684 MYSQL_TYPE_VAR_STRING,
690 fprintf (stderr, "FAILED\n");
692 return GNUNET_SYSERR;
698 get_current_trial (unsigned long long *trialuid)
702 memset (rbind, 0, sizeof (rbind));
703 rbind[0].buffer_type = MYSQL_TYPE_LONG;
704 rbind[0].is_unsigned = 1;
705 rbind[0].buffer = trialuid;
708 prepared_statement_run_select (get_trial,
711 return_ok, NULL, -1)))
713 return GNUNET_SYSERR;
720 get_current_topology (unsigned long long *topologyuid)
724 memset (rbind, 0, sizeof (rbind));
725 rbind[0].buffer_type = MYSQL_TYPE_LONGLONG;
726 rbind[0].is_unsigned = 1;
727 rbind[0].buffer = topologyuid;
730 prepared_statement_run_select (get_topology,
733 return_ok, NULL, -1)))
735 return GNUNET_SYSERR;
742 get_dhtkey_uid (unsigned long long *dhtkeyuid, const GNUNET_HashCode * key)
745 struct GNUNET_CRYPTO_HashAsciiEncoded encKey;
746 unsigned long long k_len;
747 memset (rbind, 0, sizeof (rbind));
748 rbind[0].buffer_type = MYSQL_TYPE_LONG;
749 rbind[0].is_unsigned = 1;
750 rbind[0].buffer = dhtkeyuid;
751 GNUNET_CRYPTO_hash_to_enc (key, &encKey);
752 k_len = strlen ((char *) &encKey);
755 prepared_statement_run_select (get_dhtkeyuid,
759 MYSQL_TYPE_VAR_STRING,
767 return GNUNET_SYSERR;
774 * Run a prepared statement that does NOT produce results.
776 * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective
777 * values (size + buffer-reference for pointers); terminated
779 * @param insert_id NULL or address where to store the row ID of whatever
780 * was inserted (only for INSERT statements!)
781 * @return GNUNET_SYSERR on error, otherwise
782 * the number of successfully affected rows
785 prepared_statement_run (struct StatementHandle *s,
786 unsigned long long *insert_id, ...)
791 if (GNUNET_OK != prepare_statement(s))
794 return GNUNET_SYSERR;
796 GNUNET_assert(s->valid == GNUNET_YES);
797 if (s->statement == NULL)
798 return GNUNET_SYSERR;
800 va_start (ap, insert_id);
802 if (GNUNET_OK != init_params (s, ap))
805 return GNUNET_SYSERR;
809 affected = mysql_stmt_affected_rows (s->statement);
810 if (NULL != insert_id)
811 *insert_id = (unsigned long long) mysql_stmt_insert_id (s->statement);
812 mysql_stmt_reset (s->statement);
818 * Inserts the specified trial into the dhttests.trials table
820 * @param trialuid return the trialuid of the newly inserted trial
821 * @param num_nodes how many nodes are in the trial
822 * @param topology integer representing topology for this trial
823 * @param blacklist_topology integer representing blacklist topology for this trial
824 * @param connect_topology integer representing connect topology for this trial
825 * @param connect_topology_option integer representing connect topology option
826 * @param connect_topology_option_modifier float to modify connect option
827 * @param topology_percentage percentage modifier for certain topologies
828 * @param topology_probability probability modifier for certain topologies
829 * @param puts number of puts to perform
830 * @param gets number of gets to perform
831 * @param concurrent number of concurrent requests
832 * @param settle_time time to wait between creating topology and starting testing
833 * @param num_rounds number of times to repeat the trial
834 * @param malicious_getters number of malicious GET peers in the trial
835 * @param malicious_putters number of malicious PUT peers in the trial
836 * @param malicious_droppers number of malicious DROP peers in the trial
837 * @param malicious_get_frequency how often malicious gets are sent
838 * @param malicious_put_frequency how often malicious puts are sent
839 * @param stop_closest stop forwarding PUTs if closest node found
840 * @param stop_found stop forwarding GETs if data found
841 * @param strict_kademlia test used kademlia routing algorithm
842 * @param gets_succeeded how many gets did the test driver report success on
843 * @param message string to put into DB for this trial
845 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
847 int add_trial (unsigned long long *trialuid, unsigned int num_nodes, unsigned int topology,
848 unsigned int blacklist_topology, unsigned int connect_topology,
849 unsigned int connect_topology_option, float connect_topology_option_modifier,
850 float topology_percentage, float topology_probability,
851 unsigned int puts, unsigned int gets, unsigned int concurrent, unsigned int settle_time,
852 unsigned int num_rounds, unsigned int malicious_getters, unsigned int malicious_putters,
853 unsigned int malicious_droppers, unsigned int malicious_get_frequency,
854 unsigned int malicious_put_frequency, unsigned int stop_closest, unsigned int stop_found,
855 unsigned int strict_kademlia, unsigned int gets_succeeded,
860 unsigned long long m_len;
861 m_len = strlen (message);
863 stmt = mysql_stmt_init(conn);
865 (ret = prepared_statement_run (insert_trial, trialuid,
866 MYSQL_TYPE_LONG, &num_nodes, GNUNET_YES,
867 MYSQL_TYPE_LONG, &topology, GNUNET_YES,
868 MYSQL_TYPE_FLOAT, &topology_percentage,
869 MYSQL_TYPE_FLOAT, &topology_probability,
870 MYSQL_TYPE_LONG, &blacklist_topology, GNUNET_YES,
871 MYSQL_TYPE_LONG, &connect_topology, GNUNET_YES,
872 MYSQL_TYPE_LONG, &connect_topology_option, GNUNET_YES,
873 MYSQL_TYPE_FLOAT, &connect_topology_option_modifier,
874 MYSQL_TYPE_LONG, &puts, GNUNET_YES,
875 MYSQL_TYPE_LONG, &gets, GNUNET_YES,
876 MYSQL_TYPE_LONG, &concurrent, GNUNET_YES,
877 MYSQL_TYPE_LONG, &settle_time, GNUNET_YES,
878 MYSQL_TYPE_LONG, &num_rounds, GNUNET_YES,
879 MYSQL_TYPE_LONG, &malicious_getters, GNUNET_YES,
880 MYSQL_TYPE_LONG, &malicious_putters, GNUNET_YES,
881 MYSQL_TYPE_LONG, &malicious_droppers, GNUNET_YES,
882 MYSQL_TYPE_LONG, &malicious_get_frequency, GNUNET_YES,
883 MYSQL_TYPE_LONG, &malicious_put_frequency, GNUNET_YES,
884 MYSQL_TYPE_LONG, &stop_closest, GNUNET_YES,
885 MYSQL_TYPE_LONG, &stop_found, GNUNET_YES,
886 MYSQL_TYPE_LONG, &strict_kademlia, GNUNET_YES,
887 MYSQL_TYPE_LONG, &gets_succeeded, GNUNET_YES,
888 MYSQL_TYPE_BLOB, message, max_varchar_len +
889 max_varchar_len, &m_len,
892 if (ret == GNUNET_SYSERR)
894 mysql_stmt_close(stmt);
895 return GNUNET_SYSERR;
899 get_current_trial (¤t_trial);
901 mysql_stmt_close(stmt);
907 * Inserts the specified stats into the dhttests.node_statistics table
909 * @param peer the peer inserting the statistic
910 * @param route_requests route requests seen
911 * @param route_forwards route requests forwarded
912 * @param result_requests route result requests seen
913 * @param client_requests client requests initiated
914 * @param result_forwards route results forwarded
915 * @param gets get requests handled
916 * @param puts put requests handle
917 * @param data_inserts data inserted at this node
918 * @param find_peer_requests find peer requests seen
919 * @param find_peers_started find peer requests initiated at this node
920 * @param gets_started get requests initiated at this node
921 * @param puts_started put requests initiated at this node
922 * @param find_peer_responses_received find peer responses received locally
923 * @param get_responses_received get responses received locally
924 * @param find_peer_responses_sent find peer responses sent from this node
925 * @param get_responses_sent get responses sent from this node
927 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
930 add_stat (const struct GNUNET_PeerIdentity *peer, unsigned int route_requests,
931 unsigned int route_forwards, unsigned int result_requests,
932 unsigned int client_requests, unsigned int result_forwards,
933 unsigned int gets, unsigned int puts,
934 unsigned int data_inserts, unsigned int find_peer_requests,
935 unsigned int find_peers_started, unsigned int gets_started,
936 unsigned int puts_started, unsigned int find_peer_responses_received,
937 unsigned int get_responses_received, unsigned int find_peer_responses_sent,
938 unsigned int get_responses_sent)
942 unsigned long long peer_uid;
943 unsigned long long return_uid;
945 return GNUNET_SYSERR;
947 if (GNUNET_OK != get_node_uid (&peer_uid, &peer->hashPubKey))
949 return GNUNET_SYSERR;
952 stmt = mysql_stmt_init(conn);
954 (ret = prepared_statement_run (insert_stat,
956 MYSQL_TYPE_LONGLONG, ¤t_trial, GNUNET_YES,
957 MYSQL_TYPE_LONGLONG, &peer_uid, GNUNET_YES,
958 MYSQL_TYPE_LONG, &route_requests, GNUNET_YES,
959 MYSQL_TYPE_LONG, &route_forwards, GNUNET_YES,
960 MYSQL_TYPE_LONG, &result_requests, GNUNET_YES,
961 MYSQL_TYPE_LONG, &client_requests, GNUNET_YES,
962 MYSQL_TYPE_LONG, &result_forwards, GNUNET_YES,
963 MYSQL_TYPE_LONG, &gets, GNUNET_YES,
964 MYSQL_TYPE_LONG, &puts, GNUNET_YES,
965 MYSQL_TYPE_LONG, &data_inserts, GNUNET_YES,
966 MYSQL_TYPE_LONG, &find_peer_requests, GNUNET_YES,
967 MYSQL_TYPE_LONG, &find_peers_started, GNUNET_YES,
968 MYSQL_TYPE_LONG, &gets_started, GNUNET_YES,
969 MYSQL_TYPE_LONG, &puts_started, GNUNET_YES,
970 MYSQL_TYPE_LONG, &find_peer_responses_received, GNUNET_YES,
971 MYSQL_TYPE_LONG, &get_responses_received, GNUNET_YES,
972 MYSQL_TYPE_LONG, &find_peer_responses_sent, GNUNET_YES,
973 MYSQL_TYPE_LONG, &get_responses_sent, GNUNET_YES,
976 if (ret == GNUNET_SYSERR)
978 mysql_stmt_close(stmt);
979 return GNUNET_SYSERR;
983 mysql_stmt_close(stmt);
988 * Inserts the specified stats into the dhttests.generic_stats table
990 * @param peer the peer inserting the statistic
991 * @param name the name of the statistic
992 * @param section the section of the statistic
993 * @param value the value of the statistic
995 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
998 add_generic_stat (const struct GNUNET_PeerIdentity *peer,
1000 const char *section, uint64_t value)
1002 unsigned long long peer_uid;
1003 unsigned long long section_len;
1004 unsigned long long name_len;
1007 return GNUNET_SYSERR;
1009 if (GNUNET_OK != get_node_uid (&peer_uid, &peer->hashPubKey))
1011 return GNUNET_SYSERR;
1014 section_len = strlen(section);
1015 name_len = strlen(name);
1018 (ret = prepared_statement_run (insert_generic_stat,
1020 MYSQL_TYPE_LONGLONG, ¤t_trial, GNUNET_YES,
1021 MYSQL_TYPE_LONGLONG, &peer_uid, GNUNET_YES,
1022 MYSQL_TYPE_VAR_STRING, §ion, max_varchar_len, §ion_len,
1023 MYSQL_TYPE_VAR_STRING, &name, max_varchar_len, &name_len,
1024 MYSQL_TYPE_LONGLONG, &value, GNUNET_YES,
1027 if (ret == GNUNET_SYSERR)
1029 return GNUNET_SYSERR;
1036 * Inserts the specified dhtkey into the dhttests.dhtkeys table,
1037 * stores return value of dhttests.dhtkeys.dhtkeyuid into dhtkeyuid
1039 * @param dhtkeyuid return value
1040 * @param dhtkey hashcode of key to insert
1042 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1045 add_dhtkey (unsigned long long *dhtkeyuid, const GNUNET_HashCode * dhtkey)
1049 struct GNUNET_CRYPTO_HashAsciiEncoded encKey;
1050 unsigned long long k_len;
1051 unsigned long long h_len;
1052 unsigned long long curr_dhtkeyuid;
1053 GNUNET_CRYPTO_hash_to_enc (dhtkey, &encKey);
1054 k_len = strlen ((char *) &encKey);
1055 h_len = sizeof (GNUNET_HashCode);
1057 ret = get_dhtkey_uid(&curr_dhtkeyuid, dhtkey);
1058 if (curr_dhtkeyuid != 0) /* dhtkey already exists */
1060 if (dhtkeyuid != NULL)
1061 *dhtkeyuid = curr_dhtkeyuid;
1066 (ret = prepared_statement_run (insert_dhtkey,
1068 MYSQL_TYPE_VAR_STRING,
1077 sizeof (GNUNET_HashCode),
1080 if (ret == GNUNET_SYSERR)
1082 return GNUNET_SYSERR;
1092 * Inserts the specified node into the dhttests.nodes table
1094 * @param nodeuid the inserted node uid
1095 * @param node the node to insert
1097 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1100 add_node (unsigned long long *nodeuid, struct GNUNET_PeerIdentity * node)
1102 struct GNUNET_CRYPTO_HashAsciiEncoded encPeer;
1103 unsigned long p_len;
1104 unsigned long h_len;
1108 return GNUNET_SYSERR;
1110 GNUNET_CRYPTO_hash_to_enc (&node->hashPubKey, &encPeer);
1111 p_len = (unsigned long) strlen ((char *) &encPeer);
1112 h_len = sizeof (GNUNET_HashCode);
1114 (ret = prepared_statement_run (insert_node,
1116 MYSQL_TYPE_LONGLONG, ¤t_trial, GNUNET_YES,
1117 MYSQL_TYPE_VAR_STRING, &encPeer, max_varchar_len, &p_len,
1118 MYSQL_TYPE_BLOB, &node->hashPubKey, sizeof (GNUNET_HashCode),
1121 if (ret == GNUNET_SYSERR)
1123 return GNUNET_SYSERR;
1130 * Update dhttests.trials table with current server time as end time
1132 * @param trialuid trial to update
1133 * @param gets_succeeded how many gets did the testcase report as successful
1135 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1138 update_trials (unsigned long long trialuid,
1139 unsigned int gets_succeeded)
1144 (ret = prepared_statement_run (update_trial,
1146 MYSQL_TYPE_LONG, &gets_succeeded, GNUNET_YES,
1147 MYSQL_TYPE_LONGLONG, &trialuid, GNUNET_YES,
1150 if (ret == GNUNET_SYSERR)
1152 return GNUNET_SYSERR;
1158 return GNUNET_SYSERR;
1163 * Update dhttests.nodes table setting the identified
1164 * node as a malicious dropper.
1166 * @param peer the peer that was set to be malicious
1168 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1170 int set_malicious (struct GNUNET_PeerIdentity *peer)
1172 unsigned long long p_len;
1176 temp_str = GNUNET_strdup(GNUNET_h2s_full(&peer->hashPubKey));
1177 p_len = strlen(temp_str);
1180 (ret = prepared_statement_run (update_node_malicious,
1182 MYSQL_TYPE_LONGLONG, ¤t_trial, GNUNET_YES,
1183 MYSQL_TYPE_VAR_STRING, temp_str, max_varchar_len, &p_len,
1186 if (ret == GNUNET_SYSERR)
1188 return GNUNET_SYSERR;
1196 * Update dhttests.trials table with total connections information
1198 * @param trialuid the trialuid to update
1199 * @param totalConnections the number of connections
1201 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1204 add_connections (unsigned long long trialuid, unsigned int totalConnections)
1209 (ret = prepared_statement_run (update_connection,
1214 MYSQL_TYPE_LONGLONG,
1215 &trialuid, GNUNET_YES, -1)))
1217 if (ret == GNUNET_SYSERR)
1219 return GNUNET_SYSERR;
1225 return GNUNET_SYSERR;
1229 * Inserts the specified query into the dhttests.queries table
1231 * @param sqlqueruid inserted query uid
1232 * @param queryid dht query id
1233 * @param type type of the query
1234 * @param hops number of hops query traveled
1235 * @param succeeded whether or not query was successful
1236 * @param node the node the query hit
1237 * @param key the key of the query
1239 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1242 add_query (unsigned long long *sqlqueryuid, unsigned long long queryid,
1243 unsigned int type, unsigned int hops, int succeeded,
1244 const struct GNUNET_PeerIdentity * node, const GNUNET_HashCode * key)
1247 unsigned long long peer_uid, key_uid;
1252 && (GNUNET_OK == get_node_uid (&peer_uid, &node->hashPubKey)))
1258 return GNUNET_SYSERR;
1261 if ((key != NULL) && (GNUNET_OK == get_dhtkey_uid (&key_uid, key)))
1265 else if ((key != NULL) && (key->bits[(512 / 8 / sizeof (unsigned int)) - 1] == 42)) /* Malicious marker */
1271 return GNUNET_SYSERR;
1275 (ret = prepared_statement_run (insert_query,
1277 MYSQL_TYPE_LONGLONG,
1286 MYSQL_TYPE_LONGLONG,
1289 MYSQL_TYPE_LONGLONG,
1295 MYSQL_TYPE_LONGLONG,
1296 &peer_uid, GNUNET_YES, -1)))
1298 if (ret == GNUNET_SYSERR)
1300 return GNUNET_SYSERR;
1306 return GNUNET_SYSERR;
1310 * Inserts the specified route information into the dhttests.routes table
1312 * @param sqlqueruid inserted query uid
1313 * @param queryid dht query id
1314 * @param type type of the query
1315 * @param hops number of hops query traveled
1316 * @param succeeded whether or not query was successful
1317 * @param node the node the query hit
1318 * @param key the key of the query
1319 * @param from_node the node that sent the message to node
1320 * @param to_node next node to forward message to
1322 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1325 add_route (unsigned long long *sqlqueryuid, unsigned long long queryid,
1326 unsigned int type, unsigned int hops,
1327 int succeeded, const struct GNUNET_PeerIdentity * node,
1328 const GNUNET_HashCode * key, const struct GNUNET_PeerIdentity * from_node,
1329 const struct GNUNET_PeerIdentity * to_node)
1331 unsigned long long peer_uid = 0;
1332 unsigned long long key_uid = 0;
1333 unsigned long long from_uid = 0;
1334 unsigned long long to_uid = 0;
1337 if (from_node != NULL)
1338 get_node_uid (&from_uid, &from_node->hashPubKey);
1342 if (to_node != NULL)
1343 get_node_uid (&to_uid, &to_node->hashPubKey);
1349 if (1 != get_node_uid (&peer_uid, &node->hashPubKey))
1351 return GNUNET_SYSERR;
1355 return GNUNET_SYSERR;
1359 if (1 != get_dhtkey_uid (&key_uid, key))
1361 return GNUNET_SYSERR;
1365 return GNUNET_SYSERR;
1368 (ret = prepared_statement_run (insert_route,
1370 MYSQL_TYPE_LONGLONG,
1379 MYSQL_TYPE_LONGLONG,
1382 MYSQL_TYPE_LONGLONG,
1388 MYSQL_TYPE_LONGLONG,
1391 MYSQL_TYPE_LONGLONG,
1394 MYSQL_TYPE_LONGLONG,
1395 &to_uid, GNUNET_YES, -1)))
1397 if (ret == GNUNET_SYSERR)
1399 return GNUNET_SYSERR;
1405 return GNUNET_SYSERR;
1409 * Update dhttests.topology table with total connections information
1411 * @param totalConnections the number of connections
1413 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1416 update_current_topology (unsigned int connections)
1419 unsigned long long topologyuid;
1421 get_current_topology(&topologyuid);
1424 (ret = prepared_statement_run (update_topology,
1429 MYSQL_TYPE_LONGLONG,
1430 &topologyuid, GNUNET_YES, -1)))
1432 if (ret == GNUNET_SYSERR)
1434 return GNUNET_SYSERR;
1440 return GNUNET_SYSERR;
1445 * Records the current topology (number of connections, time, trial)
1447 * @param num_connections how many connections are in the topology
1449 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1452 add_topology (int num_connections)
1457 (ret = prepared_statement_run (insert_topology,
1459 MYSQL_TYPE_LONGLONG,
1466 if (ret == GNUNET_SYSERR)
1468 return GNUNET_SYSERR;
1474 return GNUNET_SYSERR;
1479 * Records a connection between two peers in the current topology
1481 * @param first one side of the connection
1482 * @param second other side of the connection
1484 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1487 add_extended_topology (const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second)
1490 unsigned long long first_uid;
1491 unsigned long long second_uid;
1492 unsigned long long topologyuid;
1494 if (GNUNET_OK != get_current_topology(&topologyuid))
1495 return GNUNET_SYSERR;
1496 if (GNUNET_OK != get_node_uid(&first_uid, &first->hashPubKey))
1497 return GNUNET_SYSERR;
1498 if (GNUNET_OK != get_node_uid(&second_uid, &second->hashPubKey))
1499 return GNUNET_SYSERR;
1502 (ret = prepared_statement_run (extend_topology,
1504 MYSQL_TYPE_LONGLONG,
1507 MYSQL_TYPE_LONGLONG,
1510 MYSQL_TYPE_LONGLONG,
1514 if (ret == GNUNET_SYSERR)
1516 return GNUNET_SYSERR;
1522 return GNUNET_SYSERR;
1528 * Provides the dhtlog api
1530 * @param c the configuration to use to connect to a server
1532 * @return the handle to the server, or NULL on error
1535 libgnunet_plugin_dhtlog_mysql_init (void * cls)
1537 struct GNUNET_DHTLOG_Plugin *plugin = cls;
1540 max_varchar_len = 255;
1542 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MySQL DHT Logger: initializing database\n");
1545 if (iopen (plugin) != GNUNET_OK)
1547 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1548 _("Failed to initialize MySQL database connection for dhtlog.\n"));
1552 GNUNET_assert(plugin->dhtlog_api == NULL);
1553 plugin->dhtlog_api = GNUNET_malloc(sizeof(struct GNUNET_DHTLOG_Handle));
1554 plugin->dhtlog_api->insert_trial = &add_trial;
1555 plugin->dhtlog_api->insert_stat = &add_stat;
1556 plugin->dhtlog_api->add_generic_stat = &add_generic_stat;
1557 plugin->dhtlog_api->insert_query = &add_query;
1558 plugin->dhtlog_api->update_trial = &update_trials;
1559 plugin->dhtlog_api->insert_route = &add_route;
1560 plugin->dhtlog_api->insert_node = &add_node;
1561 plugin->dhtlog_api->insert_dhtkey = &add_dhtkey;
1562 plugin->dhtlog_api->update_connections = &add_connections;
1563 plugin->dhtlog_api->insert_topology = &add_topology;
1564 plugin->dhtlog_api->update_topology = &update_current_topology;
1565 plugin->dhtlog_api->insert_extended_topology = &add_extended_topology;
1566 plugin->dhtlog_api->set_malicious = &set_malicious;
1567 plugin->dhtlog_api->add_generic_stat = &add_generic_stat;
1568 get_current_trial (¤t_trial);
1574 * Shutdown the plugin.
1577 libgnunet_plugin_dhtlog_mysql_done (void * cls)
1579 struct GNUNET_DHTLOG_Handle *dhtlog_api = cls;
1581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1582 "MySQL DHT Logger: database shutdown\n");
1583 GNUNET_assert(dhtlog_api != NULL);
1584 prepared_statement_close(insert_query);
1585 prepared_statement_close(insert_route);
1586 prepared_statement_close(insert_trial);
1587 prepared_statement_close(insert_node);
1588 prepared_statement_close(insert_dhtkey);
1589 prepared_statement_close(update_trial);
1590 prepared_statement_close(get_dhtkeyuid);
1591 prepared_statement_close(get_nodeuid);
1592 prepared_statement_close(update_connection);
1593 prepared_statement_close(get_trial);
1594 prepared_statement_close(get_topology);
1595 prepared_statement_close(insert_topology);
1596 prepared_statement_close(update_topology);
1597 prepared_statement_close(extend_topology);
1598 prepared_statement_close(update_node_malicious);
1603 mysql_library_end();
1604 GNUNET_free(dhtlog_api);
1608 /* end of plugin_dhtlog_mysql.c */