diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-03-21 14:45:19 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-03-21 14:45:19 +0000 |
commit | dde852407a26aa2da817e87acc413fe1f50f81dd (patch) | |
tree | 28d255f66f55b71672552d2d4744fd7942a4e1ac /src | |
parent | 17c30ef801a526e67a09d761f137dd25ebea5fe7 (diff) | |
download | gnunet-dde852407a26aa2da817e87acc413fe1f50f81dd.tar.gz gnunet-dde852407a26aa2da817e87acc413fe1f50f81dd.zip |
-using new mysql helper library also with datastore
Diffstat (limited to 'src')
-rw-r--r-- | src/datastore/Makefile.am | 1 | ||||
-rw-r--r-- | src/datastore/plugin_datastore_mysql.c | 677 | ||||
-rw-r--r-- | src/include/gnunet_mysql_lib.h | 49 | ||||
-rw-r--r-- | src/mysql/mysql.c | 127 |
4 files changed, 196 insertions, 658 deletions
diff --git a/src/datastore/Makefile.am b/src/datastore/Makefile.am index 44c5bbee4..9443e52be 100644 --- a/src/datastore/Makefile.am +++ b/src/datastore/Makefile.am | |||
@@ -100,6 +100,7 @@ libgnunet_plugin_datastore_sqlite_la_LDFLAGS = \ | |||
100 | libgnunet_plugin_datastore_mysql_la_SOURCES = \ | 100 | libgnunet_plugin_datastore_mysql_la_SOURCES = \ |
101 | plugin_datastore_mysql.c | 101 | plugin_datastore_mysql.c |
102 | libgnunet_plugin_datastore_mysql_la_LIBADD = \ | 102 | libgnunet_plugin_datastore_mysql_la_LIBADD = \ |
103 | $(top_builddir)/src/mysql/libgnunetmysql.la \ | ||
103 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 104 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
104 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lz -lmysqlclient | 105 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lz -lmysqlclient |
105 | libgnunet_plugin_datastore_mysql_la_LDFLAGS = \ | 106 | libgnunet_plugin_datastore_mysql_la_LDFLAGS = \ |
diff --git a/src/datastore/plugin_datastore_mysql.c b/src/datastore/plugin_datastore_mysql.c index 76d6ad706..e2c77edd8 100644 --- a/src/datastore/plugin_datastore_mysql.c +++ b/src/datastore/plugin_datastore_mysql.c | |||
@@ -119,47 +119,12 @@ | |||
119 | #include "platform.h" | 119 | #include "platform.h" |
120 | #include "gnunet_datastore_plugin.h" | 120 | #include "gnunet_datastore_plugin.h" |
121 | #include "gnunet_util_lib.h" | 121 | #include "gnunet_util_lib.h" |
122 | #include <mysql/mysql.h> | 122 | #include "gnunet_mysql_lib.h" |
123 | 123 | ||
124 | #define DEBUG_MYSQL GNUNET_EXTRA_LOGGING | 124 | #define DEBUG_MYSQL GNUNET_EXTRA_LOGGING |
125 | 125 | ||
126 | #define MAX_DATUM_SIZE 65536 | 126 | #define MAX_DATUM_SIZE 65536 |
127 | 127 | ||
128 | /** | ||
129 | * Maximum number of supported parameters for a prepared | ||
130 | * statement. Increase if needed. | ||
131 | */ | ||
132 | #define MAX_PARAM 16 | ||
133 | |||
134 | /** | ||
135 | * Die with an error message that indicates | ||
136 | * a failure of the command 'cmd' with the message given | ||
137 | * by strerror(errno). | ||
138 | */ | ||
139 | #define DIE_MYSQL(cmd, dbh) do { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); GNUNET_abort(); } while(0); | ||
140 | |||
141 | /** | ||
142 | * Log an error message at log-level 'level' that indicates | ||
143 | * a failure of the command 'cmd' on file 'filename' | ||
144 | * with the message given by strerror(errno). | ||
145 | */ | ||
146 | #define LOG_MYSQL(level, cmd, dbh) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); } while(0); | ||
147 | |||
148 | |||
149 | struct GNUNET_MysqlStatementHandle | ||
150 | { | ||
151 | struct GNUNET_MysqlStatementHandle *next; | ||
152 | |||
153 | struct GNUNET_MysqlStatementHandle *prev; | ||
154 | |||
155 | char *query; | ||
156 | |||
157 | MYSQL_STMT *statement; | ||
158 | |||
159 | int valid; | ||
160 | |||
161 | }; | ||
162 | |||
163 | 128 | ||
164 | /** | 129 | /** |
165 | * Context for all functions in this plugin. | 130 | * Context for all functions in this plugin. |
@@ -174,64 +139,49 @@ struct Plugin | |||
174 | /** | 139 | /** |
175 | * Handle to talk to MySQL. | 140 | * Handle to talk to MySQL. |
176 | */ | 141 | */ |
177 | MYSQL *dbf; | 142 | struct GNUNET_MYSQL_Context *mc; |
178 | |||
179 | /** | ||
180 | * We keep all prepared statements in a DLL. This is the head. | ||
181 | */ | ||
182 | struct GNUNET_MysqlStatementHandle *shead; | ||
183 | |||
184 | /** | ||
185 | * We keep all prepared statements in a DLL. This is the tail. | ||
186 | */ | ||
187 | struct GNUNET_MysqlStatementHandle *stail; | ||
188 | |||
189 | /** | ||
190 | * Filename of "my.cnf" (msyql configuration). | ||
191 | */ | ||
192 | char *cnffile; | ||
193 | 143 | ||
194 | /** | 144 | /** |
195 | * Prepared statements. | 145 | * Prepared statements. |
196 | */ | 146 | */ |
197 | #define INSERT_ENTRY "INSERT INTO gn090 (repl,type,prio,anonLevel,expire,rvalue,hash,vhash,value) VALUES (?,?,?,?,?,?,?,?,?)" | 147 | #define INSERT_ENTRY "INSERT INTO gn090 (repl,type,prio,anonLevel,expire,rvalue,hash,vhash,value) VALUES (?,?,?,?,?,?,?,?,?)" |
198 | struct GNUNET_MysqlStatementHandle *insert_entry; | 148 | struct GNUNET_MYSQL_StatementHandle *insert_entry; |
199 | 149 | ||
200 | #define DELETE_ENTRY_BY_UID "DELETE FROM gn090 WHERE uid=?" | 150 | #define DELETE_ENTRY_BY_UID "DELETE FROM gn090 WHERE uid=?" |
201 | struct GNUNET_MysqlStatementHandle *delete_entry_by_uid; | 151 | struct GNUNET_MYSQL_StatementHandle *delete_entry_by_uid; |
202 | 152 | ||
203 | #define COUNT_ENTRY_BY_HASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash) WHERE hash=?" | 153 | #define COUNT_ENTRY_BY_HASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash) WHERE hash=?" |
204 | struct GNUNET_MysqlStatementHandle *count_entry_by_hash; | 154 | struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash; |
205 | 155 | ||
206 | #define SELECT_ENTRY_BY_HASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash) WHERE hash=? ORDER BY uid LIMIT 1 OFFSET ?" | 156 | #define SELECT_ENTRY_BY_HASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash) WHERE hash=? ORDER BY uid LIMIT 1 OFFSET ?" |
207 | struct GNUNET_MysqlStatementHandle *select_entry_by_hash; | 157 | struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash; |
208 | 158 | ||
209 | #define COUNT_ENTRY_BY_HASH_AND_VHASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=?" | 159 | #define COUNT_ENTRY_BY_HASH_AND_VHASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=?" |
210 | struct GNUNET_MysqlStatementHandle *count_entry_by_hash_and_vhash; | 160 | struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_and_vhash; |
211 | 161 | ||
212 | #define SELECT_ENTRY_BY_HASH_AND_VHASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? ORDER BY uid LIMIT 1 OFFSET ?" | 162 | #define SELECT_ENTRY_BY_HASH_AND_VHASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? ORDER BY uid LIMIT 1 OFFSET ?" |
213 | struct GNUNET_MysqlStatementHandle *select_entry_by_hash_and_vhash; | 163 | struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_vhash; |
214 | 164 | ||
215 | #define COUNT_ENTRY_BY_HASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=?" | 165 | #define COUNT_ENTRY_BY_HASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=?" |
216 | struct GNUNET_MysqlStatementHandle *count_entry_by_hash_and_type; | 166 | struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_and_type; |
217 | 167 | ||
218 | #define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=? ORDER BY uid LIMIT 1 OFFSET ?" | 168 | #define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=? ORDER BY uid LIMIT 1 OFFSET ?" |
219 | struct GNUNET_MysqlStatementHandle *select_entry_by_hash_and_type; | 169 | struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_type; |
220 | 170 | ||
221 | #define COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=?" | 171 | #define COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=?" |
222 | struct GNUNET_MysqlStatementHandle *count_entry_by_hash_vhash_and_type; | 172 | struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_vhash_and_type; |
223 | 173 | ||
224 | #define SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=? ORDER BY uid ASC LIMIT 1 OFFSET ?" | 174 | #define SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=? ORDER BY uid ASC LIMIT 1 OFFSET ?" |
225 | struct GNUNET_MysqlStatementHandle *select_entry_by_hash_vhash_and_type; | 175 | struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_vhash_and_type; |
226 | 176 | ||
227 | #define UPDATE_ENTRY "UPDATE gn090 SET prio=prio+?,expire=IF(expire>=?,expire,?) WHERE uid=?" | 177 | #define UPDATE_ENTRY "UPDATE gn090 SET prio=prio+?,expire=IF(expire>=?,expire,?) WHERE uid=?" |
228 | struct GNUNET_MysqlStatementHandle *update_entry; | 178 | struct GNUNET_MYSQL_StatementHandle *update_entry; |
229 | 179 | ||
230 | #define DEC_REPL "UPDATE gn090 SET repl=GREATEST (0, repl - 1) WHERE uid=?" | 180 | #define DEC_REPL "UPDATE gn090 SET repl=GREATEST (0, repl - 1) WHERE uid=?" |
231 | struct GNUNET_MysqlStatementHandle *dec_repl; | 181 | struct GNUNET_MYSQL_StatementHandle *dec_repl; |
232 | 182 | ||
233 | #define SELECT_SIZE "SELECT SUM(BIT_LENGTH(value) DIV 8) FROM gn090" | 183 | #define SELECT_SIZE "SELECT SUM(BIT_LENGTH(value) DIV 8) FROM gn090" |
234 | struct GNUNET_MysqlStatementHandle *get_size; | 184 | struct GNUNET_MYSQL_StatementHandle *get_size; |
235 | 185 | ||
236 | #define SELECT_IT_NON_ANONYMOUS "SELECT type,prio,anonLevel,expire,hash,value,uid "\ | 186 | #define SELECT_IT_NON_ANONYMOUS "SELECT type,prio,anonLevel,expire,hash,value,uid "\ |
237 | "FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) "\ | 187 | "FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) "\ |
@@ -239,13 +189,13 @@ struct Plugin | |||
239 | "(rvalue >= ? OR"\ | 189 | "(rvalue >= ? OR"\ |
240 | " NOT EXISTS (SELECT 1 FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) WHERE anonLevel=0 AND type=? AND rvalue>=?)) "\ | 190 | " NOT EXISTS (SELECT 1 FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) WHERE anonLevel=0 AND type=? AND rvalue>=?)) "\ |
241 | "ORDER BY rvalue ASC LIMIT 1" | 191 | "ORDER BY rvalue ASC LIMIT 1" |
242 | struct GNUNET_MysqlStatementHandle *zero_iter; | 192 | struct GNUNET_MYSQL_StatementHandle *zero_iter; |
243 | 193 | ||
244 | #define SELECT_IT_EXPIRATION "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_expire) WHERE expire < ? ORDER BY expire ASC LIMIT 1" | 194 | #define SELECT_IT_EXPIRATION "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_expire) WHERE expire < ? ORDER BY expire ASC LIMIT 1" |
245 | struct GNUNET_MysqlStatementHandle *select_expiration; | 195 | struct GNUNET_MYSQL_StatementHandle *select_expiration; |
246 | 196 | ||
247 | #define SELECT_IT_PRIORITY "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_prio) ORDER BY prio ASC LIMIT 1" | 197 | #define SELECT_IT_PRIORITY "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_prio) ORDER BY prio ASC LIMIT 1" |
248 | struct GNUNET_MysqlStatementHandle *select_priority; | 198 | struct GNUNET_MYSQL_StatementHandle *select_priority; |
249 | 199 | ||
250 | #define SELECT_IT_REPLICATION "SELECT type,prio,anonLevel,expire,hash,value,uid "\ | 200 | #define SELECT_IT_REPLICATION "SELECT type,prio,anonLevel,expire,hash,value,uid "\ |
251 | "FROM gn090 FORCE INDEX (idx_repl_rvalue) "\ | 201 | "FROM gn090 FORCE INDEX (idx_repl_rvalue) "\ |
@@ -254,510 +204,15 @@ struct Plugin | |||
254 | " NOT EXISTS (SELECT 1 FROM gn090 FORCE INDEX (idx_repl_rvalue) WHERE repl=? AND rvalue>=?)) "\ | 204 | " NOT EXISTS (SELECT 1 FROM gn090 FORCE INDEX (idx_repl_rvalue) WHERE repl=? AND rvalue>=?)) "\ |
255 | "ORDER BY rvalue ASC "\ | 205 | "ORDER BY rvalue ASC "\ |
256 | "LIMIT 1" | 206 | "LIMIT 1" |
257 | struct GNUNET_MysqlStatementHandle *select_replication; | 207 | struct GNUNET_MYSQL_StatementHandle *select_replication; |
258 | 208 | ||
259 | #define SELECT_MAX_REPL "SELECT MAX(repl) FROM gn090" | 209 | #define SELECT_MAX_REPL "SELECT MAX(repl) FROM gn090" |
260 | struct GNUNET_MysqlStatementHandle *max_repl; | 210 | struct GNUNET_MYSQL_StatementHandle *max_repl; |
261 | |||
262 | }; | ||
263 | |||
264 | |||
265 | /** | ||
266 | * Obtain the location of ".my.cnf". | ||
267 | * | ||
268 | * @param cfg our configuration | ||
269 | * @return NULL on error | ||
270 | */ | ||
271 | static char * | ||
272 | get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
273 | { | ||
274 | char *cnffile; | ||
275 | char *home_dir; | ||
276 | struct stat st; | ||
277 | |||
278 | #ifndef WINDOWS | ||
279 | struct passwd *pw; | ||
280 | #endif | ||
281 | int configured; | ||
282 | |||
283 | #ifndef WINDOWS | ||
284 | pw = getpwuid (getuid ()); | ||
285 | if (!pw) | ||
286 | { | ||
287 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "getpwuid"); | ||
288 | return NULL; | ||
289 | } | ||
290 | if (GNUNET_YES == | ||
291 | GNUNET_CONFIGURATION_have_value (cfg, "datastore-mysql", "CONFIG")) | ||
292 | { | ||
293 | GNUNET_assert (GNUNET_OK == | ||
294 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
295 | "datastore-mysql", | ||
296 | "CONFIG", | ||
297 | &cnffile)); | ||
298 | configured = GNUNET_YES; | ||
299 | } | ||
300 | else | ||
301 | { | ||
302 | home_dir = GNUNET_strdup (pw->pw_dir); | ||
303 | GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); | ||
304 | GNUNET_free (home_dir); | ||
305 | configured = GNUNET_NO; | ||
306 | } | ||
307 | #else | ||
308 | home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); | ||
309 | plibc_conv_to_win_path ("~/", home_dir); | ||
310 | GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); | ||
311 | GNUNET_free (home_dir); | ||
312 | configured = GNUNET_NO; | ||
313 | #endif | ||
314 | |||
315 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
316 | _("Trying to use file `%s' for MySQL configuration.\n"), cnffile); | ||
317 | if ((0 != STAT (cnffile, &st)) || (0 != ACCESS (cnffile, R_OK)) || | ||
318 | (!S_ISREG (st.st_mode))) | ||
319 | { | ||
320 | if (configured == GNUNET_YES) | ||
321 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
322 | _("Could not access file `%s': %s\n"), cnffile, | ||
323 | STRERROR (errno)); | ||
324 | GNUNET_free (cnffile); | ||
325 | return NULL; | ||
326 | } | ||
327 | return cnffile; | ||
328 | } | ||
329 | |||
330 | |||
331 | /** | ||
332 | * Close database connection and all prepared statements (we got a DB | ||
333 | * disconnect error). | ||
334 | * | ||
335 | * @param plugin plugin context | ||
336 | */ | ||
337 | static int | ||
338 | iclose (struct Plugin *plugin) | ||
339 | { | ||
340 | struct GNUNET_MysqlStatementHandle *s; | ||
341 | |||
342 | for (s = plugin->shead; s != NULL; s = s->next) | ||
343 | { | ||
344 | if (s->valid) | ||
345 | { | ||
346 | mysql_stmt_close (s->statement); | ||
347 | s->valid = GNUNET_NO; | ||
348 | } | ||
349 | } | ||
350 | if (plugin->dbf != NULL) | ||
351 | { | ||
352 | mysql_close (plugin->dbf); | ||
353 | plugin->dbf = NULL; | ||
354 | } | ||
355 | return GNUNET_OK; | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Open the connection with the database (and initialize | ||
361 | * our default options). | ||
362 | * | ||
363 | * @param plugin plugin context | ||
364 | * @return GNUNET_OK on success | ||
365 | */ | ||
366 | static int | ||
367 | iopen (struct Plugin *plugin) | ||
368 | { | ||
369 | char *mysql_dbname; | ||
370 | char *mysql_server; | ||
371 | char *mysql_user; | ||
372 | char *mysql_password; | ||
373 | unsigned long long mysql_port; | ||
374 | my_bool reconnect; | ||
375 | unsigned int timeout; | ||
376 | |||
377 | plugin->dbf = mysql_init (NULL); | ||
378 | if (plugin->dbf == NULL) | ||
379 | return GNUNET_SYSERR; | ||
380 | if (plugin->cnffile != NULL) | ||
381 | mysql_options (plugin->dbf, MYSQL_READ_DEFAULT_FILE, plugin->cnffile); | ||
382 | mysql_options (plugin->dbf, MYSQL_READ_DEFAULT_GROUP, "client"); | ||
383 | reconnect = 0; | ||
384 | mysql_options (plugin->dbf, MYSQL_OPT_RECONNECT, &reconnect); | ||
385 | timeout = 120; /* in seconds */ | ||
386 | mysql_options (plugin->dbf, MYSQL_OPT_CONNECT_TIMEOUT, | ||
387 | (const void *) &timeout); | ||
388 | mysql_options (plugin->dbf, MYSQL_SET_CHARSET_NAME, "UTF8"); | ||
389 | timeout = 60; /* in seconds */ | ||
390 | mysql_options (plugin->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout); | ||
391 | mysql_options (plugin->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout); | ||
392 | mysql_dbname = NULL; | ||
393 | if (GNUNET_YES == | ||
394 | GNUNET_CONFIGURATION_have_value (plugin->env->cfg, "datastore-mysql", | ||
395 | "DATABASE")) | ||
396 | GNUNET_assert (GNUNET_OK == | ||
397 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, | ||
398 | "datastore-mysql", | ||
399 | "DATABASE", | ||
400 | &mysql_dbname)); | ||
401 | else | ||
402 | mysql_dbname = GNUNET_strdup ("gnunet"); | ||
403 | mysql_user = NULL; | ||
404 | if (GNUNET_YES == | ||
405 | GNUNET_CONFIGURATION_have_value (plugin->env->cfg, "datastore-mysql", | ||
406 | "USER")) | ||
407 | { | ||
408 | GNUNET_assert (GNUNET_OK == | ||
409 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, | ||
410 | "datastore-mysql", | ||
411 | "USER", &mysql_user)); | ||
412 | } | ||
413 | mysql_password = NULL; | ||
414 | if (GNUNET_YES == | ||
415 | GNUNET_CONFIGURATION_have_value (plugin->env->cfg, "datastore-mysql", | ||
416 | "PASSWORD")) | ||
417 | { | ||
418 | GNUNET_assert (GNUNET_OK == | ||
419 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, | ||
420 | "datastore-mysql", | ||
421 | "PASSWORD", | ||
422 | &mysql_password)); | ||
423 | } | ||
424 | mysql_server = NULL; | ||
425 | if (GNUNET_YES == | ||
426 | GNUNET_CONFIGURATION_have_value (plugin->env->cfg, "datastore-mysql", | ||
427 | "HOST")) | ||
428 | { | ||
429 | GNUNET_assert (GNUNET_OK == | ||
430 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, | ||
431 | "datastore-mysql", | ||
432 | "HOST", | ||
433 | &mysql_server)); | ||
434 | } | ||
435 | mysql_port = 0; | ||
436 | if (GNUNET_YES == | ||
437 | GNUNET_CONFIGURATION_have_value (plugin->env->cfg, "datastore-mysql", | ||
438 | "PORT")) | ||
439 | { | ||
440 | GNUNET_assert (GNUNET_OK == | ||
441 | GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, | ||
442 | "datastore-mysql", | ||
443 | "PORT", &mysql_port)); | ||
444 | } | ||
445 | |||
446 | GNUNET_assert (mysql_dbname != NULL); | ||
447 | mysql_real_connect (plugin->dbf, mysql_server, mysql_user, mysql_password, | ||
448 | mysql_dbname, (unsigned int) mysql_port, NULL, | ||
449 | CLIENT_IGNORE_SIGPIPE); | ||
450 | GNUNET_free_non_null (mysql_server); | ||
451 | GNUNET_free_non_null (mysql_user); | ||
452 | GNUNET_free_non_null (mysql_password); | ||
453 | GNUNET_free (mysql_dbname); | ||
454 | if (mysql_error (plugin->dbf)[0]) | ||
455 | { | ||
456 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_real_connect", plugin); | ||
457 | return GNUNET_SYSERR; | ||
458 | } | ||
459 | return GNUNET_OK; | ||
460 | } | ||
461 | |||
462 | |||
463 | /** | ||
464 | * Run the given MySQL statement. | ||
465 | * | ||
466 | * @param plugin plugin context | ||
467 | * @param statement SQL statement to run | ||
468 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
469 | */ | ||
470 | static int | ||
471 | run_statement (struct Plugin *plugin, const char *statement) | ||
472 | { | ||
473 | if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) | ||
474 | return GNUNET_SYSERR; | ||
475 | mysql_query (plugin->dbf, statement); | ||
476 | if (mysql_error (plugin->dbf)[0]) | ||
477 | { | ||
478 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", plugin); | ||
479 | iclose (plugin); | ||
480 | return GNUNET_SYSERR; | ||
481 | } | ||
482 | return GNUNET_OK; | ||
483 | } | ||
484 | 211 | ||
212 | #define GET_ALL_KEYS "SELECT hash from gn090" | ||
213 | struct GNUNET_MYSQL_StatementHandle *get_all_keys; | ||
485 | 214 | ||
486 | /** | 215 | }; |
487 | * Create a prepared statement. | ||
488 | * | ||
489 | * @param plugin plugin context | ||
490 | * @param statement SQL statement text to prepare | ||
491 | * @return NULL on error | ||
492 | */ | ||
493 | static struct GNUNET_MysqlStatementHandle * | ||
494 | prepared_statement_create (struct Plugin *plugin, const char *statement) | ||
495 | { | ||
496 | struct GNUNET_MysqlStatementHandle *ret; | ||
497 | |||
498 | ret = GNUNET_malloc (sizeof (struct GNUNET_MysqlStatementHandle)); | ||
499 | ret->query = GNUNET_strdup (statement); | ||
500 | GNUNET_CONTAINER_DLL_insert (plugin->shead, plugin->stail, ret); | ||
501 | return ret; | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
506 | * Prepare a statement for running. | ||
507 | * | ||
508 | * @param plugin plugin context | ||
509 | * @param ret handle to prepared statement | ||
510 | * @return GNUNET_OK on success | ||
511 | */ | ||
512 | static int | ||
513 | prepare_statement (struct Plugin *plugin, | ||
514 | struct GNUNET_MysqlStatementHandle *ret) | ||
515 | { | ||
516 | if (GNUNET_YES == ret->valid) | ||
517 | return GNUNET_OK; | ||
518 | if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) | ||
519 | return GNUNET_SYSERR; | ||
520 | ret->statement = mysql_stmt_init (plugin->dbf); | ||
521 | if (ret->statement == NULL) | ||
522 | { | ||
523 | iclose (plugin); | ||
524 | return GNUNET_SYSERR; | ||
525 | } | ||
526 | if (mysql_stmt_prepare (ret->statement, ret->query, strlen (ret->query))) | ||
527 | { | ||
528 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", | ||
529 | _("Failed to prepare statement `%s'\n"), ret->query); | ||
530 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", plugin); | ||
531 | mysql_stmt_close (ret->statement); | ||
532 | ret->statement = NULL; | ||
533 | iclose (plugin); | ||
534 | return GNUNET_SYSERR; | ||
535 | } | ||
536 | ret->valid = GNUNET_YES; | ||
537 | return GNUNET_OK; | ||
538 | |||
539 | } | ||
540 | |||
541 | |||
542 | /** | ||
543 | * Bind the parameters for the given MySQL statement | ||
544 | * and run it. | ||
545 | * | ||
546 | * @param plugin plugin context | ||
547 | * @param s statement to bind and run | ||
548 | * @param ap arguments for the binding | ||
549 | * @return GNUNET_SYSERR on error, GNUNET_OK on success | ||
550 | */ | ||
551 | static int | ||
552 | init_params (struct Plugin *plugin, struct GNUNET_MysqlStatementHandle *s, | ||
553 | va_list ap) | ||
554 | { | ||
555 | MYSQL_BIND qbind[MAX_PARAM]; | ||
556 | unsigned int pc; | ||
557 | unsigned int off; | ||
558 | enum enum_field_types ft; | ||
559 | |||
560 | pc = mysql_stmt_param_count (s->statement); | ||
561 | if (pc > MAX_PARAM) | ||
562 | { | ||
563 | /* increase internal constant! */ | ||
564 | GNUNET_break (0); | ||
565 | return GNUNET_SYSERR; | ||
566 | } | ||
567 | memset (qbind, 0, sizeof (qbind)); | ||
568 | off = 0; | ||
569 | ft = 0; | ||
570 | while ((pc > 0) && (-1 != (int) (ft = va_arg (ap, enum enum_field_types)))) | ||
571 | { | ||
572 | qbind[off].buffer_type = ft; | ||
573 | switch (ft) | ||
574 | { | ||
575 | case MYSQL_TYPE_FLOAT: | ||
576 | qbind[off].buffer = va_arg (ap, float *); | ||
577 | |||
578 | break; | ||
579 | case MYSQL_TYPE_LONGLONG: | ||
580 | qbind[off].buffer = va_arg (ap, unsigned long long *); | ||
581 | qbind[off].is_unsigned = va_arg (ap, int); | ||
582 | |||
583 | break; | ||
584 | case MYSQL_TYPE_LONG: | ||
585 | qbind[off].buffer = va_arg (ap, unsigned int *); | ||
586 | qbind[off].is_unsigned = va_arg (ap, int); | ||
587 | |||
588 | break; | ||
589 | case MYSQL_TYPE_VAR_STRING: | ||
590 | case MYSQL_TYPE_STRING: | ||
591 | case MYSQL_TYPE_BLOB: | ||
592 | qbind[off].buffer = va_arg (ap, void *); | ||
593 | qbind[off].buffer_length = va_arg (ap, unsigned long); | ||
594 | qbind[off].length = va_arg (ap, unsigned long *); | ||
595 | |||
596 | break; | ||
597 | default: | ||
598 | /* unsupported type */ | ||
599 | GNUNET_break (0); | ||
600 | return GNUNET_SYSERR; | ||
601 | } | ||
602 | pc--; | ||
603 | off++; | ||
604 | } | ||
605 | if (!((pc == 0) && (-1 != (int) ft) && (va_arg (ap, int) == -1))) | ||
606 | { | ||
607 | GNUNET_assert (0); | ||
608 | return GNUNET_SYSERR; | ||
609 | } | ||
610 | if (mysql_stmt_bind_param (s->statement, qbind)) | ||
611 | { | ||
612 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
613 | _("`%s' failed at %s:%d with error: %s\n"), | ||
614 | "mysql_stmt_bind_param", __FILE__, __LINE__, | ||
615 | mysql_stmt_error (s->statement)); | ||
616 | iclose (plugin); | ||
617 | return GNUNET_SYSERR; | ||
618 | } | ||
619 | if (mysql_stmt_execute (s->statement)) | ||
620 | { | ||
621 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
622 | _("`%s' for `%s' failed at %s:%d with error: %s\n"), | ||
623 | "mysql_stmt_execute", s->query, __FILE__, __LINE__, | ||
624 | mysql_stmt_error (s->statement)); | ||
625 | iclose (plugin); | ||
626 | return GNUNET_SYSERR; | ||
627 | } | ||
628 | return GNUNET_OK; | ||
629 | } | ||
630 | |||
631 | |||
632 | /** | ||
633 | * Run a prepared SELECT statement. | ||
634 | * | ||
635 | * @param plugin plugin context | ||
636 | * @param s statement to run | ||
637 | * @param result_size number of elements in results array | ||
638 | * @param results pointer to already initialized MYSQL_BIND | ||
639 | * array (of sufficient size) for passing results | ||
640 | * @param ap pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective | ||
641 | * values (size + buffer-reference for pointers); terminated | ||
642 | * with "-1" | ||
643 | * @return GNUNET_SYSERR on error, otherwise GNUNET_OK or GNUNET_NO (no result) | ||
644 | */ | ||
645 | static int | ||
646 | prepared_statement_run_select_va (struct Plugin *plugin, | ||
647 | struct GNUNET_MysqlStatementHandle *s, | ||
648 | unsigned int result_size, | ||
649 | MYSQL_BIND * results, va_list ap) | ||
650 | { | ||
651 | int ret; | ||
652 | unsigned int rsize; | ||
653 | |||
654 | if (GNUNET_OK != prepare_statement (plugin, s)) | ||
655 | { | ||
656 | GNUNET_break (0); | ||
657 | return GNUNET_SYSERR; | ||
658 | } | ||
659 | if (GNUNET_OK != init_params (plugin, s, ap)) | ||
660 | { | ||
661 | GNUNET_break (0); | ||
662 | return GNUNET_SYSERR; | ||
663 | } | ||
664 | rsize = mysql_stmt_field_count (s->statement); | ||
665 | if (rsize > result_size) | ||
666 | { | ||
667 | GNUNET_break (0); | ||
668 | return GNUNET_SYSERR; | ||
669 | } | ||
670 | if (mysql_stmt_bind_result (s->statement, results)) | ||
671 | { | ||
672 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
673 | _("`%s' failed at %s:%d with error: %s\n"), | ||
674 | "mysql_stmt_bind_result", __FILE__, __LINE__, | ||
675 | mysql_stmt_error (s->statement)); | ||
676 | iclose (plugin); | ||
677 | return GNUNET_SYSERR; | ||
678 | } | ||
679 | ret = mysql_stmt_fetch (s->statement); | ||
680 | if (ret == MYSQL_NO_DATA) | ||
681 | return GNUNET_NO; | ||
682 | if (ret != 0) | ||
683 | { | ||
684 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
685 | _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_fetch", | ||
686 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); | ||
687 | iclose (plugin); | ||
688 | return GNUNET_SYSERR; | ||
689 | } | ||
690 | mysql_stmt_reset (s->statement); | ||
691 | return GNUNET_OK; | ||
692 | } | ||
693 | |||
694 | |||
695 | /** | ||
696 | * Run a prepared SELECT statement. | ||
697 | * | ||
698 | * @param plugin plugin context | ||
699 | * @param s statement to run | ||
700 | * @param result_size number of elements in results array | ||
701 | * @param results pointer to already initialized MYSQL_BIND | ||
702 | * array (of sufficient size) for passing results | ||
703 | * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective | ||
704 | * values (size + buffer-reference for pointers); terminated | ||
705 | * with "-1" | ||
706 | * @return GNUNET_SYSERR on error, otherwise | ||
707 | * the number of successfully affected (or queried) rows | ||
708 | */ | ||
709 | static int | ||
710 | prepared_statement_run_select (struct Plugin *plugin, | ||
711 | struct GNUNET_MysqlStatementHandle *s, | ||
712 | unsigned int result_size, MYSQL_BIND * results, | ||
713 | ...) | ||
714 | { | ||
715 | va_list ap; | ||
716 | int ret; | ||
717 | |||
718 | va_start (ap, results); | ||
719 | ret = prepared_statement_run_select_va (plugin, s, result_size, results, ap); | ||
720 | va_end (ap); | ||
721 | return ret; | ||
722 | } | ||
723 | |||
724 | |||
725 | /** | ||
726 | * Run a prepared statement that does NOT produce results. | ||
727 | * | ||
728 | * @param plugin plugin context | ||
729 | * @param s statement to run | ||
730 | * @param insert_id NULL or address where to store the row ID of whatever | ||
731 | * was inserted (only for INSERT statements!) | ||
732 | * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective | ||
733 | * values (size + buffer-reference for pointers); terminated | ||
734 | * with "-1" | ||
735 | * @return GNUNET_SYSERR on error, otherwise | ||
736 | * the number of successfully affected rows | ||
737 | */ | ||
738 | static int | ||
739 | prepared_statement_run (struct Plugin *plugin, | ||
740 | struct GNUNET_MysqlStatementHandle *s, | ||
741 | unsigned long long *insert_id, ...) | ||
742 | { | ||
743 | va_list ap; | ||
744 | int affected; | ||
745 | |||
746 | if (GNUNET_OK != prepare_statement (plugin, s)) | ||
747 | return GNUNET_SYSERR; | ||
748 | va_start (ap, insert_id); | ||
749 | if (GNUNET_OK != init_params (plugin, s, ap)) | ||
750 | { | ||
751 | va_end (ap); | ||
752 | return GNUNET_SYSERR; | ||
753 | } | ||
754 | va_end (ap); | ||
755 | affected = mysql_stmt_affected_rows (s->statement); | ||
756 | if (NULL != insert_id) | ||
757 | *insert_id = (unsigned long long) mysql_stmt_insert_id (s->statement); | ||
758 | mysql_stmt_reset (s->statement); | ||
759 | return affected; | ||
760 | } | ||
761 | 216 | ||
762 | 217 | ||
763 | /** | 218 | /** |
@@ -776,9 +231,9 @@ do_delete_entry (struct Plugin *plugin, unsigned long long uid) | |||
776 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting value %llu from gn090 table\n", | 231 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting value %llu from gn090 table\n", |
777 | uid); | 232 | uid); |
778 | #endif | 233 | #endif |
779 | ret = | 234 | ret = GNUNET_MYSQL_statement_run_prepared (plugin->mc, |
780 | prepared_statement_run (plugin, plugin->delete_entry_by_uid, NULL, | 235 | plugin->delete_entry_by_uid, NULL, |
781 | MYSQL_TYPE_LONGLONG, &uid, GNUNET_YES, -1); | 236 | MYSQL_TYPE_LONGLONG, &uid, GNUNET_YES, -1); |
782 | if (ret >= 0) | 237 | if (ret >= 0) |
783 | return GNUNET_OK; | 238 | return GNUNET_OK; |
784 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 239 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
@@ -807,7 +262,7 @@ mysql_plugin_estimate_size (void *cls) | |||
807 | cbind[0].buffer = &total; | 262 | cbind[0].buffer = &total; |
808 | cbind[0].is_unsigned = GNUNET_NO; | 263 | cbind[0].is_unsigned = GNUNET_NO; |
809 | if (GNUNET_OK != | 264 | if (GNUNET_OK != |
810 | prepared_statement_run_select (plugin, plugin->get_size, 1, cbind, -1)) | 265 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->get_size, 1, cbind, NULL, NULL, -1)) |
811 | return 0; | 266 | return 0; |
812 | return total; | 267 | return total; |
813 | } | 268 | } |
@@ -857,7 +312,7 @@ mysql_plugin_put (void *cls, const GNUNET_HashCode * key, uint32_t size, | |||
857 | lsize = size; | 312 | lsize = size; |
858 | GNUNET_CRYPTO_hash (data, size, &vhash); | 313 | GNUNET_CRYPTO_hash (data, size, &vhash); |
859 | if (GNUNET_OK != | 314 | if (GNUNET_OK != |
860 | prepared_statement_run (plugin, plugin->insert_entry, NULL, | 315 | GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->insert_entry, NULL, |
861 | MYSQL_TYPE_LONG, &irepl, GNUNET_YES, | 316 | MYSQL_TYPE_LONG, &irepl, GNUNET_YES, |
862 | MYSQL_TYPE_LONG, &type, GNUNET_YES, | 317 | MYSQL_TYPE_LONG, &type, GNUNET_YES, |
863 | MYSQL_TYPE_LONG, &ipriority, GNUNET_YES, | 318 | MYSQL_TYPE_LONG, &ipriority, GNUNET_YES, |
@@ -917,8 +372,8 @@ mysql_plugin_update (void *cls, uint64_t uid, int delta, | |||
917 | vkey, delta, lexpire); | 372 | vkey, delta, lexpire); |
918 | #endif | 373 | #endif |
919 | ret = | 374 | ret = |
920 | prepared_statement_run (plugin, plugin->update_entry, NULL, | 375 | GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->update_entry, NULL, |
921 | MYSQL_TYPE_LONG, &delta, GNUNET_NO, | 376 | MYSQL_TYPE_LONG, &delta, GNUNET_NO, |
922 | MYSQL_TYPE_LONGLONG, &lexpire, GNUNET_YES, | 377 | MYSQL_TYPE_LONGLONG, &lexpire, GNUNET_YES, |
923 | MYSQL_TYPE_LONGLONG, &lexpire, GNUNET_YES, | 378 | MYSQL_TYPE_LONGLONG, &lexpire, GNUNET_YES, |
924 | MYSQL_TYPE_LONGLONG, &vkey, GNUNET_YES, -1); | 379 | MYSQL_TYPE_LONGLONG, &vkey, GNUNET_YES, -1); |
@@ -942,7 +397,7 @@ mysql_plugin_update (void *cls, uint64_t uid, int delta, | |||
942 | * @param ... arguments to initialize stmt | 397 | * @param ... arguments to initialize stmt |
943 | */ | 398 | */ |
944 | static void | 399 | static void |
945 | execute_select (struct Plugin *plugin, struct GNUNET_MysqlStatementHandle *stmt, | 400 | execute_select (struct Plugin *plugin, struct GNUNET_MYSQL_StatementHandle *stmt, |
946 | PluginDatumProcessor proc, void *proc_cls, ...) | 401 | PluginDatumProcessor proc, void *proc_cls, ...) |
947 | { | 402 | { |
948 | va_list ap; | 403 | va_list ap; |
@@ -986,7 +441,7 @@ execute_select (struct Plugin *plugin, struct GNUNET_MysqlStatementHandle *stmt, | |||
986 | rbind[6].is_unsigned = 1; | 441 | rbind[6].is_unsigned = 1; |
987 | 442 | ||
988 | va_start (ap, proc_cls); | 443 | va_start (ap, proc_cls); |
989 | ret = prepared_statement_run_select_va (plugin, stmt, 7, rbind, ap); | 444 | ret = GNUNET_MYSQL_statement_run_prepared_select_va (plugin->mc, stmt, 7, rbind, NULL, NULL, ap); |
990 | va_end (ap); | 445 | va_end (ap); |
991 | if (ret <= 0) | 446 | if (ret <= 0) |
992 | { | 447 | { |
@@ -1067,10 +522,10 @@ mysql_plugin_get_key (void *cls, uint64_t offset, const GNUNET_HashCode * key, | |||
1067 | if (vhash != NULL) | 522 | if (vhash != NULL) |
1068 | { | 523 | { |
1069 | ret = | 524 | ret = |
1070 | prepared_statement_run_select (plugin, | 525 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, |
1071 | plugin-> | 526 | plugin-> |
1072 | count_entry_by_hash_vhash_and_type, 1, | 527 | count_entry_by_hash_vhash_and_type, 1, |
1073 | cbind, MYSQL_TYPE_BLOB, key, hashSize, | 528 | cbind, NULL, NULL, MYSQL_TYPE_BLOB, key, hashSize, |
1074 | &hashSize, MYSQL_TYPE_BLOB, vhash, | 529 | &hashSize, MYSQL_TYPE_BLOB, vhash, |
1075 | hashSize2, &hashSize2, MYSQL_TYPE_LONG, | 530 | hashSize2, &hashSize2, MYSQL_TYPE_LONG, |
1076 | &type, GNUNET_YES, -1); | 531 | &type, GNUNET_YES, -1); |
@@ -1078,9 +533,9 @@ mysql_plugin_get_key (void *cls, uint64_t offset, const GNUNET_HashCode * key, | |||
1078 | else | 533 | else |
1079 | { | 534 | { |
1080 | ret = | 535 | ret = |
1081 | prepared_statement_run_select (plugin, | 536 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, |
1082 | plugin->count_entry_by_hash_and_type, | 537 | plugin->count_entry_by_hash_and_type, |
1083 | 1, cbind, MYSQL_TYPE_BLOB, key, | 538 | 1, cbind, NULL, NULL, MYSQL_TYPE_BLOB, key, |
1084 | hashSize, &hashSize, MYSQL_TYPE_LONG, | 539 | hashSize, &hashSize, MYSQL_TYPE_LONG, |
1085 | &type, GNUNET_YES, -1); | 540 | &type, GNUNET_YES, -1); |
1086 | } | 541 | } |
@@ -1090,9 +545,9 @@ mysql_plugin_get_key (void *cls, uint64_t offset, const GNUNET_HashCode * key, | |||
1090 | if (vhash != NULL) | 545 | if (vhash != NULL) |
1091 | { | 546 | { |
1092 | ret = | 547 | ret = |
1093 | prepared_statement_run_select (plugin, | 548 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, |
1094 | plugin->count_entry_by_hash_and_vhash, | 549 | plugin->count_entry_by_hash_and_vhash, |
1095 | 1, cbind, MYSQL_TYPE_BLOB, key, | 550 | 1, cbind, NULL, NULL, MYSQL_TYPE_BLOB, key, |
1096 | hashSize, &hashSize, MYSQL_TYPE_BLOB, | 551 | hashSize, &hashSize, MYSQL_TYPE_BLOB, |
1097 | vhash, hashSize2, &hashSize2, -1); | 552 | vhash, hashSize2, &hashSize2, -1); |
1098 | 553 | ||
@@ -1100,8 +555,8 @@ mysql_plugin_get_key (void *cls, uint64_t offset, const GNUNET_HashCode * key, | |||
1100 | else | 555 | else |
1101 | { | 556 | { |
1102 | ret = | 557 | ret = |
1103 | prepared_statement_run_select (plugin, plugin->count_entry_by_hash, 1, | 558 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->count_entry_by_hash, 1, |
1104 | cbind, MYSQL_TYPE_BLOB, key, hashSize, | 559 | cbind, NULL, NULL, MYSQL_TYPE_BLOB, key, hashSize, |
1105 | &hashSize, -1); | 560 | &hashSize, -1); |
1106 | } | 561 | } |
1107 | } | 562 | } |
@@ -1244,8 +699,8 @@ repl_proc (void *cls, const GNUNET_HashCode * key, uint32_t size, | |||
1244 | { | 699 | { |
1245 | oid = (unsigned long long) uid; | 700 | oid = (unsigned long long) uid; |
1246 | iret = | 701 | iret = |
1247 | prepared_statement_run (plugin, plugin->dec_repl, NULL, | 702 | GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->dec_repl, NULL, |
1248 | MYSQL_TYPE_LONGLONG, &oid, GNUNET_YES, -1); | 703 | MYSQL_TYPE_LONGLONG, &oid, GNUNET_YES, -1); |
1249 | if (iret == GNUNET_SYSERR) | 704 | if (iret == GNUNET_SYSERR) |
1250 | { | 705 | { |
1251 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 706 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
@@ -1287,7 +742,7 @@ mysql_plugin_get_replication (void *cls, PluginDatumProcessor proc, | |||
1287 | results.is_unsigned = GNUNET_YES; | 742 | results.is_unsigned = GNUNET_YES; |
1288 | 743 | ||
1289 | if (1 != | 744 | if (1 != |
1290 | prepared_statement_run_select (plugin, plugin->max_repl, 1, &results, -1)) | 745 | GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->max_repl, 1, &results, NULL, NULL, -1)) |
1291 | { | 746 | { |
1292 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 747 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
1293 | return; | 748 | return; |
@@ -1324,19 +779,18 @@ mysql_plugin_get_keys (void *cls, | |||
1324 | MYSQL_BIND cbind[1]; | 779 | MYSQL_BIND cbind[1]; |
1325 | unsigned long length; | 780 | unsigned long length; |
1326 | 781 | ||
1327 | statement = mysql_stmt_init (plugin->dbf); | 782 | statement = GNUNET_MYSQL_statement_get_stmt (plugin->mc, |
783 | plugin->get_all_keys); | ||
1328 | if (statement == NULL) | 784 | if (statement == NULL) |
1329 | { | 785 | { |
1330 | iclose (plugin); | 786 | GNUNET_MYSQL_statements_invalidate (plugin->mc); |
1331 | return; | 787 | return; |
1332 | } | 788 | } |
1333 | if (mysql_stmt_prepare (statement, query, strlen (query))) | 789 | if (mysql_stmt_prepare (statement, query, strlen (query))) |
1334 | { | 790 | { |
1335 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", | 791 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", |
1336 | _("Failed to prepare statement `%s'\n"), query); | 792 | _("Failed to prepare statement `%s'\n"), query); |
1337 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", plugin); | 793 | GNUNET_MYSQL_statements_invalidate (plugin->mc); |
1338 | mysql_stmt_close (statement); | ||
1339 | iclose (plugin); | ||
1340 | return; | 794 | return; |
1341 | } | 795 | } |
1342 | GNUNET_assert (proc != NULL); | 796 | GNUNET_assert (proc != NULL); |
@@ -1346,8 +800,7 @@ mysql_plugin_get_keys (void *cls, | |||
1346 | _("`%s' for `%s' failed at %s:%d with error: %s\n"), | 800 | _("`%s' for `%s' failed at %s:%d with error: %s\n"), |
1347 | "mysql_stmt_execute", query, __FILE__, __LINE__, | 801 | "mysql_stmt_execute", query, __FILE__, __LINE__, |
1348 | mysql_stmt_error (statement)); | 802 | mysql_stmt_error (statement)); |
1349 | mysql_stmt_close (statement); | 803 | GNUNET_MYSQL_statements_invalidate (plugin->mc); |
1350 | iclose (plugin); | ||
1351 | return; | 804 | return; |
1352 | } | 805 | } |
1353 | memset (cbind, 0, sizeof (cbind)); | 806 | memset (cbind, 0, sizeof (cbind)); |
@@ -1362,7 +815,7 @@ mysql_plugin_get_keys (void *cls, | |||
1362 | _("`%s' failed at %s:%d with error: %s\n"), | 815 | _("`%s' failed at %s:%d with error: %s\n"), |
1363 | "mysql_stmt_bind_result", __FILE__, __LINE__, | 816 | "mysql_stmt_bind_result", __FILE__, __LINE__, |
1364 | mysql_stmt_error (statement)); | 817 | mysql_stmt_error (statement)); |
1365 | iclose (plugin); | 818 | GNUNET_MYSQL_statements_invalidate (plugin->mc); |
1366 | return; | 819 | return; |
1367 | } | 820 | } |
1368 | while (0 == (ret = mysql_stmt_fetch (statement))) | 821 | while (0 == (ret = mysql_stmt_fetch (statement))) |
@@ -1376,11 +829,10 @@ mysql_plugin_get_keys (void *cls, | |||
1376 | _("`%s' failed at %s:%d with error: %s\n"), | 829 | _("`%s' failed at %s:%d with error: %s\n"), |
1377 | "mysql_stmt_fetch", __FILE__, __LINE__, | 830 | "mysql_stmt_fetch", __FILE__, __LINE__, |
1378 | mysql_stmt_error (statement)); | 831 | mysql_stmt_error (statement)); |
1379 | mysql_stmt_close (statement); | 832 | GNUNET_MYSQL_statements_invalidate (plugin->mc); |
1380 | iclose (plugin); | ||
1381 | return; | 833 | return; |
1382 | } | 834 | } |
1383 | mysql_stmt_close (statement); | 835 | mysql_stmt_reset (statement); |
1384 | } | 836 | } |
1385 | 837 | ||
1386 | 838 | ||
@@ -1484,7 +936,7 @@ mysql_plugin_drop (void *cls) | |||
1484 | { | 936 | { |
1485 | struct Plugin *plugin = cls; | 937 | struct Plugin *plugin = cls; |
1486 | 938 | ||
1487 | if (GNUNET_OK != run_statement (plugin, "DROP TABLE gn090")) | 939 | if (GNUNET_OK != GNUNET_MYSQL_statement_run (plugin->mc, "DROP TABLE gn090")) |
1488 | return; /* error */ | 940 | return; /* error */ |
1489 | plugin->env->duc (plugin->env->cls, 0); | 941 | plugin->env->duc (plugin->env->cls, 0); |
1490 | } | 942 | } |
@@ -1505,16 +957,14 @@ libgnunet_plugin_datastore_mysql_init (void *cls) | |||
1505 | 957 | ||
1506 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | 958 | plugin = GNUNET_malloc (sizeof (struct Plugin)); |
1507 | plugin->env = env; | 959 | plugin->env = env; |
1508 | plugin->cnffile = get_my_cnf_path (env->cfg); | 960 | plugin->mc = GNUNET_MYSQL_context_create (env->cfg, "datastore-mysql"); |
1509 | if (GNUNET_OK != iopen (plugin)) | 961 | if (NULL == plugin->mc) |
1510 | { | 962 | { |
1511 | iclose (plugin); | ||
1512 | GNUNET_free_non_null (plugin->cnffile); | ||
1513 | GNUNET_free (plugin); | 963 | GNUNET_free (plugin); |
1514 | return NULL; | 964 | return NULL; |
1515 | } | 965 | } |
1516 | #define MRUNS(a) (GNUNET_OK != run_statement (plugin, a) ) | 966 | #define MRUNS(a) (GNUNET_OK != GNUNET_MYSQL_statement_run (plugin->mc, a) ) |
1517 | #define PINIT(a,b) (NULL == (a = prepared_statement_create(plugin, b))) | 967 | #define PINIT(a,b) (NULL == (a = GNUNET_MYSQL_statement_prepare (plugin->mc, b))) |
1518 | if (MRUNS | 968 | if (MRUNS |
1519 | ("CREATE TABLE IF NOT EXISTS gn090 (" | 969 | ("CREATE TABLE IF NOT EXISTS gn090 (" |
1520 | " repl INT(11) UNSIGNED NOT NULL DEFAULT 0," | 970 | " repl INT(11) UNSIGNED NOT NULL DEFAULT 0," |
@@ -1556,10 +1006,10 @@ libgnunet_plugin_datastore_mysql_init (void *cls) | |||
1556 | PINIT (plugin->select_expiration, SELECT_IT_EXPIRATION) || | 1006 | PINIT (plugin->select_expiration, SELECT_IT_EXPIRATION) || |
1557 | PINIT (plugin->select_priority, SELECT_IT_PRIORITY) || | 1007 | PINIT (plugin->select_priority, SELECT_IT_PRIORITY) || |
1558 | PINIT (plugin->max_repl, SELECT_MAX_REPL) || | 1008 | PINIT (plugin->max_repl, SELECT_MAX_REPL) || |
1009 | PINIT (plugin->get_all_keys, GET_ALL_KEYS) || | ||
1559 | PINIT (plugin->select_replication, SELECT_IT_REPLICATION)) | 1010 | PINIT (plugin->select_replication, SELECT_IT_REPLICATION)) |
1560 | { | 1011 | { |
1561 | iclose (plugin); | 1012 | GNUNET_MYSQL_context_destroy (plugin->mc); |
1562 | GNUNET_free_non_null (plugin->cnffile); | ||
1563 | GNUNET_free (plugin); | 1013 | GNUNET_free (plugin); |
1564 | return NULL; | 1014 | return NULL; |
1565 | } | 1015 | } |
@@ -1593,19 +1043,10 @@ libgnunet_plugin_datastore_mysql_done (void *cls) | |||
1593 | { | 1043 | { |
1594 | struct GNUNET_DATASTORE_PluginFunctions *api = cls; | 1044 | struct GNUNET_DATASTORE_PluginFunctions *api = cls; |
1595 | struct Plugin *plugin = api->cls; | 1045 | struct Plugin *plugin = api->cls; |
1596 | struct GNUNET_MysqlStatementHandle *s; | ||
1597 | 1046 | ||
1598 | iclose (plugin); | 1047 | GNUNET_MYSQL_context_destroy (plugin->mc); |
1599 | while (NULL != (s = plugin->shead)) | ||
1600 | { | ||
1601 | GNUNET_CONTAINER_DLL_remove (plugin->shead, plugin->stail, s); | ||
1602 | GNUNET_free (s->query); | ||
1603 | GNUNET_free (s); | ||
1604 | } | ||
1605 | GNUNET_free_non_null (plugin->cnffile); | ||
1606 | GNUNET_free (plugin); | 1048 | GNUNET_free (plugin); |
1607 | GNUNET_free (api); | 1049 | GNUNET_free (api); |
1608 | mysql_library_end (); | ||
1609 | return NULL; | 1050 | return NULL; |
1610 | } | 1051 | } |
1611 | 1052 | ||
diff --git a/src/include/gnunet_mysql_lib.h b/src/include/gnunet_mysql_lib.h index 678b7669d..c232a0065 100644 --- a/src/include/gnunet_mysql_lib.h +++ b/src/include/gnunet_mysql_lib.h | |||
@@ -86,6 +86,31 @@ GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc); | |||
86 | 86 | ||
87 | 87 | ||
88 | /** | 88 | /** |
89 | * Close database connection and all prepared statements (we got a DB | ||
90 | * error). The connection will automatically be re-opened and | ||
91 | * statements will be re-prepared if they are needed again later. | ||
92 | * | ||
93 | * @param mc mysql context | ||
94 | */ | ||
95 | void | ||
96 | GNUNET_MYSQL_statements_invalidate (struct GNUNET_MYSQL_Context *mc); | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Get internal handle for a prepared statement. This function should rarely | ||
101 | * be used, and if, with caution! On failures during the interaction with | ||
102 | * the handle, you must call 'GNUNET_MYSQL_statements_invalidate'! | ||
103 | * | ||
104 | * @param mc mysql context | ||
105 | * @param sh prepared statement to introspect | ||
106 | * @return MySQL statement handle, NULL on error | ||
107 | */ | ||
108 | MYSQL_STMT * | ||
109 | GNUNET_MYSQL_statement_get_stmt (struct GNUNET_MYSQL_Context *mc, | ||
110 | struct GNUNET_MYSQL_StatementHandle *sh); | ||
111 | |||
112 | |||
113 | /** | ||
89 | * Prepare a statement. Prepared statements are automatically discarded | 114 | * Prepare a statement. Prepared statements are automatically discarded |
90 | * when the MySQL context is destroyed. | 115 | * when the MySQL context is destroyed. |
91 | * | 116 | * |
@@ -136,6 +161,30 @@ GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, | |||
136 | 161 | ||
137 | 162 | ||
138 | /** | 163 | /** |
164 | * Run a prepared SELECT statement. | ||
165 | * | ||
166 | * @param mc mysql context | ||
167 | * @param s statement to run | ||
168 | * @param result_size number of elements in results array | ||
169 | * @param results pointer to already initialized MYSQL_BIND | ||
170 | * array (of sufficient size) for passing results | ||
171 | * @param ap pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective | ||
172 | * values (size + buffer-reference for pointers); terminated | ||
173 | * with "-1" | ||
174 | * @return GNUNET_SYSERR on error, otherwise | ||
175 | * the number of successfully affected (or queried) rows | ||
176 | */ | ||
177 | int | ||
178 | GNUNET_MYSQL_statement_run_prepared_select_va (struct GNUNET_MYSQL_Context *mc, | ||
179 | struct GNUNET_MYSQL_StatementHandle *s, | ||
180 | unsigned int result_size, | ||
181 | MYSQL_BIND * results, | ||
182 | GNUNET_MYSQL_DataProcessor processor, | ||
183 | void *processor_cls, | ||
184 | va_list ap); | ||
185 | |||
186 | |||
187 | /** | ||
139 | * Run a prepared statement that does NOT produce results. | 188 | * Run a prepared statement that does NOT produce results. |
140 | * | 189 | * |
141 | * @param mc mysql context | 190 | * @param mc mysql context |
diff --git a/src/mysql/mysql.c b/src/mysql/mysql.c index 1c3166dc7..67d2e63d2 100644 --- a/src/mysql/mysql.c +++ b/src/mysql/mysql.c | |||
@@ -315,12 +315,12 @@ GNUNET_MYSQL_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
315 | 315 | ||
316 | /** | 316 | /** |
317 | * Close database connection and all prepared statements (we got a DB | 317 | * Close database connection and all prepared statements (we got a DB |
318 | * disconnect error). | 318 | * error). |
319 | * | 319 | * |
320 | * @param mc mysql context | 320 | * @param mc mysql context |
321 | */ | 321 | */ |
322 | static void | 322 | void |
323 | iclose (struct GNUNET_MYSQL_Context *mc) | 323 | GNUNET_MYSQL_statements_invalidate (struct GNUNET_MYSQL_Context *mc) |
324 | { | 324 | { |
325 | struct GNUNET_MYSQL_StatementHandle *sh; | 325 | struct GNUNET_MYSQL_StatementHandle *sh; |
326 | 326 | ||
@@ -351,7 +351,7 @@ GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc) | |||
351 | { | 351 | { |
352 | struct GNUNET_MYSQL_StatementHandle *sh; | 352 | struct GNUNET_MYSQL_StatementHandle *sh; |
353 | 353 | ||
354 | iclose (mc); | 354 | GNUNET_MYSQL_statements_invalidate (mc); |
355 | while (NULL != (sh = mc->shead)) | 355 | while (NULL != (sh = mc->shead)) |
356 | { | 356 | { |
357 | GNUNET_CONTAINER_DLL_remove (mc->shead, mc->stail, sh); | 357 | GNUNET_CONTAINER_DLL_remove (mc->shead, mc->stail, sh); |
@@ -402,7 +402,7 @@ GNUNET_MYSQL_statement_run (struct GNUNET_MYSQL_Context *mc, | |||
402 | if (mysql_error (mc->dbf)[0]) | 402 | if (mysql_error (mc->dbf)[0]) |
403 | { | 403 | { |
404 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", mc); | 404 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", mc); |
405 | iclose (mc); | 405 | GNUNET_MYSQL_statements_invalidate (mc); |
406 | return GNUNET_SYSERR; | 406 | return GNUNET_SYSERR; |
407 | } | 407 | } |
408 | return GNUNET_OK; | 408 | return GNUNET_OK; |
@@ -427,7 +427,7 @@ prepare_statement (struct GNUNET_MYSQL_Context *mc, | |||
427 | sh->statement = mysql_stmt_init (mc->dbf); | 427 | sh->statement = mysql_stmt_init (mc->dbf); |
428 | if (NULL == sh->statement) | 428 | if (NULL == sh->statement) |
429 | { | 429 | { |
430 | iclose (mc); | 430 | GNUNET_MYSQL_statements_invalidate (mc); |
431 | return GNUNET_SYSERR; | 431 | return GNUNET_SYSERR; |
432 | } | 432 | } |
433 | if (0 != mysql_stmt_prepare (sh->statement, sh->query, strlen (sh->query))) | 433 | if (0 != mysql_stmt_prepare (sh->statement, sh->query, strlen (sh->query))) |
@@ -435,7 +435,7 @@ prepare_statement (struct GNUNET_MYSQL_Context *mc, | |||
435 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", mc); | 435 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", mc); |
436 | mysql_stmt_close (sh->statement); | 436 | mysql_stmt_close (sh->statement); |
437 | sh->statement = NULL; | 437 | sh->statement = NULL; |
438 | iclose (mc); | 438 | GNUNET_MYSQL_statements_invalidate (mc); |
439 | return GNUNET_SYSERR; | 439 | return GNUNET_SYSERR; |
440 | } | 440 | } |
441 | sh->valid = GNUNET_YES; | 441 | sh->valid = GNUNET_YES; |
@@ -444,6 +444,24 @@ prepare_statement (struct GNUNET_MYSQL_Context *mc, | |||
444 | 444 | ||
445 | 445 | ||
446 | /** | 446 | /** |
447 | * Get internal handle for a prepared statement. This function should rarely | ||
448 | * be used, and if, with caution! On failures during the interaction with | ||
449 | * the handle, you must call 'GNUNET_MYSQL_statements_invalidate'! | ||
450 | * | ||
451 | * @param mc mysql context | ||
452 | * @param sh prepared statement to introspect | ||
453 | * @return MySQL statement handle, NULL on error | ||
454 | */ | ||
455 | MYSQL_STMT * | ||
456 | GNUNET_MYSQL_statement_get_stmt (struct GNUNET_MYSQL_Context *mc, | ||
457 | struct GNUNET_MYSQL_StatementHandle *sh) | ||
458 | { | ||
459 | (void) prepare_statement (mc, sh); | ||
460 | return sh->statement; | ||
461 | } | ||
462 | |||
463 | |||
464 | /** | ||
447 | * Bind the parameters for the given MySQL statement | 465 | * Bind the parameters for the given MySQL statement |
448 | * and run it. | 466 | * and run it. |
449 | * | 467 | * |
@@ -519,7 +537,7 @@ init_params (struct GNUNET_MYSQL_Context *mc, | |||
519 | _("`%s' failed at %s:%d with error: %s\n"), | 537 | _("`%s' failed at %s:%d with error: %s\n"), |
520 | "mysql_stmt_bind_param", __FILE__, __LINE__, | 538 | "mysql_stmt_bind_param", __FILE__, __LINE__, |
521 | mysql_stmt_error (sh->statement)); | 539 | mysql_stmt_error (sh->statement)); |
522 | iclose (mc); | 540 | GNUNET_MYSQL_statements_invalidate (mc); |
523 | return GNUNET_SYSERR; | 541 | return GNUNET_SYSERR; |
524 | } | 542 | } |
525 | if (mysql_stmt_execute (sh->statement)) | 543 | if (mysql_stmt_execute (sh->statement)) |
@@ -529,75 +547,71 @@ init_params (struct GNUNET_MYSQL_Context *mc, | |||
529 | _("`%s' failed at %s:%d with error: %s\n"), | 547 | _("`%s' failed at %s:%d with error: %s\n"), |
530 | "mysql_stmt_execute", __FILE__, __LINE__, | 548 | "mysql_stmt_execute", __FILE__, __LINE__, |
531 | mysql_stmt_error (sh->statement)); | 549 | mysql_stmt_error (sh->statement)); |
532 | iclose (mc); | 550 | GNUNET_MYSQL_statements_invalidate (mc); |
533 | return GNUNET_SYSERR; | 551 | return GNUNET_SYSERR; |
534 | } | 552 | } |
535 | return GNUNET_OK; | 553 | return GNUNET_OK; |
536 | } | 554 | } |
537 | 555 | ||
538 | 556 | ||
557 | |||
539 | /** | 558 | /** |
540 | * Run a prepared SELECT statement. | 559 | * Run a prepared SELECT statement. |
541 | * | 560 | * |
542 | * @param mc mysql context | 561 | * @param mc mysql context |
543 | * @param sh handle to SELECT statment | 562 | * @param s statement to run |
544 | * @param result_size number of elements in results array | 563 | * @param result_size number of elements in results array |
545 | * @param results pointer to already initialized MYSQL_BIND | 564 | * @param results pointer to already initialized MYSQL_BIND |
546 | * array (of sufficient size) for passing results | 565 | * array (of sufficient size) for passing results |
547 | * @param processor function to call on each result | 566 | * @param ap pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective |
548 | * @param processor_cls extra argument to processor | ||
549 | * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective | ||
550 | * values (size + buffer-reference for pointers); terminated | 567 | * values (size + buffer-reference for pointers); terminated |
551 | * with "-1" | 568 | * with "-1" |
552 | * @return GNUNET_SYSERR on error, otherwise | 569 | * @return GNUNET_SYSERR on error, otherwise |
553 | * the number of successfully affected (or queried) rows | 570 | * the number of successfully affected (or queried) rows |
554 | */ | 571 | */ |
555 | int | 572 | int |
556 | GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, | 573 | GNUNET_MYSQL_statement_run_prepared_select_va (struct GNUNET_MYSQL_Context *mc, |
557 | struct GNUNET_MYSQL_StatementHandle *sh, | 574 | struct GNUNET_MYSQL_StatementHandle *s, |
558 | unsigned int result_size, MYSQL_BIND * results, | 575 | unsigned int result_size, |
559 | GNUNET_MYSQL_DataProcessor processor, | 576 | MYSQL_BIND * results, |
560 | void *processor_cls, ...) | 577 | GNUNET_MYSQL_DataProcessor processor, |
578 | void *processor_cls, | ||
579 | va_list ap) | ||
561 | { | 580 | { |
562 | va_list ap; | ||
563 | int ret; | 581 | int ret; |
564 | unsigned int rsize; | 582 | unsigned int rsize; |
565 | int total; | 583 | int total; |
566 | 584 | ||
567 | if (GNUNET_OK != prepare_statement (mc, sh)) | 585 | if (GNUNET_OK != prepare_statement (mc, s)) |
568 | { | 586 | { |
569 | GNUNET_break (0); | 587 | GNUNET_break (0); |
570 | return GNUNET_SYSERR; | 588 | return GNUNET_SYSERR; |
571 | } | 589 | } |
572 | va_start (ap, processor_cls); | 590 | if (GNUNET_OK != init_params (mc, s, ap)) |
573 | if (GNUNET_OK != init_params (mc, sh, ap)) | ||
574 | { | 591 | { |
575 | GNUNET_break (0); | 592 | GNUNET_break (0); |
576 | va_end (ap); | ||
577 | return GNUNET_SYSERR; | 593 | return GNUNET_SYSERR; |
578 | } | 594 | } |
579 | va_end (ap); | 595 | rsize = mysql_stmt_field_count (s->statement); |
580 | rsize = mysql_stmt_field_count (sh->statement); | ||
581 | if (rsize > result_size) | 596 | if (rsize > result_size) |
582 | { | 597 | { |
583 | GNUNET_break (0); | 598 | GNUNET_break (0); |
584 | return GNUNET_SYSERR; | 599 | return GNUNET_SYSERR; |
585 | } | 600 | } |
586 | if (mysql_stmt_bind_result (sh->statement, results)) | 601 | if (mysql_stmt_bind_result (s->statement, results)) |
587 | { | 602 | { |
588 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | 603 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
589 | "mysql", | 604 | _("`%s' failed at %s:%d with error: %s\n"), |
590 | _("`%s' failed at %s:%d with error: %s\n"), | 605 | "mysql_stmt_bind_result", __FILE__, __LINE__, |
591 | "mysql_stmt_bind_result", __FILE__, __LINE__, | 606 | mysql_stmt_error (s->statement)); |
592 | mysql_stmt_error (sh->statement)); | 607 | GNUNET_MYSQL_statements_invalidate (mc); |
593 | iclose (mc); | ||
594 | return GNUNET_SYSERR; | 608 | return GNUNET_SYSERR; |
595 | } | 609 | } |
596 | 610 | ||
597 | total = 0; | 611 | total = 0; |
598 | while (1) | 612 | while (1) |
599 | { | 613 | { |
600 | ret = mysql_stmt_fetch (sh->statement); | 614 | ret = mysql_stmt_fetch (s->statement); |
601 | if (ret == MYSQL_NO_DATA) | 615 | if (ret == MYSQL_NO_DATA) |
602 | break; | 616 | break; |
603 | if (ret != 0) | 617 | if (ret != 0) |
@@ -606,21 +620,54 @@ GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, | |||
606 | "mysql", | 620 | "mysql", |
607 | _("`%s' failed at %s:%d with error: %s\n"), | 621 | _("`%s' failed at %s:%d with error: %s\n"), |
608 | "mysql_stmt_fetch", __FILE__, __LINE__, | 622 | "mysql_stmt_fetch", __FILE__, __LINE__, |
609 | mysql_stmt_error (sh->statement)); | 623 | mysql_stmt_error (s->statement)); |
610 | iclose (mc); | 624 | GNUNET_MYSQL_statements_invalidate (mc); |
611 | return GNUNET_SYSERR; | 625 | return GNUNET_SYSERR; |
612 | } | 626 | } |
613 | if (processor != NULL) | ||
614 | if (GNUNET_OK != processor (processor_cls, rsize, results)) | ||
615 | break; | ||
616 | total++; | 627 | total++; |
628 | if ( (NULL == processor) || | ||
629 | (GNUNET_OK != processor (processor_cls, rsize, results)) ) | ||
630 | break; | ||
617 | } | 631 | } |
618 | mysql_stmt_reset (sh->statement); | 632 | mysql_stmt_reset (s->statement); |
619 | return total; | 633 | return total; |
620 | } | 634 | } |
621 | 635 | ||
622 | 636 | ||
623 | /** | 637 | /** |
638 | * Run a prepared SELECT statement. | ||
639 | * | ||
640 | * @param mc mysql context | ||
641 | * @param sh handle to SELECT statment | ||
642 | * @param result_size number of elements in results array | ||
643 | * @param results pointer to already initialized MYSQL_BIND | ||
644 | * array (of sufficient size) for passing results | ||
645 | * @param processor function to call on each result | ||
646 | * @param processor_cls extra argument to processor | ||
647 | * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective | ||
648 | * values (size + buffer-reference for pointers); terminated | ||
649 | * with "-1" | ||
650 | * @return GNUNET_SYSERR on error, otherwise | ||
651 | * the number of successfully affected (or queried) rows | ||
652 | */ | ||
653 | int | ||
654 | GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, | ||
655 | struct GNUNET_MYSQL_StatementHandle *sh, | ||
656 | unsigned int result_size, MYSQL_BIND * results, | ||
657 | GNUNET_MYSQL_DataProcessor processor, | ||
658 | void *processor_cls, ...) | ||
659 | { | ||
660 | va_list ap; | ||
661 | int ret; | ||
662 | |||
663 | va_start (ap, processor_cls); | ||
664 | ret = GNUNET_MYSQL_statement_run_prepared_select_va (mc, sh, result_size, results, processor, processor_cls, ap); | ||
665 | va_end (ap); | ||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | |||
670 | /** | ||
624 | * Run a prepared statement that does NOT produce results. | 671 | * Run a prepared statement that does NOT produce results. |
625 | * | 672 | * |
626 | * @param mc mysql context | 673 | * @param mc mysql context |