diff options
Diffstat (limited to 'src/datastore/plugin_datastore_sqlite.c')
-rw-r--r-- | src/datastore/plugin_datastore_sqlite.c | 892 |
1 files changed, 479 insertions, 413 deletions
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index 18a3aa4ac..1f874e190 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of GNUnet | 2 | * This file is part of GNUnet |
3 | * Copyright (C) 2009, 2011 GNUnet e.V. | 3 | * Copyright (C) 2009, 2011, 2017 GNUnet e.V. |
4 | * | 4 | * |
5 | * GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | * it under the terms of the GNU General Public License as published |
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include "platform.h" | 27 | #include "platform.h" |
28 | #include "gnunet_datastore_plugin.h" | 28 | #include "gnunet_datastore_plugin.h" |
29 | #include "gnunet_sq_lib.h" | ||
29 | #include <sqlite3.h> | 30 | #include <sqlite3.h> |
30 | 31 | ||
31 | 32 | ||
@@ -127,6 +128,11 @@ struct Plugin | |||
127 | sqlite3_stmt *insertContent; | 128 | sqlite3_stmt *insertContent; |
128 | 129 | ||
129 | /** | 130 | /** |
131 | * Precompiled SQL for selection | ||
132 | */ | ||
133 | sqlite3_stmt *get; | ||
134 | |||
135 | /** | ||
130 | * Should the database be dropped on shutdown? | 136 | * Should the database be dropped on shutdown? |
131 | */ | 137 | */ |
132 | int drop_on_shutdown; | 138 | int drop_on_shutdown; |
@@ -150,11 +156,17 @@ sq_prepare (sqlite3 *dbh, | |||
150 | char *dummy; | 156 | char *dummy; |
151 | int result; | 157 | int result; |
152 | 158 | ||
153 | result = | 159 | result = sqlite3_prepare_v2 (dbh, |
154 | sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt, | 160 | zSql, |
155 | (const char **) &dummy); | 161 | strlen (zSql), |
156 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | 162 | ppStmt, |
157 | "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result); | 163 | (const char **) &dummy); |
164 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
165 | "sqlite", | ||
166 | "Prepared `%s' / %p: %d\n", | ||
167 | zSql, | ||
168 | *ppStmt, | ||
169 | result); | ||
158 | return result; | 170 | return result; |
159 | } | 171 | } |
160 | 172 | ||
@@ -229,35 +241,41 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
229 | { | 241 | { |
230 | sqlite3_stmt *stmt; | 242 | sqlite3_stmt *stmt; |
231 | char *afsdir; | 243 | char *afsdir; |
232 | |||
233 | #if ENULL_DEFINED | 244 | #if ENULL_DEFINED |
234 | char *e; | 245 | char *e; |
235 | #endif | 246 | #endif |
236 | 247 | ||
237 | if (GNUNET_OK != | 248 | if (GNUNET_OK != |
238 | GNUNET_CONFIGURATION_get_value_filename (cfg, "datastore-sqlite", | 249 | GNUNET_CONFIGURATION_get_value_filename (cfg, |
239 | "FILENAME", &afsdir)) | 250 | "datastore-sqlite", |
251 | "FILENAME", | ||
252 | &afsdir)) | ||
240 | { | 253 | { |
241 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | 254 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, |
242 | "datastore-sqlite", "FILENAME"); | 255 | "datastore-sqlite", |
256 | "FILENAME"); | ||
243 | return GNUNET_SYSERR; | 257 | return GNUNET_SYSERR; |
244 | } | 258 | } |
245 | if (GNUNET_OK != GNUNET_DISK_file_test (afsdir)) | 259 | if (GNUNET_OK != GNUNET_DISK_file_test (afsdir)) |
246 | { | 260 | { |
247 | if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir)) | 261 | if (GNUNET_OK != |
262 | GNUNET_DISK_directory_create_for_file (afsdir)) | ||
248 | { | 263 | { |
249 | GNUNET_break (0); | 264 | GNUNET_break (0); |
250 | GNUNET_free (afsdir); | 265 | GNUNET_free (afsdir); |
251 | return GNUNET_SYSERR; | 266 | return GNUNET_SYSERR; |
252 | } | 267 | } |
253 | /* database is new or got deleted, reset payload to zero! */ | 268 | /* database is new or got deleted, reset payload to zero! */ |
254 | plugin->env->duc (plugin->env->cls, 0); | 269 | if (NULL != plugin->env->duc) |
270 | plugin->env->duc (plugin->env->cls, | ||
271 | 0); | ||
255 | } | 272 | } |
256 | /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ | 273 | /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ |
257 | plugin->fn = afsdir; | 274 | plugin->fn = afsdir; |
258 | 275 | ||
259 | /* Open database and precompile statements */ | 276 | /* Open database and precompile statements */ |
260 | if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) | 277 | if (SQLITE_OK != |
278 | sqlite3_open (plugin->fn, &plugin->dbh)) | ||
261 | { | 279 | { |
262 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite", | 280 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite", |
263 | _("Unable to initialize SQLite: %s.\n"), | 281 | _("Unable to initialize SQLite: %s.\n"), |
@@ -265,25 +283,32 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
265 | return GNUNET_SYSERR; | 283 | return GNUNET_SYSERR; |
266 | } | 284 | } |
267 | CHECK (SQLITE_OK == | 285 | CHECK (SQLITE_OK == |
268 | sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL, | 286 | sqlite3_exec (plugin->dbh, |
287 | "PRAGMA temp_store=MEMORY", NULL, NULL, | ||
269 | ENULL)); | 288 | ENULL)); |
270 | CHECK (SQLITE_OK == | 289 | CHECK (SQLITE_OK == |
271 | sqlite3_exec (plugin->dbh, "PRAGMA synchronous=OFF", NULL, NULL, | 290 | sqlite3_exec (plugin->dbh, |
291 | "PRAGMA synchronous=OFF", NULL, NULL, | ||
272 | ENULL)); | 292 | ENULL)); |
273 | CHECK (SQLITE_OK == | 293 | CHECK (SQLITE_OK == |
274 | sqlite3_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF", NULL, NULL, | 294 | sqlite3_exec (plugin->dbh, |
295 | "PRAGMA legacy_file_format=OFF", NULL, NULL, | ||
275 | ENULL)); | 296 | ENULL)); |
276 | CHECK (SQLITE_OK == | 297 | CHECK (SQLITE_OK == |
277 | sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL, | 298 | sqlite3_exec (plugin->dbh, |
299 | "PRAGMA auto_vacuum=INCREMENTAL", NULL, | ||
278 | NULL, ENULL)); | 300 | NULL, ENULL)); |
279 | CHECK (SQLITE_OK == | 301 | CHECK (SQLITE_OK == |
280 | sqlite3_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, | 302 | sqlite3_exec (plugin->dbh, |
303 | "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, | ||
281 | ENULL)); | 304 | ENULL)); |
282 | CHECK (SQLITE_OK == | 305 | CHECK (SQLITE_OK == |
283 | sqlite3_exec (plugin->dbh, "PRAGMA page_size=4092", NULL, NULL, | 306 | sqlite3_exec (plugin->dbh, |
307 | "PRAGMA page_size=4092", NULL, NULL, | ||
284 | ENULL)); | 308 | ENULL)); |
285 | 309 | ||
286 | CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS)); | 310 | CHECK (SQLITE_OK == |
311 | sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS)); | ||
287 | 312 | ||
288 | 313 | ||
289 | /* We have to do it here, because otherwise precompiling SQL might fail */ | 314 | /* We have to do it here, because otherwise precompiling SQL might fail */ |
@@ -291,80 +316,120 @@ database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
291 | sq_prepare (plugin->dbh, | 316 | sq_prepare (plugin->dbh, |
292 | "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn090'", | 317 | "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn090'", |
293 | &stmt)); | 318 | &stmt)); |
294 | if ((sqlite3_step (stmt) == SQLITE_DONE) && | 319 | |
295 | (sqlite3_exec | 320 | /* FIXME: SQLite does not have unsigned integers! This is ok for the type column because |
296 | (plugin->dbh, | 321 | * we only test equality on it and can cast it to/from uint32_t. For repl, prio, and anonLevel |
297 | "CREATE TABLE gn090 (" " repl INT4 NOT NULL DEFAULT 0," | 322 | * we do math or inequality tests, so we can't handle the entire range of uint32_t. |
298 | " type INT4 NOT NULL DEFAULT 0," " prio INT4 NOT NULL DEFAULT 0," | 323 | * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC. |
299 | " anonLevel INT4 NOT NULL DEFAULT 0," | 324 | */ |
300 | " expire INT8 NOT NULL DEFAULT 0," " rvalue INT8 NOT NULL," | 325 | if ( (SQLITE_DONE == |
301 | " hash TEXT NOT NULL DEFAULT ''," " vhash TEXT NOT NULL DEFAULT ''," | 326 | sqlite3_step (stmt)) && |
302 | " value BLOB NOT NULL DEFAULT '')", NULL, NULL, NULL) != SQLITE_OK)) | 327 | (SQLITE_OK != |
328 | sqlite3_exec (plugin->dbh, | ||
329 | "CREATE TABLE gn090 (" | ||
330 | " repl INT4 NOT NULL DEFAULT 0," | ||
331 | " type INT4 NOT NULL DEFAULT 0," | ||
332 | " prio INT4 NOT NULL DEFAULT 0," | ||
333 | " anonLevel INT4 NOT NULL DEFAULT 0," | ||
334 | " expire INT8 NOT NULL DEFAULT 0," | ||
335 | " rvalue INT8 NOT NULL," | ||
336 | " hash TEXT NOT NULL DEFAULT ''," | ||
337 | " vhash TEXT NOT NULL DEFAULT ''," | ||
338 | " value BLOB NOT NULL DEFAULT '')", | ||
339 | NULL, | ||
340 | NULL, | ||
341 | NULL)) ) | ||
303 | { | 342 | { |
304 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); | 343 | LOG_SQLITE (plugin, |
344 | GNUNET_ERROR_TYPE_ERROR, | ||
345 | "sqlite3_exec"); | ||
305 | sqlite3_finalize (stmt); | 346 | sqlite3_finalize (stmt); |
306 | return GNUNET_SYSERR; | 347 | return GNUNET_SYSERR; |
307 | } | 348 | } |
308 | sqlite3_finalize (stmt); | 349 | sqlite3_finalize (stmt); |
309 | create_indices (plugin->dbh); | 350 | create_indices (plugin->dbh); |
310 | 351 | ||
311 | if ((sq_prepare | 352 | #define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, _ROWID_" |
312 | (plugin->dbh, | 353 | if ( (SQLITE_OK != |
313 | "UPDATE gn090 " | 354 | sq_prepare (plugin->dbh, |
314 | "SET prio = prio + ?, expire = MAX(expire,?) WHERE _ROWID_ = ?", | 355 | "UPDATE gn090 " |
315 | &plugin->updPrio) != SQLITE_OK) || | 356 | "SET prio = prio + ?, " |
316 | (sq_prepare | 357 | "repl = repl + ?, " |
317 | (plugin->dbh, | 358 | "expire = MAX(expire, ?) " |
318 | "UPDATE gn090 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?", | 359 | "WHERE _ROWID_ = ?", |
319 | &plugin->updRepl) != SQLITE_OK) || | 360 | &plugin->updPrio)) || |
320 | (sq_prepare | 361 | (SQLITE_OK != |
321 | (plugin->dbh, | 362 | sq_prepare (plugin->dbh, |
322 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " | 363 | "UPDATE gn090 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?", |
364 | &plugin->updRepl)) || | ||
365 | (SQLITE_OK != | ||
366 | sq_prepare (plugin->dbh, | ||
367 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
323 | #if SQLITE_VERSION_NUMBER >= 3007000 | 368 | #if SQLITE_VERSION_NUMBER >= 3007000 |
324 | "INDEXED BY idx_repl_rvalue " | 369 | "INDEXED BY idx_repl_rvalue " |
325 | #endif | 370 | #endif |
326 | "WHERE repl=?2 AND " " (rvalue>=?1 OR " | 371 | "WHERE repl=?2 AND " " (rvalue>=?1 OR " |
327 | " NOT EXISTS (SELECT 1 FROM gn090 " | 372 | " NOT EXISTS (SELECT 1 FROM gn090 " |
328 | #if SQLITE_VERSION_NUMBER >= 3007000 | 373 | #if SQLITE_VERSION_NUMBER >= 3007000 |
329 | "INDEXED BY idx_repl_rvalue " | 374 | "INDEXED BY idx_repl_rvalue " |
330 | #endif | 375 | #endif |
331 | "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) " | 376 | "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) " |
332 | "ORDER BY rvalue ASC LIMIT 1", &plugin->selRepl) != SQLITE_OK) || | 377 | "ORDER BY rvalue ASC LIMIT 1", |
333 | (sq_prepare (plugin->dbh, "SELECT MAX(repl) FROM gn090" | 378 | &plugin->selRepl)) || |
379 | (SQLITE_OK != | ||
380 | sq_prepare (plugin->dbh, | ||
381 | "SELECT MAX(repl) FROM gn090" | ||
334 | #if SQLITE_VERSION_NUMBER >= 3007000 | 382 | #if SQLITE_VERSION_NUMBER >= 3007000 |
335 | " INDEXED BY idx_repl_rvalue" | 383 | " INDEXED BY idx_repl_rvalue" |
336 | #endif | 384 | #endif |
337 | "", &plugin->maxRepl) != SQLITE_OK) || | 385 | "", |
338 | (sq_prepare | 386 | &plugin->maxRepl)) || |
339 | (plugin->dbh, | 387 | (SQLITE_OK != |
340 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " | 388 | sq_prepare (plugin->dbh, |
389 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
341 | #if SQLITE_VERSION_NUMBER >= 3007000 | 390 | #if SQLITE_VERSION_NUMBER >= 3007000 |
342 | "INDEXED BY idx_expire " | 391 | "INDEXED BY idx_expire " |
343 | #endif | 392 | #endif |
344 | "WHERE NOT EXISTS (SELECT 1 FROM gn090 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) " | 393 | "WHERE NOT EXISTS (SELECT 1 FROM gn090 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) " |
345 | "ORDER BY expire ASC LIMIT 1", &plugin->selExpi) != SQLITE_OK) || | 394 | "ORDER BY expire ASC LIMIT 1", |
346 | (sq_prepare | 395 | &plugin->selExpi)) || |
347 | (plugin->dbh, | 396 | (SQLITE_OK != |
348 | "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " | 397 | sq_prepare (plugin->dbh, |
398 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
349 | #if SQLITE_VERSION_NUMBER >= 3007000 | 399 | #if SQLITE_VERSION_NUMBER >= 3007000 |
350 | "INDEXED BY idx_anon_type_hash " | 400 | "INDEXED BY idx_anon_type_hash " |
351 | #endif | 401 | #endif |
352 | "WHERE (anonLevel = 0 AND type=?1) " | 402 | "WHERE _ROWID_ >= ? AND " |
353 | "ORDER BY hash DESC LIMIT 1 OFFSET ?2", | 403 | "anonLevel = 0 AND " |
354 | &plugin->selZeroAnon) != SQLITE_OK) || | 404 | "type = ? " |
355 | (sq_prepare | 405 | "ORDER BY _ROWID_ ASC LIMIT 1", |
356 | (plugin->dbh, | 406 | &plugin->selZeroAnon)) || |
357 | "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " | 407 | (SQLITE_OK != |
358 | "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", | 408 | sq_prepare (plugin->dbh, |
359 | &plugin->insertContent) != SQLITE_OK) || | 409 | "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " |
360 | (sq_prepare | 410 | "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", |
361 | (plugin->dbh, "DELETE FROM gn090 WHERE _ROWID_ = ?", | 411 | &plugin->insertContent)) || |
362 | &plugin->delRow) != SQLITE_OK)) | 412 | (SQLITE_OK != |
413 | sq_prepare (plugin->dbh, | ||
414 | "SELECT " RESULT_COLUMNS " FROM gn090 " | ||
415 | "WHERE _ROWID_ >= ? AND " | ||
416 | "(rvalue >= ? OR 0 = ?) AND " | ||
417 | "(hash = ? OR 0 = ?) AND " | ||
418 | "(vhash = ? OR 0 = ?) AND " | ||
419 | "(type = ? OR 0 = ?) " | ||
420 | "ORDER BY _ROWID_ ASC LIMIT 1", | ||
421 | &plugin->get)) || | ||
422 | (SQLITE_OK != | ||
423 | sq_prepare (plugin->dbh, | ||
424 | "DELETE FROM gn090 WHERE _ROWID_ = ?", | ||
425 | &plugin->delRow)) | ||
426 | ) | ||
363 | { | 427 | { |
364 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "precompiling"); | 428 | LOG_SQLITE (plugin, |
429 | GNUNET_ERROR_TYPE_ERROR, | ||
430 | "precompiling"); | ||
365 | return GNUNET_SYSERR; | 431 | return GNUNET_SYSERR; |
366 | } | 432 | } |
367 | |||
368 | return GNUNET_OK; | 433 | return GNUNET_OK; |
369 | } | 434 | } |
370 | 435 | ||
@@ -379,51 +444,60 @@ static void | |||
379 | database_shutdown (struct Plugin *plugin) | 444 | database_shutdown (struct Plugin *plugin) |
380 | { | 445 | { |
381 | int result; | 446 | int result; |
382 | |||
383 | #if SQLITE_VERSION_NUMBER >= 3007000 | 447 | #if SQLITE_VERSION_NUMBER >= 3007000 |
384 | sqlite3_stmt *stmt; | 448 | sqlite3_stmt *stmt; |
385 | #endif | 449 | #endif |
386 | 450 | ||
387 | if (plugin->delRow != NULL) | 451 | if (NULL != plugin->delRow) |
388 | sqlite3_finalize (plugin->delRow); | 452 | sqlite3_finalize (plugin->delRow); |
389 | if (plugin->updPrio != NULL) | 453 | if (NULL != plugin->updPrio) |
390 | sqlite3_finalize (plugin->updPrio); | 454 | sqlite3_finalize (plugin->updPrio); |
391 | if (plugin->updRepl != NULL) | 455 | if (NULL != plugin->updRepl) |
392 | sqlite3_finalize (plugin->updRepl); | 456 | sqlite3_finalize (plugin->updRepl); |
393 | if (plugin->selRepl != NULL) | 457 | if (NULL != plugin->selRepl) |
394 | sqlite3_finalize (plugin->selRepl); | 458 | sqlite3_finalize (plugin->selRepl); |
395 | if (plugin->maxRepl != NULL) | 459 | if (NULL != plugin->maxRepl) |
396 | sqlite3_finalize (plugin->maxRepl); | 460 | sqlite3_finalize (plugin->maxRepl); |
397 | if (plugin->selExpi != NULL) | 461 | if (NULL != plugin->selExpi) |
398 | sqlite3_finalize (plugin->selExpi); | 462 | sqlite3_finalize (plugin->selExpi); |
399 | if (plugin->selZeroAnon != NULL) | 463 | if (NULL != plugin->selZeroAnon) |
400 | sqlite3_finalize (plugin->selZeroAnon); | 464 | sqlite3_finalize (plugin->selZeroAnon); |
401 | if (plugin->insertContent != NULL) | 465 | if (NULL != plugin->insertContent) |
402 | sqlite3_finalize (plugin->insertContent); | 466 | sqlite3_finalize (plugin->insertContent); |
467 | if (NULL != plugin->get) | ||
468 | sqlite3_finalize (plugin->get); | ||
403 | result = sqlite3_close (plugin->dbh); | 469 | result = sqlite3_close (plugin->dbh); |
404 | #if SQLITE_VERSION_NUMBER >= 3007000 | 470 | #if SQLITE_VERSION_NUMBER >= 3007000 |
405 | if (result == SQLITE_BUSY) | 471 | if (result == SQLITE_BUSY) |
406 | { | 472 | { |
407 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", | 473 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, |
408 | _ | 474 | "sqlite", |
409 | ("Tried to close sqlite without finalizing all prepared statements.\n")); | 475 | _("Tried to close sqlite without finalizing all prepared statements.\n")); |
410 | stmt = sqlite3_next_stmt (plugin->dbh, NULL); | 476 | stmt = sqlite3_next_stmt (plugin->dbh, |
411 | while (stmt != NULL) | 477 | NULL); |
478 | while (NULL != stmt) | ||
412 | { | 479 | { |
413 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | 480 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
414 | "Closing statement %p\n", stmt); | 481 | "sqlite", |
482 | "Closing statement %p\n", | ||
483 | stmt); | ||
415 | result = sqlite3_finalize (stmt); | 484 | result = sqlite3_finalize (stmt); |
416 | if (result != SQLITE_OK) | 485 | if (result != SQLITE_OK) |
417 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", | 486 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, |
418 | "Failed to close statement %p: %d\n", stmt, result); | 487 | "sqlite", |
419 | stmt = sqlite3_next_stmt (plugin->dbh, NULL); | 488 | "Failed to close statement %p: %d\n", |
489 | stmt, | ||
490 | result); | ||
491 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
492 | NULL); | ||
420 | } | 493 | } |
421 | result = sqlite3_close (plugin->dbh); | 494 | result = sqlite3_close (plugin->dbh); |
422 | } | 495 | } |
423 | #endif | 496 | #endif |
424 | if (SQLITE_OK != result) | 497 | if (SQLITE_OK != result) |
425 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); | 498 | LOG_SQLITE (plugin, |
426 | 499 | GNUNET_ERROR_TYPE_ERROR, | |
500 | "sqlite3_close"); | ||
427 | GNUNET_free_non_null (plugin->fn); | 501 | GNUNET_free_non_null (plugin->fn); |
428 | } | 502 | } |
429 | 503 | ||
@@ -437,31 +511,27 @@ database_shutdown (struct Plugin *plugin) | |||
437 | */ | 511 | */ |
438 | static int | 512 | static int |
439 | delete_by_rowid (struct Plugin *plugin, | 513 | delete_by_rowid (struct Plugin *plugin, |
440 | unsigned long long rid) | 514 | uint64_t rid) |
441 | { | 515 | { |
442 | if (SQLITE_OK != sqlite3_bind_int64 (plugin->delRow, 1, rid)) | 516 | struct GNUNET_SQ_QueryParam params[] = { |
443 | { | 517 | GNUNET_SQ_query_param_uint64 (&rid), |
444 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 518 | GNUNET_SQ_query_param_end |
445 | "sqlite3_bind_XXXX"); | 519 | }; |
446 | if (SQLITE_OK != sqlite3_reset (plugin->delRow)) | 520 | |
447 | LOG_SQLITE (plugin, | 521 | if (GNUNET_OK != |
448 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 522 | GNUNET_SQ_bind (plugin->delRow, |
449 | "sqlite3_reset"); | 523 | params)) |
450 | return GNUNET_SYSERR; | 524 | return GNUNET_SYSERR; |
451 | } | ||
452 | if (SQLITE_DONE != sqlite3_step (plugin->delRow)) | 525 | if (SQLITE_DONE != sqlite3_step (plugin->delRow)) |
453 | { | 526 | { |
454 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 527 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
455 | "sqlite3_step"); | 528 | "sqlite3_step"); |
456 | if (SQLITE_OK != sqlite3_reset (plugin->delRow)) | 529 | GNUNET_SQ_reset (plugin->dbh, |
457 | LOG_SQLITE (plugin, | 530 | plugin->delRow); |
458 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
459 | "sqlite3_reset"); | ||
460 | return GNUNET_SYSERR; | 531 | return GNUNET_SYSERR; |
461 | } | 532 | } |
462 | if (SQLITE_OK != sqlite3_reset (plugin->delRow)) | 533 | GNUNET_SQ_reset (plugin->dbh, |
463 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 534 | plugin->delRow); |
464 | "sqlite3_reset"); | ||
465 | return GNUNET_OK; | 535 | return GNUNET_OK; |
466 | } | 536 | } |
467 | 537 | ||
@@ -494,12 +564,25 @@ sqlite_plugin_put (void *cls, | |||
494 | PluginPutCont cont, | 564 | PluginPutCont cont, |
495 | void *cont_cls) | 565 | void *cont_cls) |
496 | { | 566 | { |
567 | uint64_t rvalue; | ||
568 | struct GNUNET_HashCode vhash; | ||
569 | uint32_t type32 = (uint32_t) type; | ||
570 | struct GNUNET_SQ_QueryParam params[] = { | ||
571 | GNUNET_SQ_query_param_uint32 (&replication), | ||
572 | GNUNET_SQ_query_param_uint32 (&type32), | ||
573 | GNUNET_SQ_query_param_uint32 (&priority), | ||
574 | GNUNET_SQ_query_param_uint32 (&anonymity), | ||
575 | GNUNET_SQ_query_param_absolute_time (&expiration), | ||
576 | GNUNET_SQ_query_param_uint64 (&rvalue), | ||
577 | GNUNET_SQ_query_param_auto_from_type (key), | ||
578 | GNUNET_SQ_query_param_auto_from_type (&vhash), | ||
579 | GNUNET_SQ_query_param_fixed_size (data, size), | ||
580 | GNUNET_SQ_query_param_end | ||
581 | }; | ||
497 | struct Plugin *plugin = cls; | 582 | struct Plugin *plugin = cls; |
498 | int n; | 583 | int n; |
499 | int ret; | 584 | int ret; |
500 | sqlite3_stmt *stmt; | 585 | sqlite3_stmt *stmt; |
501 | struct GNUNET_HashCode vhash; | ||
502 | uint64_t rvalue; | ||
503 | char *msg = NULL; | 586 | char *msg = NULL; |
504 | 587 | ||
505 | if (size > MAX_ITEM_SIZE) | 588 | if (size > MAX_ITEM_SIZE) |
@@ -518,26 +601,10 @@ sqlite_plugin_put (void *cls, | |||
518 | GNUNET_CRYPTO_hash (data, size, &vhash); | 601 | GNUNET_CRYPTO_hash (data, size, &vhash); |
519 | stmt = plugin->insertContent; | 602 | stmt = plugin->insertContent; |
520 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); | 603 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); |
521 | if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, replication)) || | 604 | if (GNUNET_OK != |
522 | (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) || | 605 | GNUNET_SQ_bind (stmt, |
523 | (SQLITE_OK != sqlite3_bind_int (stmt, 3, priority)) || | 606 | params)) |
524 | (SQLITE_OK != sqlite3_bind_int (stmt, 4, anonymity)) || | ||
525 | (SQLITE_OK != sqlite3_bind_int64 (stmt, 5, expiration.abs_value_us)) || | ||
526 | (SQLITE_OK != sqlite3_bind_int64 (stmt, 6, rvalue)) || | ||
527 | (SQLITE_OK != | ||
528 | sqlite3_bind_blob (stmt, 7, key, sizeof (struct GNUNET_HashCode), | ||
529 | SQLITE_TRANSIENT)) || | ||
530 | (SQLITE_OK != | ||
531 | sqlite3_bind_blob (stmt, 8, &vhash, sizeof (struct GNUNET_HashCode), | ||
532 | SQLITE_TRANSIENT)) || | ||
533 | (SQLITE_OK != sqlite3_bind_blob (stmt, 9, data, size, SQLITE_TRANSIENT))) | ||
534 | { | 607 | { |
535 | LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
536 | "sqlite3_bind_XXXX"); | ||
537 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
538 | LOG_SQLITE (plugin, | ||
539 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
540 | "sqlite3_reset"); | ||
541 | cont (cont_cls, key, size, GNUNET_SYSERR, msg); | 608 | cont (cont_cls, key, size, GNUNET_SYSERR, msg); |
542 | GNUNET_free_non_null(msg); | 609 | GNUNET_free_non_null(msg); |
543 | return; | 610 | return; |
@@ -546,7 +613,9 @@ sqlite_plugin_put (void *cls, | |||
546 | switch (n) | 613 | switch (n) |
547 | { | 614 | { |
548 | case SQLITE_DONE: | 615 | case SQLITE_DONE: |
549 | plugin->env->duc (plugin->env->cls, size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | 616 | if (NULL != plugin->env->duc) |
617 | plugin->env->duc (plugin->env->cls, | ||
618 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | ||
550 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | 619 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", |
551 | "Stored new entry (%u bytes)\n", | 620 | "Stored new entry (%u bytes)\n", |
552 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | 621 | size + GNUNET_DATASTORE_ENTRY_OVERHEAD); |
@@ -561,77 +630,71 @@ sqlite_plugin_put (void *cls, | |||
561 | default: | 630 | default: |
562 | LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 631 | LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
563 | "sqlite3_step"); | 632 | "sqlite3_step"); |
564 | if (SQLITE_OK != sqlite3_reset (stmt)) | 633 | GNUNET_SQ_reset (plugin->dbh, |
565 | LOG_SQLITE (plugin, | 634 | stmt); |
566 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
567 | "sqlite3_reset"); | ||
568 | database_shutdown (plugin); | 635 | database_shutdown (plugin); |
569 | database_setup (plugin->env->cfg, plugin); | 636 | database_setup (plugin->env->cfg, plugin); |
570 | cont (cont_cls, key, size, GNUNET_SYSERR, msg); | 637 | cont (cont_cls, key, size, GNUNET_SYSERR, msg); |
571 | GNUNET_free_non_null(msg); | 638 | GNUNET_free_non_null(msg); |
572 | return; | 639 | return; |
573 | } | 640 | } |
574 | if (SQLITE_OK != sqlite3_reset (stmt)) | 641 | GNUNET_SQ_reset (plugin->dbh, |
575 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 642 | stmt); |
576 | "sqlite3_reset"); | ||
577 | cont (cont_cls, key, size, ret, msg); | 643 | cont (cont_cls, key, size, ret, msg); |
578 | GNUNET_free_non_null(msg); | 644 | GNUNET_free_non_null(msg); |
579 | } | 645 | } |
580 | 646 | ||
581 | 647 | ||
582 | /** | 648 | /** |
583 | * Update the priority for a particular key in the datastore. If | 649 | * Update the priority, replication and expiration for a particular |
584 | * the expiration time in value is different than the time found in | 650 | * unique ID in the datastore. If the expiration time in value is |
585 | * the datastore, the higher value should be kept. For the | 651 | * different than the time found in the datastore, the higher value |
586 | * anonymity level, the lower value is to be used. The specified | 652 | * should be kept. The specified priority and replication is added |
587 | * priority should be added to the existing priority, ignoring the | 653 | * to the existing value. |
588 | * priority in value. | ||
589 | * | ||
590 | * Note that it is possible for multiple values to match this put. | ||
591 | * In that case, all of the respective values are updated. | ||
592 | * | 654 | * |
593 | * @param cls the plugin context (state for this module) | 655 | * @param cls the plugin context (state for this module) |
594 | * @param uid unique identifier of the datum | 656 | * @param uid unique identifier of the datum |
595 | * @param delta by how much should the priority | 657 | * @param priority by how much should the priority |
596 | * change? If priority + delta < 0 the | 658 | * change? |
597 | * priority should be set to 0 (never go | 659 | * @param replication by how much should the replication |
598 | * negative). | 660 | * change? |
599 | * @param expire new expiration time should be the | 661 | * @param expire new expiration time should be the |
600 | * MAX of any existing expiration time and | 662 | * MAX of any existing expiration time and |
601 | * this value | 663 | * this value |
602 | * @param cont continuation called with success or failure status | 664 | * @param cont continuation called with success or failure status |
603 | * @param cons_cls continuation closure | 665 | * @param cons_cls closure for @a cont |
604 | */ | 666 | */ |
605 | static void | 667 | static void |
606 | sqlite_plugin_update (void *cls, | 668 | sqlite_plugin_update (void *cls, |
607 | uint64_t uid, | 669 | uint64_t uid, |
608 | int delta, | 670 | uint32_t priority, |
671 | uint32_t replication, | ||
609 | struct GNUNET_TIME_Absolute expire, | 672 | struct GNUNET_TIME_Absolute expire, |
610 | PluginUpdateCont cont, | 673 | PluginUpdateCont cont, |
611 | void *cont_cls) | 674 | void *cont_cls) |
612 | { | 675 | { |
613 | struct Plugin *plugin = cls; | 676 | struct Plugin *plugin = cls; |
677 | struct GNUNET_SQ_QueryParam params[] = { | ||
678 | GNUNET_SQ_query_param_uint32 (&priority), | ||
679 | GNUNET_SQ_query_param_uint32 (&replication), | ||
680 | GNUNET_SQ_query_param_absolute_time (&expire), | ||
681 | GNUNET_SQ_query_param_uint64 (&uid), | ||
682 | GNUNET_SQ_query_param_end | ||
683 | }; | ||
614 | int n; | 684 | int n; |
615 | char *msg = NULL; | 685 | char *msg = NULL; |
616 | 686 | ||
617 | if ((SQLITE_OK != sqlite3_bind_int (plugin->updPrio, 1, delta)) || | 687 | if (GNUNET_OK != |
618 | (SQLITE_OK != sqlite3_bind_int64 (plugin->updPrio, 2, expire.abs_value_us)) | 688 | GNUNET_SQ_bind (plugin->updPrio, |
619 | || (SQLITE_OK != sqlite3_bind_int64 (plugin->updPrio, 3, uid))) | 689 | params)) |
620 | { | 690 | { |
621 | LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
622 | "sqlite3_bind_XXXX"); | ||
623 | if (SQLITE_OK != sqlite3_reset (plugin->updPrio)) | ||
624 | LOG_SQLITE (plugin, | ||
625 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
626 | "sqlite3_reset"); | ||
627 | cont (cont_cls, GNUNET_SYSERR, msg); | 691 | cont (cont_cls, GNUNET_SYSERR, msg); |
628 | GNUNET_free_non_null(msg); | 692 | GNUNET_free_non_null(msg); |
629 | return; | 693 | return; |
630 | } | 694 | } |
631 | n = sqlite3_step (plugin->updPrio); | 695 | n = sqlite3_step (plugin->updPrio); |
632 | if (SQLITE_OK != sqlite3_reset (plugin->updPrio)) | 696 | GNUNET_SQ_reset (plugin->dbh, |
633 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 697 | plugin->updPrio); |
634 | "sqlite3_reset"); | ||
635 | switch (n) | 698 | switch (n) |
636 | { | 699 | { |
637 | case SQLITE_DONE: | 700 | case SQLITE_DONE: |
@@ -672,73 +735,88 @@ execute_get (struct Plugin *plugin, | |||
672 | { | 735 | { |
673 | int n; | 736 | int n; |
674 | struct GNUNET_TIME_Absolute expiration; | 737 | struct GNUNET_TIME_Absolute expiration; |
675 | unsigned long long rowid; | 738 | uint32_t replication; |
676 | unsigned int size; | 739 | uint32_t type; |
740 | uint32_t priority; | ||
741 | uint32_t anonymity; | ||
742 | uint64_t rowid; | ||
743 | void *value; | ||
744 | size_t value_size; | ||
745 | struct GNUNET_HashCode key; | ||
677 | int ret; | 746 | int ret; |
747 | struct GNUNET_SQ_ResultSpec rs[] = { | ||
748 | GNUNET_SQ_result_spec_uint32 (&replication), | ||
749 | GNUNET_SQ_result_spec_uint32 (&type), | ||
750 | GNUNET_SQ_result_spec_uint32 (&priority), | ||
751 | GNUNET_SQ_result_spec_uint32 (&anonymity), | ||
752 | GNUNET_SQ_result_spec_absolute_time (&expiration), | ||
753 | GNUNET_SQ_result_spec_auto_from_type (&key), | ||
754 | GNUNET_SQ_result_spec_variable_size (&value, | ||
755 | &value_size), | ||
756 | GNUNET_SQ_result_spec_uint64 (&rowid), | ||
757 | GNUNET_SQ_result_spec_end | ||
758 | }; | ||
678 | 759 | ||
679 | n = sqlite3_step (stmt); | 760 | n = sqlite3_step (stmt); |
680 | switch (n) | 761 | switch (n) |
681 | { | 762 | { |
682 | case SQLITE_ROW: | 763 | case SQLITE_ROW: |
683 | size = sqlite3_column_bytes (stmt, 5); | 764 | if (GNUNET_OK != |
684 | rowid = sqlite3_column_int64 (stmt, 6); | 765 | GNUNET_SQ_extract_result (stmt, |
685 | if (sqlite3_column_bytes (stmt, 4) != sizeof (struct GNUNET_HashCode)) | 766 | rs)) |
686 | { | 767 | { |
687 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", | 768 | GNUNET_break (0); |
688 | _("Invalid data in database. Trying to fix (by deletion).\n")); | ||
689 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
690 | LOG_SQLITE (plugin, | ||
691 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
692 | "sqlite3_reset"); | ||
693 | if (GNUNET_OK == delete_by_rowid (plugin, rowid)) | ||
694 | plugin->env->duc (plugin->env->cls, | ||
695 | -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); | ||
696 | break; | 769 | break; |
697 | } | 770 | } |
698 | expiration.abs_value_us = sqlite3_column_int64 (stmt, 3); | 771 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
699 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | 772 | "sqlite", |
700 | "Found reply in database with expiration %s\n", | 773 | "Found reply in database with expiration %s\n", |
701 | GNUNET_STRINGS_absolute_time_to_string (expiration)); | 774 | GNUNET_STRINGS_absolute_time_to_string (expiration)); |
702 | ret = proc (proc_cls, sqlite3_column_blob (stmt, 4) /* key */ , | 775 | ret = proc (proc_cls, |
703 | size, sqlite3_column_blob (stmt, 5) /* data */ , | 776 | &key, |
704 | sqlite3_column_int (stmt, 0) /* type */ , | 777 | value_size, |
705 | sqlite3_column_int (stmt, 1) /* priority */ , | 778 | value, |
706 | sqlite3_column_int (stmt, 2) /* anonymity */ , | 779 | type, |
707 | expiration, rowid); | 780 | priority, |
708 | if (SQLITE_OK != sqlite3_reset (stmt)) | 781 | anonymity, |
709 | LOG_SQLITE (plugin, | 782 | replication, |
710 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 783 | expiration, |
711 | "sqlite3_reset"); | 784 | rowid); |
712 | if ((GNUNET_NO == ret) && (GNUNET_OK == delete_by_rowid (plugin, rowid))) | 785 | GNUNET_SQ_cleanup_result (rs); |
786 | GNUNET_SQ_reset (plugin->dbh, | ||
787 | stmt); | ||
788 | if ( (GNUNET_NO == ret) && | ||
789 | (GNUNET_OK == delete_by_rowid (plugin, | ||
790 | rowid)) && | ||
791 | (NULL != plugin->env->duc) ) | ||
713 | plugin->env->duc (plugin->env->cls, | 792 | plugin->env->duc (plugin->env->cls, |
714 | -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); | 793 | -(value_size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); |
715 | return; | 794 | return; |
716 | case SQLITE_DONE: | 795 | case SQLITE_DONE: |
717 | /* database must be empty */ | 796 | /* database must be empty */ |
718 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
719 | LOG_SQLITE (plugin, | ||
720 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
721 | "sqlite3_reset"); | ||
722 | break; | 797 | break; |
723 | case SQLITE_BUSY: | 798 | case SQLITE_BUSY: |
724 | case SQLITE_ERROR: | 799 | case SQLITE_ERROR: |
725 | case SQLITE_MISUSE: | 800 | case SQLITE_MISUSE: |
726 | default: | 801 | default: |
727 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 802 | LOG_SQLITE (plugin, |
803 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
728 | "sqlite3_step"); | 804 | "sqlite3_step"); |
729 | if (SQLITE_OK != sqlite3_reset (stmt)) | 805 | if (SQLITE_OK != |
806 | sqlite3_reset (stmt)) | ||
730 | LOG_SQLITE (plugin, | 807 | LOG_SQLITE (plugin, |
731 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 808 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
732 | "sqlite3_reset"); | 809 | "sqlite3_reset"); |
733 | GNUNET_break (0); | 810 | GNUNET_break (0); |
811 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
734 | database_shutdown (plugin); | 812 | database_shutdown (plugin); |
735 | database_setup (plugin->env->cfg, plugin); | 813 | database_setup (plugin->env->cfg, |
736 | break; | 814 | plugin); |
815 | return; | ||
737 | } | 816 | } |
738 | if (SQLITE_OK != sqlite3_reset (stmt)) | 817 | GNUNET_SQ_reset (plugin->dbh, |
739 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 818 | stmt); |
740 | "sqlite3_reset"); | 819 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
741 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
742 | } | 820 | } |
743 | 821 | ||
744 | 822 | ||
@@ -747,37 +825,36 @@ execute_get (struct Plugin *plugin, | |||
747 | * the given processor for the item. | 825 | * the given processor for the item. |
748 | * | 826 | * |
749 | * @param cls our plugin context | 827 | * @param cls our plugin context |
750 | * @param offset offset of the result (modulo num-results); | 828 | * @param next_uid return the result with lowest uid >= next_uid |
751 | * specific ordering does not matter for the offset | ||
752 | * @param type entries of which type should be considered? | 829 | * @param type entries of which type should be considered? |
753 | * Use 0 for any type. | 830 | * Must not be zero (ANY). |
754 | * @param proc function to call on each matching value; | 831 | * @param proc function to call on the matching value; |
755 | * will be called once with a NULL value at the end | 832 | * will be called with NULL if no value matches |
756 | * @param proc_cls closure for @a proc | 833 | * @param proc_cls closure for @a proc |
757 | */ | 834 | */ |
758 | static void | 835 | static void |
759 | sqlite_plugin_get_zero_anonymity (void *cls, uint64_t offset, | 836 | sqlite_plugin_get_zero_anonymity (void *cls, |
837 | uint64_t next_uid, | ||
760 | enum GNUNET_BLOCK_Type type, | 838 | enum GNUNET_BLOCK_Type type, |
761 | PluginDatumProcessor proc, void *proc_cls) | 839 | PluginDatumProcessor proc, |
840 | void *proc_cls) | ||
762 | { | 841 | { |
763 | struct Plugin *plugin = cls; | 842 | struct Plugin *plugin = cls; |
764 | sqlite3_stmt *stmt; | 843 | struct GNUNET_SQ_QueryParam params[] = { |
844 | GNUNET_SQ_query_param_uint64 (&next_uid), | ||
845 | GNUNET_SQ_query_param_uint32 (&type), | ||
846 | GNUNET_SQ_query_param_end | ||
847 | }; | ||
765 | 848 | ||
766 | GNUNET_assert (type != GNUNET_BLOCK_TYPE_ANY); | 849 | GNUNET_assert (type != GNUNET_BLOCK_TYPE_ANY); |
767 | stmt = plugin->selZeroAnon; | 850 | if (GNUNET_OK != |
768 | if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) || | 851 | GNUNET_SQ_bind (plugin->selZeroAnon, |
769 | (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, offset))) | 852 | params)) |
770 | { | 853 | { |
771 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 854 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
772 | "sqlite3_bind_XXXX"); | ||
773 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
774 | LOG_SQLITE (plugin, | ||
775 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
776 | "sqlite3_reset"); | ||
777 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
778 | return; | 855 | return; |
779 | } | 856 | } |
780 | execute_get (plugin, stmt, proc, proc_cls); | 857 | execute_get (plugin, plugin->selZeroAnon, proc, proc_cls); |
781 | } | 858 | } |
782 | 859 | ||
783 | 860 | ||
@@ -785,8 +862,9 @@ sqlite_plugin_get_zero_anonymity (void *cls, uint64_t offset, | |||
785 | * Get results for a particular key in the datastore. | 862 | * Get results for a particular key in the datastore. |
786 | * | 863 | * |
787 | * @param cls closure | 864 | * @param cls closure |
788 | * @param offset offset (mod count). | 865 | * @param next_uid return the result with lowest uid >= next_uid |
789 | * @param key key to match, never NULL | 866 | * @param random if true, return a random result instead of using next_uid |
867 | * @param key maybe NULL (to match all entries) | ||
790 | * @param vhash hash of the value, maybe NULL (to | 868 | * @param vhash hash of the value, maybe NULL (to |
791 | * match all values that have the right key). | 869 | * match all values that have the right key). |
792 | * Note that for DBlocks there is no difference | 870 | * Note that for DBlocks there is no difference |
@@ -800,7 +878,8 @@ sqlite_plugin_get_zero_anonymity (void *cls, uint64_t offset, | |||
800 | */ | 878 | */ |
801 | static void | 879 | static void |
802 | sqlite_plugin_get_key (void *cls, | 880 | sqlite_plugin_get_key (void *cls, |
803 | uint64_t offset, | 881 | uint64_t next_uid, |
882 | bool random, | ||
804 | const struct GNUNET_HashCode *key, | 883 | const struct GNUNET_HashCode *key, |
805 | const struct GNUNET_HashCode *vhash, | 884 | const struct GNUNET_HashCode *vhash, |
806 | enum GNUNET_BLOCK_Type type, | 885 | enum GNUNET_BLOCK_Type type, |
@@ -808,97 +887,45 @@ sqlite_plugin_get_key (void *cls, | |||
808 | void *proc_cls) | 887 | void *proc_cls) |
809 | { | 888 | { |
810 | struct Plugin *plugin = cls; | 889 | struct Plugin *plugin = cls; |
811 | int ret; | 890 | uint64_t rvalue; |
812 | int total; | 891 | uint16_t use_rvalue = random; |
813 | int limit_off; | 892 | uint32_t type32 = (uint32_t) type; |
814 | unsigned int sqoff; | 893 | uint16_t use_type = GNUNET_BLOCK_TYPE_ANY != type; |
815 | sqlite3_stmt *stmt; | 894 | uint16_t use_key = NULL != key; |
816 | char scratch[256]; | 895 | uint16_t use_vhash = NULL != vhash; |
817 | 896 | struct GNUNET_SQ_QueryParam params[] = { | |
818 | GNUNET_assert (proc != NULL); | 897 | GNUNET_SQ_query_param_uint64 (&next_uid), |
819 | GNUNET_assert (key != NULL); | 898 | GNUNET_SQ_query_param_uint64 (&rvalue), |
820 | GNUNET_snprintf (scratch, sizeof (scratch), | 899 | GNUNET_SQ_query_param_uint16 (&use_rvalue), |
821 | "SELECT count(*) FROM gn090 WHERE hash=?%s%s", | 900 | GNUNET_SQ_query_param_auto_from_type (key), |
822 | vhash == NULL ? "" : " AND vhash=?", | 901 | GNUNET_SQ_query_param_uint16 (&use_key), |
823 | type == 0 ? "" : " AND type=?"); | 902 | GNUNET_SQ_query_param_auto_from_type (vhash), |
824 | if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) | 903 | GNUNET_SQ_query_param_uint16 (&use_vhash), |
825 | { | 904 | GNUNET_SQ_query_param_uint32 (&type32), |
826 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 905 | GNUNET_SQ_query_param_uint16 (&use_type), |
827 | "sqlite_prepare"); | 906 | GNUNET_SQ_query_param_end |
828 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 907 | }; |
829 | return; | 908 | |
830 | } | 909 | if (random) |
831 | sqoff = 1; | ||
832 | ret = | ||
833 | sqlite3_bind_blob (stmt, sqoff++, key, sizeof (struct GNUNET_HashCode), | ||
834 | SQLITE_TRANSIENT); | ||
835 | if ((vhash != NULL) && (ret == SQLITE_OK)) | ||
836 | ret = | ||
837 | sqlite3_bind_blob (stmt, sqoff++, vhash, sizeof (struct GNUNET_HashCode), | ||
838 | SQLITE_TRANSIENT); | ||
839 | if ((type != 0) && (ret == SQLITE_OK)) | ||
840 | ret = sqlite3_bind_int (stmt, sqoff++, type); | ||
841 | if (SQLITE_OK != ret) | ||
842 | { | ||
843 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_bind"); | ||
844 | sqlite3_finalize (stmt); | ||
845 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
846 | return; | ||
847 | } | ||
848 | ret = sqlite3_step (stmt); | ||
849 | if (ret != SQLITE_ROW) | ||
850 | { | ||
851 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
852 | "sqlite_step"); | ||
853 | sqlite3_finalize (stmt); | ||
854 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
855 | return; | ||
856 | } | ||
857 | total = sqlite3_column_int (stmt, 0); | ||
858 | sqlite3_finalize (stmt); | ||
859 | if (0 == total) | ||
860 | { | ||
861 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
862 | return; | ||
863 | } | ||
864 | limit_off = (int) (offset % total); | ||
865 | if (limit_off < 0) | ||
866 | limit_off += total; | ||
867 | GNUNET_snprintf (scratch, sizeof (scratch), | ||
868 | "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ " | ||
869 | "FROM gn090 WHERE hash=?%s%s " | ||
870 | "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?", | ||
871 | vhash == NULL ? "" : " AND vhash=?", | ||
872 | type == 0 ? "" : " AND type=?"); | ||
873 | if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) | ||
874 | { | 910 | { |
875 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 911 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, |
876 | "sqlite_prepare"); | 912 | UINT64_MAX); |
877 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 913 | next_uid = 0; |
878 | return; | ||
879 | } | 914 | } |
880 | sqoff = 1; | 915 | else |
881 | ret = sqlite3_bind_blob (stmt, sqoff++, key, | 916 | rvalue = 0; |
882 | sizeof (struct GNUNET_HashCode), | 917 | |
883 | SQLITE_TRANSIENT); | 918 | if (GNUNET_OK != |
884 | if ((vhash != NULL) && (ret == SQLITE_OK)) | 919 | GNUNET_SQ_bind (plugin->get, |
885 | ret = sqlite3_bind_blob (stmt, sqoff++, vhash, | 920 | params)) |
886 | sizeof (struct GNUNET_HashCode), | ||
887 | SQLITE_TRANSIENT); | ||
888 | if ((type != 0) && (ret == SQLITE_OK)) | ||
889 | ret = sqlite3_bind_int (stmt, sqoff++, type); | ||
890 | if (ret == SQLITE_OK) | ||
891 | ret = sqlite3_bind_int64 (stmt, sqoff++, limit_off); | ||
892 | if (ret != SQLITE_OK) | ||
893 | { | 921 | { |
894 | LOG_SQLITE (plugin, | 922 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
895 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
896 | "sqlite_bind"); | ||
897 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
898 | return; | 923 | return; |
899 | } | 924 | } |
900 | execute_get (plugin, stmt, proc, proc_cls); | 925 | execute_get (plugin, |
901 | sqlite3_finalize (stmt); | 926 | plugin->get, |
927 | proc, | ||
928 | proc_cls); | ||
902 | } | 929 | } |
903 | 930 | ||
904 | 931 | ||
@@ -942,6 +969,7 @@ struct ReplCtx | |||
942 | * @param type type of the content | 969 | * @param type type of the content |
943 | * @param priority priority of the content | 970 | * @param priority priority of the content |
944 | * @param anonymity anonymity-level for the content | 971 | * @param anonymity anonymity-level for the content |
972 | * @param replication replication-level for the content | ||
945 | * @param expiration expiration time for the content | 973 | * @param expiration expiration time for the content |
946 | * @param uid unique identifier for the datum; | 974 | * @param uid unique identifier for the datum; |
947 | * maybe 0 if no unique identifier is available | 975 | * maybe 0 if no unique identifier is available |
@@ -956,19 +984,25 @@ repl_proc (void *cls, | |||
956 | enum GNUNET_BLOCK_Type type, | 984 | enum GNUNET_BLOCK_Type type, |
957 | uint32_t priority, | 985 | uint32_t priority, |
958 | uint32_t anonymity, | 986 | uint32_t anonymity, |
987 | uint32_t replication, | ||
959 | struct GNUNET_TIME_Absolute expiration, | 988 | struct GNUNET_TIME_Absolute expiration, |
960 | uint64_t uid) | 989 | uint64_t uid) |
961 | { | 990 | { |
962 | struct ReplCtx *rc = cls; | 991 | struct ReplCtx *rc = cls; |
963 | int ret; | 992 | int ret; |
964 | 993 | ||
994 | if (GNUNET_SYSERR == rc->have_uid) | ||
995 | rc->have_uid = GNUNET_NO; | ||
965 | ret = rc->proc (rc->proc_cls, | 996 | ret = rc->proc (rc->proc_cls, |
966 | key, | 997 | key, |
967 | size, data, | 998 | size, |
999 | data, | ||
968 | type, | 1000 | type, |
969 | priority, | 1001 | priority, |
970 | anonymity, | 1002 | anonymity, |
971 | expiration, uid); | 1003 | replication, |
1004 | expiration, | ||
1005 | uid); | ||
972 | if (NULL != key) | 1006 | if (NULL != key) |
973 | { | 1007 | { |
974 | rc->uid = uid; | 1008 | rc->uid = uid; |
@@ -989,81 +1023,77 @@ repl_proc (void *cls, | |||
989 | * @param proc_cls closure for @a proc | 1023 | * @param proc_cls closure for @a proc |
990 | */ | 1024 | */ |
991 | static void | 1025 | static void |
992 | sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc, | 1026 | sqlite_plugin_get_replication (void *cls, |
1027 | PluginDatumProcessor proc, | ||
993 | void *proc_cls) | 1028 | void *proc_cls) |
994 | { | 1029 | { |
995 | struct Plugin *plugin = cls; | 1030 | struct Plugin *plugin = cls; |
996 | struct ReplCtx rc; | 1031 | struct ReplCtx rc; |
997 | uint64_t rvalue; | 1032 | uint64_t rvalue; |
998 | uint32_t repl; | 1033 | uint32_t repl; |
999 | sqlite3_stmt *stmt; | 1034 | struct GNUNET_SQ_QueryParam params_sel_repl[] = { |
1000 | 1035 | GNUNET_SQ_query_param_uint64 (&rvalue), | |
1001 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | 1036 | GNUNET_SQ_query_param_uint32 (&repl), |
1037 | GNUNET_SQ_query_param_end | ||
1038 | }; | ||
1039 | struct GNUNET_SQ_QueryParam params_upd_repl[] = { | ||
1040 | GNUNET_SQ_query_param_uint64 (&rc.uid), | ||
1041 | GNUNET_SQ_query_param_end | ||
1042 | }; | ||
1043 | |||
1044 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1045 | "datastore-sqlite", | ||
1002 | "Getting random block based on replication order.\n"); | 1046 | "Getting random block based on replication order.\n"); |
1003 | rc.have_uid = GNUNET_NO; | 1047 | if (SQLITE_ROW != |
1004 | rc.proc = proc; | 1048 | sqlite3_step (plugin->maxRepl)) |
1005 | rc.proc_cls = proc_cls; | ||
1006 | stmt = plugin->maxRepl; | ||
1007 | if (SQLITE_ROW != sqlite3_step (stmt)) | ||
1008 | { | 1049 | { |
1009 | if (SQLITE_OK != sqlite3_reset (stmt)) | 1050 | GNUNET_SQ_reset (plugin->dbh, |
1010 | LOG_SQLITE (plugin, | 1051 | plugin->maxRepl); |
1011 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
1012 | "sqlite3_reset"); | ||
1013 | /* DB empty */ | 1052 | /* DB empty */ |
1014 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 1053 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
1015 | return; | 1054 | return; |
1016 | } | 1055 | } |
1017 | repl = sqlite3_column_int (stmt, 0); | 1056 | repl = sqlite3_column_int (plugin->maxRepl, |
1018 | if (SQLITE_OK != sqlite3_reset (stmt)) | 1057 | 0); |
1019 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 1058 | GNUNET_SQ_reset (plugin->dbh, |
1020 | "sqlite3_reset"); | 1059 | plugin->maxRepl); |
1021 | stmt = plugin->selRepl; | 1060 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, |
1022 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); | 1061 | UINT64_MAX); |
1023 | if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, rvalue)) | 1062 | if (GNUNET_OK != |
1024 | { | 1063 | GNUNET_SQ_bind (plugin->selRepl, |
1025 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 1064 | params_sel_repl)) |
1026 | "sqlite3_bind_XXXX"); | ||
1027 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
1028 | LOG_SQLITE (plugin, | ||
1029 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
1030 | "sqlite3_reset"); | ||
1031 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
1032 | return; | ||
1033 | } | ||
1034 | if (SQLITE_OK != sqlite3_bind_int (stmt, 2, repl)) | ||
1035 | { | 1065 | { |
1036 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 1066 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
1037 | "sqlite3_bind_XXXX"); | ||
1038 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
1039 | LOG_SQLITE (plugin, | ||
1040 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
1041 | "sqlite3_reset"); | ||
1042 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
1043 | return; | 1067 | return; |
1044 | } | 1068 | } |
1045 | execute_get (plugin, stmt, &repl_proc, &rc); | 1069 | rc.have_uid = GNUNET_SYSERR; |
1070 | rc.proc = proc; | ||
1071 | rc.proc_cls = proc_cls; | ||
1072 | execute_get (plugin, | ||
1073 | plugin->selRepl, | ||
1074 | &repl_proc, | ||
1075 | &rc); | ||
1046 | if (GNUNET_YES == rc.have_uid) | 1076 | if (GNUNET_YES == rc.have_uid) |
1047 | { | 1077 | { |
1048 | if (SQLITE_OK != sqlite3_bind_int64 (plugin->updRepl, 1, rc.uid)) | 1078 | if (GNUNET_OK != |
1079 | GNUNET_SQ_bind (plugin->updRepl, | ||
1080 | params_upd_repl)) | ||
1049 | { | 1081 | { |
1050 | LOG_SQLITE (plugin, | 1082 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
1051 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
1052 | "sqlite3_bind_XXXX"); | ||
1053 | if (SQLITE_OK != sqlite3_reset (plugin->updRepl)) | ||
1054 | LOG_SQLITE (plugin, | ||
1055 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
1056 | "sqlite3_reset"); | ||
1057 | return; | 1083 | return; |
1058 | } | 1084 | } |
1059 | if (SQLITE_DONE != sqlite3_step (plugin->updRepl)) | 1085 | if (SQLITE_DONE != |
1086 | sqlite3_step (plugin->updRepl)) | ||
1060 | LOG_SQLITE (plugin, | 1087 | LOG_SQLITE (plugin, |
1061 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 1088 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
1062 | "sqlite3_step"); | 1089 | "sqlite3_step"); |
1063 | if (SQLITE_OK != sqlite3_reset (plugin->updRepl)) | 1090 | GNUNET_SQ_reset (plugin->dbh, |
1064 | LOG_SQLITE (plugin, | 1091 | plugin->updRepl); |
1065 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 1092 | } |
1066 | "sqlite3_reset"); | 1093 | if (GNUNET_SYSERR == rc.have_uid) |
1094 | { | ||
1095 | /* proc was not called at all so far, do it now. */ | ||
1096 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
1067 | } | 1097 | } |
1068 | } | 1098 | } |
1069 | 1099 | ||
@@ -1083,20 +1113,21 @@ sqlite_plugin_get_expiration (void *cls, PluginDatumProcessor proc, | |||
1083 | struct Plugin *plugin = cls; | 1113 | struct Plugin *plugin = cls; |
1084 | sqlite3_stmt *stmt; | 1114 | sqlite3_stmt *stmt; |
1085 | struct GNUNET_TIME_Absolute now; | 1115 | struct GNUNET_TIME_Absolute now; |
1116 | struct GNUNET_SQ_QueryParam params[] = { | ||
1117 | GNUNET_SQ_query_param_absolute_time (&now), | ||
1118 | GNUNET_SQ_query_param_end | ||
1119 | }; | ||
1086 | 1120 | ||
1087 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | 1121 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
1122 | "sqlite", | ||
1088 | "Getting random block based on expiration and priority order.\n"); | 1123 | "Getting random block based on expiration and priority order.\n"); |
1089 | now = GNUNET_TIME_absolute_get (); | 1124 | now = GNUNET_TIME_absolute_get (); |
1090 | stmt = plugin->selExpi; | 1125 | stmt = plugin->selExpi; |
1091 | if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, now.abs_value_us)) | 1126 | if (GNUNET_OK != |
1127 | GNUNET_SQ_bind (stmt, | ||
1128 | params)) | ||
1092 | { | 1129 | { |
1093 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 1130 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
1094 | "sqlite3_bind_XXXX"); | ||
1095 | if (SQLITE_OK != sqlite3_reset (stmt)) | ||
1096 | LOG_SQLITE (plugin, | ||
1097 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
1098 | "sqlite3_reset"); | ||
1099 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | ||
1100 | return; | 1131 | return; |
1101 | } | 1132 | } |
1102 | execute_get (plugin, stmt, proc, proc_cls); | 1133 | execute_get (plugin, stmt, proc, proc_cls); |
@@ -1116,30 +1147,47 @@ sqlite_plugin_get_keys (void *cls, | |||
1116 | void *proc_cls) | 1147 | void *proc_cls) |
1117 | { | 1148 | { |
1118 | struct Plugin *plugin = cls; | 1149 | struct Plugin *plugin = cls; |
1119 | const struct GNUNET_HashCode *key; | 1150 | struct GNUNET_HashCode key; |
1151 | struct GNUNET_SQ_ResultSpec results[] = { | ||
1152 | GNUNET_SQ_result_spec_auto_from_type (&key), | ||
1153 | GNUNET_SQ_result_spec_end | ||
1154 | }; | ||
1120 | sqlite3_stmt *stmt; | 1155 | sqlite3_stmt *stmt; |
1121 | int ret; | 1156 | int ret; |
1122 | 1157 | ||
1123 | GNUNET_assert (proc != NULL); | 1158 | GNUNET_assert (NULL != proc); |
1124 | if (sq_prepare (plugin->dbh, "SELECT hash FROM gn090", &stmt) != SQLITE_OK) | 1159 | if (SQLITE_OK != |
1160 | sq_prepare (plugin->dbh, | ||
1161 | "SELECT hash FROM gn090", | ||
1162 | &stmt)) | ||
1125 | { | 1163 | { |
1126 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 1164 | LOG_SQLITE (plugin, |
1165 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
1127 | "sqlite_prepare"); | 1166 | "sqlite_prepare"); |
1128 | proc (proc_cls, NULL, 0); | 1167 | proc (proc_cls, |
1168 | NULL, | ||
1169 | 0); | ||
1129 | return; | 1170 | return; |
1130 | } | 1171 | } |
1131 | while (SQLITE_ROW == (ret = sqlite3_step (stmt))) | 1172 | while (SQLITE_ROW == (ret = sqlite3_step (stmt))) |
1132 | { | 1173 | { |
1133 | key = sqlite3_column_blob (stmt, 0); | 1174 | if (GNUNET_OK == |
1134 | if (sizeof (struct GNUNET_HashCode) == sqlite3_column_bytes (stmt, 0)) | 1175 | GNUNET_SQ_extract_result (stmt, |
1135 | proc (proc_cls, key, 1); | 1176 | results)) |
1177 | proc (proc_cls, | ||
1178 | &key, | ||
1179 | 1); | ||
1136 | else | 1180 | else |
1137 | GNUNET_break (0); | 1181 | GNUNET_break (0); |
1138 | } | 1182 | } |
1139 | if (SQLITE_DONE != ret) | 1183 | if (SQLITE_DONE != ret) |
1140 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); | 1184 | LOG_SQLITE (plugin, |
1185 | GNUNET_ERROR_TYPE_ERROR, | ||
1186 | "sqlite_step"); | ||
1141 | sqlite3_finalize (stmt); | 1187 | sqlite3_finalize (stmt); |
1142 | proc (proc_cls, NULL, 0); | 1188 | proc (proc_cls, |
1189 | NULL, | ||
1190 | 0); | ||
1143 | } | 1191 | } |
1144 | 1192 | ||
1145 | 1193 | ||
@@ -1165,7 +1213,8 @@ sqlite_plugin_drop (void *cls) | |||
1165 | * @return the size of the database on disk (estimate) | 1213 | * @return the size of the database on disk (estimate) |
1166 | */ | 1214 | */ |
1167 | static void | 1215 | static void |
1168 | sqlite_plugin_estimate_size (void *cls, unsigned long long *estimate) | 1216 | sqlite_plugin_estimate_size (void *cls, |
1217 | unsigned long long *estimate) | ||
1169 | { | 1218 | { |
1170 | struct Plugin *plugin = cls; | 1219 | struct Plugin *plugin = cls; |
1171 | sqlite3_stmt *stmt; | 1220 | sqlite3_stmt *stmt; |
@@ -1180,30 +1229,45 @@ sqlite_plugin_estimate_size (void *cls, unsigned long long *estimate) | |||
1180 | return; | 1229 | return; |
1181 | if (SQLITE_VERSION_NUMBER < 3006000) | 1230 | if (SQLITE_VERSION_NUMBER < 3006000) |
1182 | { | 1231 | { |
1183 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "datastore-sqlite", | 1232 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, |
1184 | _ | 1233 | "datastore-sqlite", |
1185 | ("sqlite version to old to determine size, assuming zero\n")); | 1234 | _("sqlite version to old to determine size, assuming zero\n")); |
1186 | *estimate = 0; | 1235 | *estimate = 0; |
1187 | return; | 1236 | return; |
1188 | } | 1237 | } |
1189 | CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "VACUUM", NULL, NULL, ENULL)); | ||
1190 | CHECK (SQLITE_OK == | 1238 | CHECK (SQLITE_OK == |
1191 | sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL, | 1239 | sqlite3_exec (plugin->dbh, |
1240 | "VACUUM", | ||
1241 | NULL, | ||
1242 | NULL, | ||
1243 | ENULL)); | ||
1244 | CHECK (SQLITE_OK == | ||
1245 | sqlite3_exec (plugin->dbh, | ||
1246 | "PRAGMA auto_vacuum=INCREMENTAL", | ||
1247 | NULL, | ||
1192 | NULL, ENULL)); | 1248 | NULL, ENULL)); |
1193 | CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_count", &stmt)); | 1249 | CHECK (SQLITE_OK == |
1250 | sq_prepare (plugin->dbh, | ||
1251 | "PRAGMA page_count", | ||
1252 | &stmt)); | ||
1194 | if (SQLITE_ROW == sqlite3_step (stmt)) | 1253 | if (SQLITE_ROW == sqlite3_step (stmt)) |
1195 | pages = sqlite3_column_int64 (stmt, 0); | 1254 | pages = sqlite3_column_int64 (stmt, |
1255 | 0); | ||
1196 | else | 1256 | else |
1197 | pages = 0; | 1257 | pages = 0; |
1198 | sqlite3_finalize (stmt); | 1258 | sqlite3_finalize (stmt); |
1199 | CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_size", &stmt)); | 1259 | CHECK (SQLITE_OK == |
1200 | CHECK (SQLITE_ROW == sqlite3_step (stmt)); | 1260 | sq_prepare (plugin->dbh, |
1261 | "PRAGMA page_size", | ||
1262 | &stmt)); | ||
1263 | CHECK (SQLITE_ROW == | ||
1264 | sqlite3_step (stmt)); | ||
1201 | page_size = sqlite3_column_int64 (stmt, 0); | 1265 | page_size = sqlite3_column_int64 (stmt, 0); |
1202 | sqlite3_finalize (stmt); | 1266 | sqlite3_finalize (stmt); |
1203 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1267 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
1204 | _ | 1268 | _("Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"), |
1205 | ("Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"), | 1269 | (unsigned long long) pages, |
1206 | (unsigned long long) pages, (unsigned long long) page_size); | 1270 | (unsigned long long) page_size); |
1207 | *estimate = pages * page_size; | 1271 | *estimate = pages * page_size; |
1208 | } | 1272 | } |
1209 | 1273 | ||
@@ -1221,9 +1285,11 @@ libgnunet_plugin_datastore_sqlite_init (void *cls) | |||
1221 | struct GNUNET_DATASTORE_PluginEnvironment *env = cls; | 1285 | struct GNUNET_DATASTORE_PluginEnvironment *env = cls; |
1222 | struct GNUNET_DATASTORE_PluginFunctions *api; | 1286 | struct GNUNET_DATASTORE_PluginFunctions *api; |
1223 | 1287 | ||
1224 | if (plugin.env != NULL) | 1288 | if (NULL != plugin.env) |
1225 | return NULL; /* can only initialize once! */ | 1289 | return NULL; /* can only initialize once! */ |
1226 | memset (&plugin, 0, sizeof (struct Plugin)); | 1290 | memset (&plugin, |
1291 | 0, | ||
1292 | sizeof (struct Plugin)); | ||
1227 | plugin.env = env; | 1293 | plugin.env = env; |
1228 | if (GNUNET_OK != database_setup (env->cfg, &plugin)) | 1294 | if (GNUNET_OK != database_setup (env->cfg, &plugin)) |
1229 | { | 1295 | { |
@@ -1241,7 +1307,8 @@ libgnunet_plugin_datastore_sqlite_init (void *cls) | |||
1241 | api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity; | 1307 | api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity; |
1242 | api->get_keys = &sqlite_plugin_get_keys; | 1308 | api->get_keys = &sqlite_plugin_get_keys; |
1243 | api->drop = &sqlite_plugin_drop; | 1309 | api->drop = &sqlite_plugin_drop; |
1244 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "sqlite", | 1310 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, |
1311 | "sqlite", | ||
1245 | _("Sqlite database running\n")); | 1312 | _("Sqlite database running\n")); |
1246 | return api; | 1313 | return api; |
1247 | } | 1314 | } |
@@ -1260,24 +1327,23 @@ libgnunet_plugin_datastore_sqlite_done (void *cls) | |||
1260 | struct GNUNET_DATASTORE_PluginFunctions *api = cls; | 1327 | struct GNUNET_DATASTORE_PluginFunctions *api = cls; |
1261 | struct Plugin *plugin = api->cls; | 1328 | struct Plugin *plugin = api->cls; |
1262 | 1329 | ||
1263 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | 1330 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
1331 | "sqlite", | ||
1264 | "sqlite plugin is done\n"); | 1332 | "sqlite plugin is done\n"); |
1265 | fn = NULL; | 1333 | fn = NULL; |
1266 | if (plugin->drop_on_shutdown) | 1334 | if (plugin->drop_on_shutdown) |
1267 | fn = GNUNET_strdup (plugin->fn); | 1335 | fn = GNUNET_strdup (plugin->fn); |
1268 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | ||
1269 | "Shutting down database\n"); | ||
1270 | database_shutdown (plugin); | 1336 | database_shutdown (plugin); |
1271 | plugin->env = NULL; | 1337 | plugin->env = NULL; |
1272 | GNUNET_free (api); | 1338 | GNUNET_free (api); |
1273 | if (fn != NULL) | 1339 | if (NULL != fn) |
1274 | { | 1340 | { |
1275 | if (0 != UNLINK (fn)) | 1341 | if (0 != UNLINK (fn)) |
1276 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); | 1342 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, |
1343 | "unlink", | ||
1344 | fn); | ||
1277 | GNUNET_free (fn); | 1345 | GNUNET_free (fn); |
1278 | } | 1346 | } |
1279 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", | ||
1280 | "sqlite plugin is finished\n"); | ||
1281 | return NULL; | 1347 | return NULL; |
1282 | } | 1348 | } |
1283 | 1349 | ||