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 */
91 static char *password;
95 static char *database;
97 static unsigned long long port;
100 * Connection to the MySQL Server.
104 #define INSERT_QUERIES_STMT "INSERT INTO queries (trialuid, querytype, hops, dhtkeyuid, dhtqueryid, succeeded, nodeuid) "\
105 "VALUES (?, ?, ?, ?, ?, ?, ?)"
106 static struct StatementHandle *insert_query;
108 #define INSERT_ROUTES_STMT "INSERT INTO routes (trialuid, querytype, hops, dhtkeyuid, dhtqueryid, succeeded, nodeuid, from_node, to_node) "\
109 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
110 static struct StatementHandle *insert_route;
112 #define INSERT_NODES_STMT "INSERT INTO nodes (trialuid, nodeid, nodebits) "\
114 static struct StatementHandle *insert_node;
116 #define INSERT_TRIALS_STMT "INSERT INTO trials"\
117 "(starttime, numnodes, topology,"\
118 "topology_percentage, topology_probability,"\
119 "blacklist_topology, connect_topology, connect_topology_option,"\
120 "connect_topology_option_modifier, puts, gets, "\
121 "concurrent, settle_time, num_rounds, malicious_getters,"\
122 "malicious_putters, malicious_droppers, message) "\
123 "VALUES (NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
125 static struct StatementHandle *insert_trial;
127 #define INSERT_DHTKEY_STMT "INSERT INTO dhtkeys (dhtkey, trialuid, keybits) "\
129 static struct StatementHandle *insert_dhtkey;
131 #define UPDATE_TRIALS_STMT "UPDATE trials set endtime=NOW(), total_messages_dropped = ?, total_bytes_dropped = ?, unknownPeers = ? where trialuid = ?"
132 static struct StatementHandle *update_trial;
134 #define UPDATE_CONNECTIONS_STMT "UPDATE trials set totalConnections = ? where trialuid = ?"
135 static struct StatementHandle *update_connection;
137 #define GET_TRIAL_STMT "SELECT MAX( trialuid ) FROM trials"
138 static struct StatementHandle *get_trial;
140 #define GET_TOPOLOGY_STMT "SELECT MAX( topology_uid ) FROM topology"
141 static struct StatementHandle *get_topology;
143 #define GET_DHTKEYUID_STMT "SELECT dhtkeyuid FROM dhtkeys where dhtkey = ? and trialuid = ?"
144 static struct StatementHandle *get_dhtkeyuid;
146 #define GET_NODEUID_STMT "SELECT nodeuid FROM nodes where trialuid = ? and nodeid = ?"
147 static struct StatementHandle *get_nodeuid;
149 #define INSERT_TOPOLOGY_STMT "INSERT INTO topology (trialuid, date, connections) "\
150 "VALUES (?, NOW(), ?)"
151 static struct StatementHandle *insert_topology;
153 #define EXTEND_TOPOLOGY_STMT "INSERT INTO extended_topology (topology_uid, uid_first, uid_second) "\
155 static struct StatementHandle *extend_topology;
157 #define UPDATE_TOPOLOGY_STMT "update topology set connections = ? where topology_uid = ?"
158 static struct StatementHandle *update_topology;
161 * Run a query (not a select statement)
163 * @return GNUNET_OK if executed, GNUNET_SYSERR if an error occurred
166 run_statement (const char *statement)
168 mysql_query (conn, statement);
169 if (mysql_error (conn)[0])
171 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
173 return GNUNET_SYSERR;
179 * Creates tables if they don't already exist for dht logging
184 #define MRUNS(a) (GNUNET_OK != run_statement (a) )
186 if (MRUNS ("CREATE TABLE IF NOT EXISTS `dhtkeys` ("
187 "dhtkeyuid int(10) unsigned NOT NULL auto_increment COMMENT 'Unique Key given to each query',"
188 "`dhtkey` varchar(255) NOT NULL COMMENT 'The ASCII value of the key being searched for',"
189 "trialuid int(10) unsigned NOT NULL,"
190 "keybits blob NOT NULL,"
191 "UNIQUE KEY `dhtkeyuid` (`dhtkeyuid`)"
192 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
193 return GNUNET_SYSERR;
195 if (MRUNS ("CREATE TABLE IF NOT EXISTS `nodes` ("
196 "`nodeuid` int(10) unsigned NOT NULL auto_increment,"
197 "`trialuid` int(10) unsigned NOT NULL,"
198 "`nodeid` varchar(255) NOT NULL,"
199 "`nodebits` blob NOT NULL,"
200 "PRIMARY KEY (`nodeuid`)"
201 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
202 return GNUNET_SYSERR;
204 if (MRUNS ("CREATE TABLE IF NOT EXISTS `queries` ("
205 "`trialuid` int(10) unsigned NOT NULL,"
206 "`queryuid` int(10) unsigned NOT NULL auto_increment,"
207 "`dhtqueryid` bigint(20) NOT NULL,"
208 "`querytype` enum('1','2','3','4','5') NOT NULL,"
209 "`hops` int(10) unsigned NOT NULL,"
210 "`succeeded` tinyint NOT NULL,"
211 "`nodeuid` int(10) unsigned NOT NULL,"
212 "`time` timestamp NOT NULL default CURRENT_TIMESTAMP,"
213 "`dhtkeyuid` int(10) unsigned NOT NULL,"
214 "PRIMARY KEY (`queryuid`)"
215 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
216 return GNUNET_SYSERR;
218 if (MRUNS ("CREATE TABLE IF NOT EXISTS `routes` ("
219 "`trialuid` int(10) unsigned NOT NULL,"
220 "`queryuid` int(10) unsigned NOT NULL auto_increment,"
221 "`dhtqueryid` bigint(20) NOT NULL,"
222 "`querytype` enum('1','2','3','4','5') NOT NULL,"
223 "`hops` int(10) unsigned NOT NULL,"
224 "`succeeded` tinyint NOT NULL,"
225 "`nodeuid` int(10) unsigned NOT NULL,"
226 "`time` timestamp NOT NULL default CURRENT_TIMESTAMP,"
227 "`dhtkeyuid` int(10) unsigned NOT NULL,"
228 "`from_node` int(10) unsigned NOT NULL,"
229 "`to_node` int(10) unsigned NOT NULL,"
230 "PRIMARY KEY (`queryuid`)"
231 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
232 return GNUNET_SYSERR;
234 if (MRUNS ("CREATE TABLE IF NOT EXISTS `trials` ("
235 "`trialuid` int(10) unsigned NOT NULL auto_increment,"
236 "`numnodes` int(10) unsigned NOT NULL,"
237 "`topology` int(10) NOT NULL,"
238 "`starttime` datetime NOT NULL,"
239 "`endtime` datetime NOT NULL,"
240 "`puts` int(10) unsigned NOT NULL,"
241 "`gets` int(10) unsigned NOT NULL,"
242 "`concurrent` int(10) unsigned NOT NULL,"
243 "`settle_time` int(10) unsigned NOT NULL,"
244 "`totalConnections` int(10) unsigned NOT NULL,"
245 "`message` text NOT NULL,"
246 "`num_rounds` int(10) unsigned NOT NULL,"
247 "`malicious_getters` int(10) unsigned NOT NULL,"
248 "`malicious_putters` int(10) unsigned NOT NULL,"
249 "`malicious_droppers` int(10) unsigned NOT NULL,"
250 "`totalMessagesDropped` int(10) unsigned NOT NULL,"
251 "`totalBytesDropped` int(10) unsigned NOT NULL,"
252 "`topology_modifier` double NOT NULL,"
253 "`logNMultiplier` double NOT NULL,"
254 "`maxnetbps` bigint(20) unsigned NOT NULL,"
255 "`unknownPeers` int(10) unsigned NOT NULL,"
256 "PRIMARY KEY (`trialuid`),"
257 "UNIQUE KEY `trialuid` (`trialuid`)"
258 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
259 return GNUNET_SYSERR;
261 if (MRUNS ("CREATE TABLE IF NOT EXISTS `topology` ("
262 "`topology_uid` int(10) unsigned NOT NULL AUTO_INCREMENT,"
263 "`trialuid` int(10) unsigned NOT NULL,"
264 "`date` datetime NOT NULL,"
265 "`connections` int(10) unsigned NOT NULL,"
266 "PRIMARY KEY (`topology_uid`)) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
267 return GNUNET_SYSERR;
269 if (MRUNS ("CREATE TABLE IF NOT EXISTS `extended_topology` ("
270 "`extended_uid` int(10) unsigned NOT NULL AUTO_INCREMENT,"
271 "`topology_uid` int(10) unsigned NOT NULL,"
272 "`uid_first` int(10) unsigned NOT NULL,"
273 "`uid_second` int(10) unsigned NOT NULL,"
274 "PRIMARY KEY (`extended_uid`)"
275 ") ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"))
276 return GNUNET_SYSERR;
278 if (MRUNS ("SET AUTOCOMMIT = 1"))
279 return GNUNET_SYSERR;
286 * Create a prepared statement.
288 * @return NULL on error
290 struct StatementHandle *
291 prepared_statement_create (const char *statement)
293 struct StatementHandle *ret;
295 ret = GNUNET_malloc (sizeof (struct StatementHandle));
296 ret->query = GNUNET_strdup (statement);
301 * Create a prepared statement.
303 * @return NULL on error
306 prepared_statement_close (struct StatementHandle *s)
311 if (s->query != NULL)
312 GNUNET_free(s->query);
313 if (s->valid == GNUNET_YES)
314 mysql_stmt_close(s->statement);
319 * Initialize the prepared statements for use with dht test logging
326 conn = mysql_init (NULL);
328 return GNUNET_SYSERR;
330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to mysql with: user %s, pass %s, server %s, database %s, port %d\n",
331 user, password, server, database, port);
333 mysql_real_connect (conn, server, user, password,
334 database, (unsigned int) port, NULL, 0);
336 if (mysql_error (conn)[0])
338 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
339 "mysql_real_connect");
340 return GNUNET_SYSERR;
344 db = GNUNET_MYSQL_database_open (coreAPI->ectx, coreAPI->cfg);
346 return GNUNET_SYSERR;
351 #define PINIT(a,b) (NULL == (a = prepared_statement_create(b)))
352 if (PINIT (insert_query, INSERT_QUERIES_STMT) ||
353 PINIT (insert_route, INSERT_ROUTES_STMT) ||
354 PINIT (insert_trial, INSERT_TRIALS_STMT) ||
355 PINIT (insert_node, INSERT_NODES_STMT) ||
356 PINIT (insert_dhtkey, INSERT_DHTKEY_STMT) ||
357 PINIT (update_trial, UPDATE_TRIALS_STMT) ||
358 PINIT (get_dhtkeyuid, GET_DHTKEYUID_STMT) ||
359 PINIT (get_nodeuid, GET_NODEUID_STMT) ||
360 PINIT (update_connection, UPDATE_CONNECTIONS_STMT) ||
361 PINIT (get_trial, GET_TRIAL_STMT) ||
362 PINIT (get_topology, GET_TOPOLOGY_STMT) ||
363 PINIT (insert_topology, INSERT_TOPOLOGY_STMT)||
364 PINIT (update_topology, UPDATE_TOPOLOGY_STMT)||
365 PINIT (extend_topology, EXTEND_TOPOLOGY_STMT))
367 return GNUNET_SYSERR;
375 return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values)
381 * Prepare a statement for running.
383 * @return GNUNET_OK on success
386 prepare_statement (struct StatementHandle *ret)
388 if (GNUNET_YES == ret->valid)
391 ret->statement = mysql_stmt_init (conn);
392 if (ret->statement == NULL)
393 return GNUNET_SYSERR;
395 if (mysql_stmt_prepare (ret->statement, ret->query, strlen (ret->query)))
397 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
398 "mysql_stmt_prepare `%s', %s", ret->query, mysql_error(conn));
399 mysql_stmt_close (ret->statement);
400 ret->statement = NULL;
401 return GNUNET_SYSERR;
403 ret->valid = GNUNET_YES;
408 * Bind the parameters for the given MySQL statement
411 * @param s statement to bind and run
412 * @param ap arguments for the binding
413 * @return GNUNET_SYSERR on error, GNUNET_OK on success
416 init_params (struct StatementHandle *s, va_list ap)
418 MYSQL_BIND qbind[MAX_PARAM];
421 enum enum_field_types ft;
423 pc = mysql_stmt_param_count (s->statement);
426 /* increase internal constant! */
428 return GNUNET_SYSERR;
430 memset (qbind, 0, sizeof (qbind));
433 while ((pc > 0) && (-1 != (ft = va_arg (ap, enum enum_field_types))))
435 qbind[off].buffer_type = ft;
438 case MYSQL_TYPE_FLOAT:
439 qbind[off].buffer = va_arg (ap, float *);
441 case MYSQL_TYPE_LONGLONG:
442 qbind[off].buffer = va_arg (ap, unsigned long long *);
443 qbind[off].is_unsigned = va_arg (ap, int);
445 case MYSQL_TYPE_LONG:
446 qbind[off].buffer = va_arg (ap, unsigned int *);
447 qbind[off].is_unsigned = va_arg (ap, int);
449 case MYSQL_TYPE_VAR_STRING:
450 case MYSQL_TYPE_STRING:
451 case MYSQL_TYPE_BLOB:
452 qbind[off].buffer = va_arg (ap, void *);
453 qbind[off].buffer_length = va_arg (ap, unsigned long);
454 qbind[off].length = va_arg (ap, unsigned long *);
457 /* unsupported type */
459 return GNUNET_SYSERR;
464 if (!((pc == 0) && (ft != -1) && (va_arg (ap, int) == -1)))
467 return GNUNET_SYSERR;
469 if (mysql_stmt_bind_param (s->statement, qbind))
471 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
472 _("`%s' failed at %s:%d with error: %s\n"),
473 "mysql_stmt_bind_param",
474 __FILE__, __LINE__, mysql_stmt_error (s->statement));
475 return GNUNET_SYSERR;
478 if (mysql_stmt_execute (s->statement))
480 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
481 _("`%s' failed at %s:%d with error: %s\n"),
482 "mysql_stmt_execute",
483 __FILE__, __LINE__, mysql_stmt_error (s->statement));
484 return GNUNET_SYSERR;
491 * Run a prepared SELECT statement.
493 * @param result_size number of elements in results array
494 * @param results pointer to already initialized MYSQL_BIND
495 * array (of sufficient size) for passing results
496 * @param processor function to call on each result
497 * @param processor_cls extra argument to processor
498 * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective
499 * values (size + buffer-reference for pointers); terminated
501 * @return GNUNET_SYSERR on error, otherwise
502 * the number of successfully affected (or queried) rows
505 prepared_statement_run_select (struct StatementHandle
506 *s, unsigned int result_size,
507 MYSQL_BIND * results,
508 GNUNET_MysqlDataProcessor
509 processor, void *processor_cls,
517 if (GNUNET_OK != prepare_statement (s))
520 return GNUNET_SYSERR;
522 va_start (ap, processor_cls);
523 if (GNUNET_OK != init_params (s, ap))
527 return GNUNET_SYSERR;
530 rsize = mysql_stmt_field_count (s->statement);
531 if (rsize > result_size)
534 return GNUNET_SYSERR;
536 if (mysql_stmt_bind_result (s->statement, results))
538 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
539 _("`%s' failed at %s:%d with error: %s\n"),
540 "mysql_stmt_bind_result",
541 __FILE__, __LINE__, mysql_stmt_error (s->statement));
542 return GNUNET_SYSERR;
548 ret = mysql_stmt_fetch (s->statement);
549 if (ret == MYSQL_NO_DATA)
553 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
554 _("`%s' failed at %s:%d with error: %s\n"),
556 __FILE__, __LINE__, mysql_stmt_error (s->statement));
557 return GNUNET_SYSERR;
559 if (processor != NULL)
560 if (GNUNET_OK != processor (processor_cls, rsize, results))
564 mysql_stmt_reset (s->statement);
570 get_node_uid (unsigned long long *nodeuid, const GNUNET_HashCode * peerHash)
573 struct GNUNET_CRYPTO_HashAsciiEncoded encPeer;
574 unsigned long long p_len;
577 memset (rbind, 0, sizeof (rbind));
578 rbind[0].buffer_type = MYSQL_TYPE_LONGLONG;
579 rbind[0].buffer = nodeuid;
580 rbind[0].is_unsigned = GNUNET_YES;
582 GNUNET_CRYPTO_hash_to_enc (peerHash, &encPeer);
583 p_len = strlen ((char *) &encPeer);
585 if (1 != (ret = prepared_statement_run_select (get_nodeuid,
593 MYSQL_TYPE_VAR_STRING,
599 fprintf (stderr, "FAILED\n");
601 return GNUNET_SYSERR;
607 get_current_trial (unsigned long long *trialuid)
611 memset (rbind, 0, sizeof (rbind));
612 rbind[0].buffer_type = MYSQL_TYPE_LONG;
613 rbind[0].is_unsigned = 1;
614 rbind[0].buffer = trialuid;
617 prepared_statement_run_select (get_trial,
620 return_ok, NULL, -1)))
622 return GNUNET_SYSERR;
629 get_current_topology (unsigned long long *topologyuid)
633 memset (rbind, 0, sizeof (rbind));
634 rbind[0].buffer_type = MYSQL_TYPE_LONGLONG;
635 rbind[0].is_unsigned = 1;
636 rbind[0].buffer = topologyuid;
639 prepared_statement_run_select (get_topology,
642 return_ok, NULL, -1)))
644 return GNUNET_SYSERR;
651 get_dhtkey_uid (unsigned long long *dhtkeyuid, const GNUNET_HashCode * key)
654 struct GNUNET_CRYPTO_HashAsciiEncoded encKey;
655 unsigned long long k_len;
656 memset (rbind, 0, sizeof (rbind));
657 rbind[0].buffer_type = MYSQL_TYPE_LONG;
658 rbind[0].is_unsigned = 1;
659 rbind[0].buffer = dhtkeyuid;
660 GNUNET_CRYPTO_hash_to_enc (key, &encKey);
661 k_len = strlen ((char *) &encKey);
664 prepared_statement_run_select (get_dhtkeyuid,
668 MYSQL_TYPE_VAR_STRING,
676 return GNUNET_SYSERR;
683 * Run a prepared statement that does NOT produce results.
685 * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective
686 * values (size + buffer-reference for pointers); terminated
688 * @param insert_id NULL or address where to store the row ID of whatever
689 * was inserted (only for INSERT statements!)
690 * @return GNUNET_SYSERR on error, otherwise
691 * the number of successfully affected rows
694 prepared_statement_run (struct StatementHandle *s,
695 unsigned long long *insert_id, ...)
700 if (GNUNET_OK != prepare_statement(s))
703 return GNUNET_SYSERR;
705 GNUNET_assert(s->valid == GNUNET_YES);
706 if (s->statement == NULL)
707 return GNUNET_SYSERR;
709 va_start (ap, insert_id);
711 if (mysql_stmt_prepare (s->statement, s->query, strlen (s->query)))
713 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare ERROR");
714 return GNUNET_SYSERR;
717 if (GNUNET_OK != init_params (s, ap))
720 return GNUNET_SYSERR;
724 affected = mysql_stmt_affected_rows (s->statement);
725 if (NULL != insert_id)
726 *insert_id = (unsigned long long) mysql_stmt_insert_id (s->statement);
727 mysql_stmt_reset (s->statement);
733 * Inserts the specified trial into the dhttests.trials table
735 * @param trialuid return the trialuid of the newly inserted trial
736 * @param num_nodes how many nodes are in the trial
737 * @param topology integer representing topology for this trial
738 * @param blacklist_topology integer representing blacklist topology for this trial
739 * @param connect_topology integer representing connect topology for this trial
740 * @param connect_topology_option integer representing connect topology option
741 * @param connect_topology_option_modifier float to modify connect option
742 * @param topology_percentage percentage modifier for certain topologies
743 * @param topology_probability probability modifier for certain topologies
744 * @param puts number of puts to perform
745 * @param gets number of gets to perform
746 * @param concurrent number of concurrent requests
747 * @param settle_time time to wait between creating topology and starting testing
748 * @param num_rounds number of times to repeat the trial
749 * @param malicious_getters number of malicious GET peers in the trial
750 * @param malicious_putters number of malicious PUT peers in the trial
751 * @param malicious_droppers number of malicious DROP peers in the trial
752 * @param message string to put into DB for this trial
754 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
757 add_trial (unsigned long long *trialuid, int num_nodes, int topology,
758 int blacklist_topology, int connect_topology,
759 int connect_topology_option, float connect_topology_option_modifier,
760 float topology_percentage, float topology_probability,
761 int puts, int gets, int concurrent, int settle_time,
762 int num_rounds, int malicious_getters, int malicious_putters,
763 int malicious_droppers, char *message)
767 unsigned long long m_len;
768 m_len = strlen (message);
770 stmt = mysql_stmt_init(conn);
772 (ret = prepared_statement_run (insert_trial,
781 &topology_percentage,
783 &topology_probability,
791 &connect_topology_option,
794 &connect_topology_option_modifier,
822 max_varchar_len, &m_len,
825 if (ret == GNUNET_SYSERR)
827 mysql_stmt_close(stmt);
828 return GNUNET_SYSERR;
832 get_current_trial (¤t_trial);
834 fprintf (stderr, "Current trial is %llu\n", current_trial);
836 mysql_stmt_close(stmt);
841 * Inserts the specified dhtkey into the dhttests.dhtkeys table,
842 * stores return value of dhttests.dhtkeys.dhtkeyuid into dhtkeyuid
844 * @param dhtkeyuid return value
845 * @param dhtkey hashcode of key to insert
847 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
850 add_dhtkey (unsigned long long *dhtkeyuid, const GNUNET_HashCode * dhtkey)
854 struct GNUNET_CRYPTO_HashAsciiEncoded encKey;
855 unsigned long long k_len;
856 unsigned long long h_len;
857 unsigned long long curr_dhtkeyuid;
858 GNUNET_CRYPTO_hash_to_enc (dhtkey, &encKey);
859 k_len = strlen ((char *) &encKey);
860 h_len = sizeof (GNUNET_HashCode);
862 ret = get_dhtkey_uid(&curr_dhtkeyuid, dhtkey);
863 if (curr_dhtkeyuid != 0) /* dhtkey already exists */
865 if (dhtkeyuid != NULL)
866 *dhtkeyuid = curr_dhtkeyuid;
871 (ret = prepared_statement_run (insert_dhtkey,
873 MYSQL_TYPE_VAR_STRING,
882 sizeof (GNUNET_HashCode),
885 if (ret == GNUNET_SYSERR)
887 return GNUNET_SYSERR;
897 * Inserts the specified node into the dhttests.nodes table
899 * @param nodeuid the inserted node uid
900 * @param node the node to insert
902 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
905 add_node (unsigned long long *nodeuid, struct GNUNET_PeerIdentity * node)
907 struct GNUNET_CRYPTO_HashAsciiEncoded encPeer;
913 return GNUNET_SYSERR;
915 GNUNET_CRYPTO_hash_to_enc (&node->hashPubKey, &encPeer);
916 p_len = (unsigned long) strlen ((char *) &encPeer);
917 h_len = sizeof (GNUNET_HashCode);
919 (ret = prepared_statement_run (insert_node,
924 MYSQL_TYPE_VAR_STRING,
930 sizeof (GNUNET_HashCode),
933 if (ret == GNUNET_SYSERR)
935 return GNUNET_SYSERR;
942 * Update dhttests.trials table with current server time as end time
944 * @param trialuid trial to update
945 * @param totalMessagesDropped stats value for messages dropped
946 * @param totalBytesDropped stats value for total bytes dropped
947 * @param unknownPeers stats value for unknown peers
949 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
952 update_trials (unsigned long long trialuid,
953 unsigned long long totalMessagesDropped,
954 unsigned long long totalBytesDropped,
955 unsigned long long unknownPeers)
959 if (trialuid != current_trial)
962 _("Trialuid to update is not equal to current_trial\n"));
966 (ret = prepared_statement_run (update_trial,
969 &totalMessagesDropped,
978 &trialuid, GNUNET_YES, -1)))
980 if (ret == GNUNET_SYSERR)
982 return GNUNET_SYSERR;
988 return GNUNET_SYSERR;
993 * Update dhttests.trials table with total connections information
995 * @param trialuid the trialuid to update
996 * @param totalConnections the number of connections
998 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1001 add_connections (unsigned long long trialuid, unsigned int totalConnections)
1005 if (trialuid != current_trial)
1008 _("Trialuid to update is not equal to current_trial(!)(?)\n"));
1012 (ret = prepared_statement_run (update_connection,
1017 MYSQL_TYPE_LONGLONG,
1018 &trialuid, GNUNET_YES, -1)))
1020 if (ret == GNUNET_SYSERR)
1022 return GNUNET_SYSERR;
1028 return GNUNET_SYSERR;
1032 * Inserts the specified query into the dhttests.queries table
1034 * @param sqlqueruid inserted query uid
1035 * @param queryid dht query id
1036 * @param type type of the query
1037 * @param hops number of hops query traveled
1038 * @param succeeded whether or not query was successful
1039 * @param node the node the query hit
1040 * @param key the key of the query
1042 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1045 add_query (unsigned long long *sqlqueryuid, unsigned long long queryid,
1046 unsigned int type, unsigned int hops, int succeeded,
1047 const struct GNUNET_PeerIdentity * node, const GNUNET_HashCode * key)
1050 unsigned long long peer_uid, key_uid;
1055 && (GNUNET_OK == get_node_uid (&peer_uid, &node->hashPubKey)))
1061 return GNUNET_SYSERR;
1064 if ((key != NULL) && (GNUNET_OK == get_dhtkey_uid (&key_uid, key)))
1068 else if ((key != NULL) && (key->bits[(512 / 8 / sizeof (unsigned int)) - 1] == 42)) /* Malicious marker */
1074 return GNUNET_SYSERR;
1078 (ret = prepared_statement_run (insert_query,
1080 MYSQL_TYPE_LONGLONG,
1089 MYSQL_TYPE_LONGLONG,
1092 MYSQL_TYPE_LONGLONG,
1098 MYSQL_TYPE_LONGLONG,
1099 &peer_uid, GNUNET_YES, -1)))
1101 if (ret == GNUNET_SYSERR)
1103 return GNUNET_SYSERR;
1109 return GNUNET_SYSERR;
1113 * Inserts the specified route information into the dhttests.routes table
1115 * @param sqlqueruid inserted query uid
1116 * @param queryid dht query id
1117 * @param type type of the query
1118 * @param hops number of hops query traveled
1119 * @param succeeded whether or not query was successful
1120 * @param node the node the query hit
1121 * @param key the key of the query
1122 * @param from_node the node that sent the message to node
1123 * @param to_node next node to forward message to
1125 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1128 add_route (unsigned long long *sqlqueryuid, unsigned long long queryid,
1129 unsigned int type, unsigned int hops,
1130 int succeeded, const struct GNUNET_PeerIdentity * node,
1131 const GNUNET_HashCode * key, const struct GNUNET_PeerIdentity * from_node,
1132 const struct GNUNET_PeerIdentity * to_node)
1134 unsigned long long peer_uid = 0;
1135 unsigned long long key_uid = 0;
1136 unsigned long long from_uid = 0;
1137 unsigned long long to_uid = 0;
1140 if (from_node != NULL)
1141 get_node_uid (&from_uid, &from_node->hashPubKey);
1145 if (to_node != NULL)
1146 get_node_uid (&to_uid, &to_node->hashPubKey);
1152 if (1 != get_node_uid (&peer_uid, &node->hashPubKey))
1154 return GNUNET_SYSERR;
1158 return GNUNET_SYSERR;
1162 if (1 != get_dhtkey_uid (&key_uid, key))
1164 return GNUNET_SYSERR;
1168 return GNUNET_SYSERR;
1171 (ret = prepared_statement_run (insert_route,
1173 MYSQL_TYPE_LONGLONG,
1182 MYSQL_TYPE_LONGLONG,
1185 MYSQL_TYPE_LONGLONG,
1191 MYSQL_TYPE_LONGLONG,
1194 MYSQL_TYPE_LONGLONG,
1197 MYSQL_TYPE_LONGLONG,
1198 &to_uid, GNUNET_YES, -1)))
1200 if (ret == GNUNET_SYSERR)
1202 return GNUNET_SYSERR;
1208 return GNUNET_SYSERR;
1212 * Update dhttests.topology table with total connections information
1214 * @param totalConnections the number of connections
1216 * @return GNUNET_OK on success, GNUNET_SYSERR on failure.
1219 update_current_topology (unsigned int connections)
1222 unsigned long long topologyuid;
1224 get_current_topology(&topologyuid);
1227 (ret = prepared_statement_run (update_topology,
1232 MYSQL_TYPE_LONGLONG,
1233 &topologyuid, GNUNET_YES, -1)))
1235 if (ret == GNUNET_SYSERR)
1237 return GNUNET_SYSERR;
1243 return GNUNET_SYSERR;
1248 * Records the current topology (number of connections, time, trial)
1250 * @param num_connections how many connections are in the topology
1252 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1255 add_topology (int num_connections)
1260 (ret = prepared_statement_run (insert_topology,
1262 MYSQL_TYPE_LONGLONG,
1269 if (ret == GNUNET_SYSERR)
1271 return GNUNET_SYSERR;
1277 return GNUNET_SYSERR;
1282 * Records a connection between two peers in the current topology
1284 * @param first one side of the connection
1285 * @param second other side of the connection
1287 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1290 add_extended_topology (const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second)
1293 unsigned long long first_uid;
1294 unsigned long long second_uid;
1295 unsigned long long topologyuid;
1297 if (GNUNET_OK != get_current_topology(&topologyuid))
1298 return GNUNET_SYSERR;
1299 if (GNUNET_OK != get_node_uid(&first_uid, &first->hashPubKey))
1300 return GNUNET_SYSERR;
1301 if (GNUNET_OK != get_node_uid(&second_uid, &second->hashPubKey))
1302 return GNUNET_SYSERR;
1305 (ret = prepared_statement_run (extend_topology,
1307 MYSQL_TYPE_LONGLONG,
1310 MYSQL_TYPE_LONGLONG,
1313 MYSQL_TYPE_LONGLONG,
1317 if (ret == GNUNET_SYSERR)
1319 return GNUNET_SYSERR;
1325 return GNUNET_SYSERR;
1331 * Provides the dhtlog api
1333 * @param c the configuration to use to connect to a server
1335 * @return the handle to the server, or NULL on error
1338 libgnunet_plugin_dhtlog_mysql_init (void * cls)
1340 struct GNUNET_DHTLOG_Plugin *plugin = cls;
1343 max_varchar_len = 255;
1345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MySQL DHT Logger: initializing database\n");
1348 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
1349 "MYSQL", "DATABASE",
1352 database = GNUNET_strdup("gnunet");
1355 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
1356 "MYSQL", "USER", &user))
1358 user = GNUNET_strdup("dht");
1361 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
1362 "MYSQL", "PASSWORD", &password))
1364 password = GNUNET_strdup("dhttest**");
1367 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (plugin->cfg,
1368 "MYSQL", "SERVER", &server))
1370 server = GNUNET_strdup("localhost");
1373 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (plugin->cfg,
1374 "MYSQL", "MYSQL_PORT", &port))
1379 if (iopen () != GNUNET_OK)
1381 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1382 _("Failed to initialize MySQL database connection for dhtlog.\n"));
1385 GNUNET_assert(plugin->dhtlog_api == NULL);
1386 plugin->dhtlog_api = GNUNET_malloc(sizeof(struct GNUNET_DHTLOG_Handle));
1387 plugin->dhtlog_api->insert_trial = &add_trial;
1388 plugin->dhtlog_api->insert_query = &add_query;
1389 plugin->dhtlog_api->update_trial = &update_trials;
1390 plugin->dhtlog_api->insert_route = &add_route;
1391 plugin->dhtlog_api->insert_node = &add_node;
1392 plugin->dhtlog_api->insert_dhtkey = &add_dhtkey;
1393 plugin->dhtlog_api->update_connections = &add_connections;
1394 plugin->dhtlog_api->insert_topology = &add_topology;
1395 plugin->dhtlog_api->update_topology = &update_current_topology;
1396 plugin->dhtlog_api->insert_extended_topology = &add_extended_topology;
1397 get_current_trial (¤t_trial);
1403 * Shutdown the plugin.
1406 libgnunet_plugin_dhtlog_mysql_done (void * cls)
1408 struct GNUNET_DHTLOG_Handle *dhtlog_api = cls;
1410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1411 "MySQL DHT Logger: database shutdown\n");
1413 GNUNET_assert(dhtlog_api != NULL);
1414 prepared_statement_close(insert_query);
1415 prepared_statement_close(insert_route);
1416 prepared_statement_close(insert_trial);
1417 prepared_statement_close(insert_node);
1418 prepared_statement_close(insert_dhtkey);
1419 prepared_statement_close(update_trial);
1420 prepared_statement_close(get_dhtkeyuid);
1421 prepared_statement_close(get_nodeuid);
1422 prepared_statement_close(update_connection);
1423 prepared_statement_close(get_trial);
1424 prepared_statement_close(get_topology);
1425 prepared_statement_close(insert_topology);
1426 prepared_statement_close(update_topology);
1427 prepared_statement_close(extend_topology);
1432 GNUNET_free(dhtlog_api);
1436 /* end of plugin_dhtlog_mysql.c */