aboutsummaryrefslogtreecommitdiff
path: root/src/datacache
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-03-12 02:51:36 +0100
committerChristian Grothoff <christian@grothoff.org>2017-03-12 02:51:36 +0100
commita707b513688690a3dad9dc39535900da73a79f28 (patch)
tree0439c267fc54960441ae09f0ca5c62e0c41f2cb7 /src/datacache
parent538d7fde8cb1c0d079f01f2290aa3e3e2744beff (diff)
downloadgnunet-a707b513688690a3dad9dc39535900da73a79f28.tar.gz
gnunet-a707b513688690a3dad9dc39535900da73a79f28.zip
converting datacache to sqlite, fixing misc. issues in libgnunetsq
Diffstat (limited to 'src/datacache')
-rw-r--r--src/datacache/Makefile.am1
-rw-r--r--src/datacache/plugin_datacache_sqlite.c549
2 files changed, 309 insertions, 241 deletions
diff --git a/src/datacache/Makefile.am b/src/datacache/Makefile.am
index 431b3179e..670a64926 100644
--- a/src/datacache/Makefile.am
+++ b/src/datacache/Makefile.am
@@ -53,6 +53,7 @@ libgnunet_plugin_datacache_sqlite_la_SOURCES = \
53 plugin_datacache_sqlite.c 53 plugin_datacache_sqlite.c
54libgnunet_plugin_datacache_sqlite_la_LIBADD = \ 54libgnunet_plugin_datacache_sqlite_la_LIBADD = \
55 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 55 $(top_builddir)/src/statistics/libgnunetstatistics.la \
56 $(top_builddir)/src/sq/libgnunetsq.la \
56 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ 57 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
57 $(LTLIBINTL) 58 $(LTLIBINTL)
58libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \ 59libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c
index 5567077d3..5cc48b26c 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -26,6 +26,7 @@
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_datacache_plugin.h" 28#include "gnunet_datacache_plugin.h"
29#include "gnunet_sq_lib.h"
29#include <sqlite3.h> 30#include <sqlite3.h>
30 31
31#define LOG(kind,...) GNUNET_log_from (kind, "datacache-sqlite", __VA_ARGS__) 32#define LOG(kind,...) GNUNET_log_from (kind, "datacache-sqlite", __VA_ARGS__)
@@ -60,6 +61,41 @@ struct Plugin
60 char *fn; 61 char *fn;
61 62
62 /** 63 /**
64 * Prepared statement for #sqlite_plugin_put.
65 */
66 sqlite3_stmt *insert_stmt;
67
68 /**
69 * Prepared statement for #sqlite_plugin_get.
70 */
71 sqlite3_stmt *get_count_stmt;
72
73 /**
74 * Prepared statement for #sqlite_plugin_get.
75 */
76 sqlite3_stmt *get_stmt;
77
78 /**
79 * Prepared statement for #sqlite_plugin_del.
80 */
81 sqlite3_stmt *del_select_stmt;
82
83 /**
84 * Prepared statement for #sqlite_plugin_del.
85 */
86 sqlite3_stmt *del_stmt;
87
88 /**
89 * Prepared statement for #sqlite_plugin_get_random.
90 */
91 sqlite3_stmt *get_random_stmt;
92
93 /**
94 * Prepared statement for #sqlite_plugin_get_closest.
95 */
96 sqlite3_stmt *get_closest_stmt;
97
98 /**
63 * Number of key-value pairs in the database. 99 * Number of key-value pairs in the database.
64 */ 100 */
65 unsigned int num_items; 101 unsigned int num_items;
@@ -132,60 +168,47 @@ sqlite_plugin_put (void *cls,
132 const struct GNUNET_PeerIdentity *path_info) 168 const struct GNUNET_PeerIdentity *path_info)
133{ 169{
134 struct Plugin *plugin = cls; 170 struct Plugin *plugin = cls;
135 sqlite3_stmt *stmt; 171 uint32_t type32 = type;
136 int64_t dval; 172 struct GNUNET_SQ_QueryParam params[] = {
173 GNUNET_SQ_query_param_uint32 (&type32),
174 GNUNET_SQ_query_param_absolute_time (&discard_time),
175 GNUNET_SQ_query_param_auto_from_type (key),
176 GNUNET_SQ_query_param_fixed_size (data, size),
177 GNUNET_SQ_query_param_fixed_size (path_info,
178 path_info_len * sizeof (struct GNUNET_PeerIdentity)),
179 GNUNET_SQ_query_param_end
180 };
137 181
138 LOG (GNUNET_ERROR_TYPE_DEBUG, 182 LOG (GNUNET_ERROR_TYPE_DEBUG,
139 "Processing PUT of %u bytes with key `%4s' and expiration %s\n", 183 "Processing PUT of %u bytes with key `%s' and expiration %s\n",
140 (unsigned int) size, 184 (unsigned int) size,
141 GNUNET_h2s (key), 185 GNUNET_h2s (key),
142 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (discard_time), GNUNET_YES)); 186 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (discard_time),
143 dval = (int64_t) discard_time.abs_value_us; 187 GNUNET_YES));
144 if (dval < 0) 188 if (GNUNET_OK !=
145 dval = INT64_MAX; 189 GNUNET_SQ_bind (plugin->insert_stmt,
146 if (sq_prepare 190 params))
147 (plugin->dbh,
148 "INSERT INTO ds090 (type, expire, key, value, path) VALUES (?, ?, ?, ?, ?)",
149 &stmt) != SQLITE_OK)
150 {
151 LOG_SQLITE (plugin->dbh,
152 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
153 "sq_prepare");
154 return -1;
155 }
156 if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) ||
157 (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, dval)) ||
158 (SQLITE_OK !=
159 sqlite3_bind_blob (stmt, 3,
160 key, sizeof (struct GNUNET_HashCode),
161 SQLITE_TRANSIENT)) ||
162 (SQLITE_OK != sqlite3_bind_blob (stmt, 4,
163 data, size,
164 SQLITE_TRANSIENT)) ||
165 (SQLITE_OK != sqlite3_bind_blob (stmt, 5,
166 path_info,
167 path_info_len * sizeof (struct GNUNET_PeerIdentity),
168 SQLITE_TRANSIENT)))
169 { 191 {
170 LOG_SQLITE (plugin->dbh, 192 LOG_SQLITE (plugin->dbh,
171 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 193 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
172 "sqlite3_bind_xxx"); 194 "sqlite3_bind_xxx");
173 sqlite3_finalize (stmt); 195 GNUNET_SQ_reset (plugin->dbh,
196 plugin->insert_stmt);
174 return -1; 197 return -1;
175 } 198 }
176 if (SQLITE_DONE != sqlite3_step (stmt)) 199 if (SQLITE_DONE !=
200 sqlite3_step (plugin->insert_stmt))
177 { 201 {
178 LOG_SQLITE (plugin->dbh, 202 LOG_SQLITE (plugin->dbh,
179 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 203 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
180 "sqlite3_step"); 204 "sqlite3_step");
181 sqlite3_finalize (stmt); 205 GNUNET_SQ_reset (plugin->dbh,
206 plugin->insert_stmt);
182 return -1; 207 return -1;
183 } 208 }
184 plugin->num_items++; 209 plugin->num_items++;
185 if (SQLITE_OK != sqlite3_finalize (stmt)) 210 GNUNET_SQ_reset (plugin->dbh,
186 LOG_SQLITE (plugin->dbh, 211 plugin->insert_stmt);
187 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
188 "sqlite3_finalize");
189 return size + OVERHEAD; 212 return size + OVERHEAD;
190} 213}
191 214
@@ -209,120 +232,119 @@ sqlite_plugin_get (void *cls,
209 void *iter_cls) 232 void *iter_cls)
210{ 233{
211 struct Plugin *plugin = cls; 234 struct Plugin *plugin = cls;
212 sqlite3_stmt *stmt; 235 uint32_t type32 = type;
213 struct GNUNET_TIME_Absolute now; 236 struct GNUNET_TIME_Absolute now;
214 struct GNUNET_TIME_Absolute exp; 237 struct GNUNET_TIME_Absolute exp;
215 unsigned int size; 238 size_t size;
216 const char *dat; 239 void *dat;
217 unsigned int cnt; 240 unsigned int cnt;
218 unsigned int off; 241 uint32_t off;
219 unsigned int total; 242 unsigned int total;
220 unsigned int psize; 243 size_t psize;
221 char scratch[256]; 244 struct GNUNET_PeerIdentity *path;
222 int64_t ntime; 245 struct GNUNET_SQ_QueryParam params_count[] = {
223 const struct GNUNET_PeerIdentity *path; 246 GNUNET_SQ_query_param_auto_from_type (key),
247 GNUNET_SQ_query_param_uint32 (&type32),
248 GNUNET_SQ_query_param_absolute_time (&now),
249 GNUNET_SQ_query_param_end
250 };
251 struct GNUNET_SQ_QueryParam params_select[] = {
252 GNUNET_SQ_query_param_auto_from_type (key),
253 GNUNET_SQ_query_param_uint32 (&type32),
254 GNUNET_SQ_query_param_absolute_time (&now),
255 GNUNET_SQ_query_param_uint32 (&off),
256 GNUNET_SQ_query_param_end
257 };
258 struct GNUNET_SQ_ResultSpec rs[] = {
259 GNUNET_SQ_result_spec_variable_size (&dat,
260 &size),
261 GNUNET_SQ_result_spec_absolute_time (&exp),
262 GNUNET_SQ_result_spec_variable_size ((void **) &path,
263 &psize),
264 GNUNET_SQ_result_spec_end
265 };
224 266
225 now = GNUNET_TIME_absolute_get (); 267 now = GNUNET_TIME_absolute_get ();
226 LOG (GNUNET_ERROR_TYPE_DEBUG, 268 LOG (GNUNET_ERROR_TYPE_DEBUG,
227 "Processing GET for key `%4s'\n", 269 "Processing GET for key `%s'\n",
228 GNUNET_h2s (key)); 270 GNUNET_h2s (key));
229 if (sq_prepare 271
230 (plugin->dbh, 272 if (GNUNET_OK !=
231 "SELECT count(*) FROM ds090 WHERE key=? AND type=? AND expire >= ?", 273 GNUNET_SQ_bind (plugin->get_count_stmt,
232 &stmt) != SQLITE_OK) 274 params_count))
233 {
234 LOG_SQLITE (plugin->dbh,
235 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
236 "sq_prepare");
237 return 0;
238 }
239 ntime = (int64_t) now.abs_value_us;
240 GNUNET_assert (ntime >= 0);
241 if ((SQLITE_OK !=
242 sqlite3_bind_blob (stmt, 1, key, sizeof (struct GNUNET_HashCode),
243 SQLITE_TRANSIENT)) ||
244 (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) ||
245 (SQLITE_OK != sqlite3_bind_int64 (stmt, 3, now.abs_value_us)))
246 { 275 {
247 LOG_SQLITE (plugin->dbh, 276 LOG_SQLITE (plugin->dbh,
248 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 277 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
249 "sqlite3_bind_xxx"); 278 "sqlite3_bind_xxx");
250 sqlite3_finalize (stmt); 279 GNUNET_SQ_reset (plugin->dbh,
280 plugin->get_count_stmt);
251 return 0; 281 return 0;
252 } 282 }
253 283 if (SQLITE_ROW !=
254 if (SQLITE_ROW != sqlite3_step (stmt)) 284 sqlite3_step (plugin->get_count_stmt))
255 { 285 {
256 LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 286 LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
257 "sqlite_step"); 287 "sqlite_step");
258 sqlite3_finalize (stmt); 288 GNUNET_SQ_reset (plugin->dbh,
289 plugin->get_count_stmt);
259 LOG (GNUNET_ERROR_TYPE_DEBUG, 290 LOG (GNUNET_ERROR_TYPE_DEBUG,
260 "No content found when processing GET for key `%4s'\n", 291 "No content found when processing GET for key `%s'\n",
261 GNUNET_h2s (key)); 292 GNUNET_h2s (key));
262 return 0; 293 return 0;
263 } 294 }
264 total = sqlite3_column_int (stmt, 0); 295 total = sqlite3_column_int (plugin->get_count_stmt,
265 sqlite3_finalize (stmt); 296 0);
266 if ((0 == total) || (NULL == iter)) 297 GNUNET_SQ_reset (plugin->dbh,
298 plugin->get_count_stmt);
299 if ( (0 == total) ||
300 (NULL == iter) )
267 { 301 {
268 if (0 == total) 302 if (0 == total)
269 LOG (GNUNET_ERROR_TYPE_DEBUG, 303 LOG (GNUNET_ERROR_TYPE_DEBUG,
270 "No content found when processing GET for key `%4s'\n", 304 "No content found when processing GET for key `%s'\n",
271 GNUNET_h2s (key)); 305 GNUNET_h2s (key));
272 return total; 306 return total;
273 } 307 }
274 308
275 cnt = 0; 309 cnt = 0;
276 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); 310 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
311 total);
277 while (cnt < total) 312 while (cnt < total)
278 { 313 {
279 off = (off + 1) % total; 314 off = (off + 1) % total;
280 GNUNET_snprintf (scratch, sizeof (scratch), 315 if (GNUNET_OK !=
281 "SELECT value,expire,path FROM ds090 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u", 316 GNUNET_SQ_bind (plugin->get_stmt,
282 off); 317 params_select))
283 if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK)
284 {
285 LOG_SQLITE (plugin->dbh,
286 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
287 "sq_prepare");
288 return cnt;
289 }
290 if ((SQLITE_OK !=
291 sqlite3_bind_blob (stmt, 1,
292 key,
293 sizeof (struct GNUNET_HashCode),
294 SQLITE_TRANSIENT)) ||
295 (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) ||
296 (SQLITE_OK != sqlite3_bind_int64 (stmt, 3, now.abs_value_us)))
297 { 318 {
298 LOG_SQLITE (plugin->dbh, 319 LOG_SQLITE (plugin->dbh,
299 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 320 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
300 "sqlite3_bind_xxx"); 321 "sqlite3_bind_xxx");
301 sqlite3_finalize (stmt); 322 GNUNET_SQ_reset (plugin->dbh,
323 plugin->get_stmt);
302 return cnt; 324 return cnt;
303 } 325 }
304 if (sqlite3_step (stmt) != SQLITE_ROW) 326 if (SQLITE_ROW !=
327 sqlite3_step (plugin->get_stmt))
305 break; 328 break;
306 size = sqlite3_column_bytes (stmt, 0); 329 if (GNUNET_OK !=
307 dat = sqlite3_column_blob (stmt, 0); 330 GNUNET_SQ_extract_result (plugin->get_stmt,
308 exp.abs_value_us = sqlite3_column_int64 (stmt, 1); 331 rs))
309 psize = sqlite3_column_bytes (stmt, 2); 332 {
333 GNUNET_break (0);
334 GNUNET_SQ_reset (plugin->dbh,
335 plugin->get_stmt);
336 break;
337 }
310 if (0 != psize % sizeof (struct GNUNET_PeerIdentity)) 338 if (0 != psize % sizeof (struct GNUNET_PeerIdentity))
311 { 339 {
312 GNUNET_break (0); 340 GNUNET_break (0);
313 psize = 0; 341 psize = 0;
342 path = NULL;
314 } 343 }
315 psize /= sizeof (struct GNUNET_PeerIdentity); 344 psize /= sizeof (struct GNUNET_PeerIdentity);
316 if (0 != psize)
317 path = sqlite3_column_blob (stmt, 2);
318 else
319 path = NULL;
320 ntime = (int64_t) exp.abs_value_us;
321 if (ntime == INT64_MAX)
322 exp = GNUNET_TIME_UNIT_FOREVER_ABS;
323 cnt++; 345 cnt++;
324 LOG (GNUNET_ERROR_TYPE_DEBUG, 346 LOG (GNUNET_ERROR_TYPE_DEBUG,
325 "Found %u-byte result when processing GET for key `%4s'\n", 347 "Found %u-byte result when processing GET for key `%s'\n",
326 (unsigned int) size, 348 (unsigned int) size,
327 GNUNET_h2s (key)); 349 GNUNET_h2s (key));
328 if (GNUNET_OK != iter (iter_cls, 350 if (GNUNET_OK != iter (iter_cls,
@@ -334,11 +356,17 @@ sqlite_plugin_get (void *cls,
334 psize, 356 psize,
335 path)) 357 path))
336 { 358 {
337 sqlite3_finalize (stmt); 359 GNUNET_SQ_cleanup_result (rs);
360 GNUNET_SQ_reset (plugin->dbh,
361 plugin->get_stmt);
338 break; 362 break;
339 } 363 }
340 sqlite3_finalize (stmt); 364 GNUNET_SQ_cleanup_result (rs);
365 GNUNET_SQ_reset (plugin->dbh,
366 plugin->get_stmt);
341 } 367 }
368 GNUNET_SQ_reset (plugin->dbh,
369 plugin->get_stmt);
342 return cnt; 370 return cnt;
343} 371}
344 372
@@ -354,79 +382,73 @@ static int
354sqlite_plugin_del (void *cls) 382sqlite_plugin_del (void *cls)
355{ 383{
356 struct Plugin *plugin = cls; 384 struct Plugin *plugin = cls;
357 unsigned long long rowid; 385 uint64_t rowid;
358 unsigned int dsize; 386 void *data;
359 sqlite3_stmt *stmt; 387 size_t dsize;
360 sqlite3_stmt *dstmt;
361 struct GNUNET_HashCode hc; 388 struct GNUNET_HashCode hc;
389 struct GNUNET_SQ_ResultSpec rs[] = {
390 GNUNET_SQ_result_spec_uint64 (&rowid),
391 GNUNET_SQ_result_spec_auto_from_type (&hc),
392 GNUNET_SQ_result_spec_variable_size ((void **) &data,
393 &dsize),
394 GNUNET_SQ_result_spec_end
395 };
396 struct GNUNET_SQ_QueryParam params[] = {
397 GNUNET_SQ_query_param_uint64 (&rowid),
398 GNUNET_SQ_query_param_end
399 };
362 400
363 LOG (GNUNET_ERROR_TYPE_DEBUG, 401 LOG (GNUNET_ERROR_TYPE_DEBUG,
364 "Processing DEL\n"); 402 "Processing DEL\n");
365 stmt = NULL; 403 if (SQLITE_ROW !=
366 dstmt = NULL; 404 sqlite3_step (plugin->del_select_stmt))
367 if (SQLITE_OK !=
368 sq_prepare (plugin->dbh,
369 "SELECT _ROWID_,key,value FROM ds090 ORDER BY expire ASC LIMIT 1",
370 &stmt))
371 {
372 LOG_SQLITE (plugin->dbh,
373 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
374 "sq_prepare");
375 if (stmt != NULL)
376 (void) sqlite3_finalize (stmt);
377 return GNUNET_SYSERR;
378 }
379 if (SQLITE_ROW != sqlite3_step (stmt))
380 { 405 {
381 LOG_SQLITE (plugin->dbh, 406 LOG_SQLITE (plugin->dbh,
382 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 407 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
383 "sqlite3_step"); 408 "sqlite3_step");
384 (void) sqlite3_finalize (stmt); 409 GNUNET_SQ_reset (plugin->dbh,
410 plugin->del_select_stmt);
385 return GNUNET_SYSERR; 411 return GNUNET_SYSERR;
386 } 412 }
387 rowid = sqlite3_column_int64 (stmt, 0); 413 if (GNUNET_OK !=
388 GNUNET_assert (sqlite3_column_bytes (stmt, 1) == sizeof (struct GNUNET_HashCode)); 414 GNUNET_SQ_extract_result (plugin->del_select_stmt,
389 GNUNET_memcpy (&hc, sqlite3_column_blob (stmt, 1), sizeof (struct GNUNET_HashCode)); 415 rs))
390 dsize = sqlite3_column_bytes (stmt, 2);
391 if (SQLITE_OK != sqlite3_finalize (stmt))
392 LOG_SQLITE (plugin->dbh,
393 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
394 "sqlite3_step");
395 if (SQLITE_OK !=
396 sq_prepare (plugin->dbh,
397 "DELETE FROM ds090 WHERE _ROWID_=?", &dstmt))
398 { 416 {
399 LOG_SQLITE (plugin->dbh, 417 GNUNET_break (0);
400 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 418 GNUNET_SQ_reset (plugin->dbh,
401 "sq_prepare"); 419 plugin->del_select_stmt);
402 if (stmt != NULL)
403 (void) sqlite3_finalize (stmt);
404 return GNUNET_SYSERR; 420 return GNUNET_SYSERR;
405 } 421 }
406 if (SQLITE_OK != sqlite3_bind_int64 (dstmt, 1, rowid)) 422 GNUNET_SQ_cleanup_result (rs);
423 GNUNET_SQ_reset (plugin->dbh,
424 plugin->del_select_stmt);
425 if (GNUNET_OK !=
426 GNUNET_SQ_bind (plugin->del_stmt,
427 params))
407 { 428 {
408 LOG_SQLITE (plugin->dbh, 429 LOG_SQLITE (plugin->dbh,
409 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 430 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
410 "sqlite3_bind"); 431 "sqlite3_bind");
411 (void) sqlite3_finalize (dstmt); 432 GNUNET_SQ_reset (plugin->dbh,
433 plugin->del_stmt);
412 return GNUNET_SYSERR; 434 return GNUNET_SYSERR;
413 } 435 }
414 if (SQLITE_DONE != sqlite3_step (dstmt)) 436 if (SQLITE_DONE !=
437 sqlite3_step (plugin->del_stmt))
415 { 438 {
416 LOG_SQLITE (plugin->dbh, 439 LOG_SQLITE (plugin->dbh,
417 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 440 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
418 "sqlite3_step"); 441 "sqlite3_step");
419 (void) sqlite3_finalize (dstmt); 442 GNUNET_SQ_reset (plugin->dbh,
443 plugin->del_stmt);
420 return GNUNET_SYSERR; 444 return GNUNET_SYSERR;
421 } 445 }
422 plugin->num_items--; 446 plugin->num_items--;
423 plugin->env->delete_notify (plugin->env->cls, 447 plugin->env->delete_notify (plugin->env->cls,
424 &hc, 448 &hc,
425 dsize + OVERHEAD); 449 dsize + OVERHEAD);
426 if (SQLITE_OK != sqlite3_finalize (dstmt)) 450 GNUNET_SQ_reset (plugin->dbh,
427 LOG_SQLITE (plugin->dbh, 451 plugin->del_stmt);
428 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
429 "sqlite3_finalize");
430 return GNUNET_OK; 452 return GNUNET_OK;
431} 453}
432 454
@@ -445,17 +467,28 @@ sqlite_plugin_get_random (void *cls,
445 void *iter_cls) 467 void *iter_cls)
446{ 468{
447 struct Plugin *plugin = cls; 469 struct Plugin *plugin = cls;
448 sqlite3_stmt *stmt;
449 struct GNUNET_TIME_Absolute exp; 470 struct GNUNET_TIME_Absolute exp;
450 unsigned int size; 471 size_t size;
451 const char *dat; 472 void *dat;
452 unsigned int off; 473 uint32_t off;
453 unsigned int psize; 474 size_t psize;
454 unsigned int type; 475 uint32_t type;
455 char scratch[256]; 476 struct GNUNET_PeerIdentity *path;
456 int64_t ntime; 477 struct GNUNET_HashCode key;
457 const struct GNUNET_PeerIdentity *path; 478 struct GNUNET_SQ_QueryParam params[] = {
458 const struct GNUNET_HashCode *key; 479 GNUNET_SQ_query_param_uint32 (&off),
480 GNUNET_SQ_query_param_end
481 };
482 struct GNUNET_SQ_ResultSpec rs[] = {
483 GNUNET_SQ_result_spec_variable_size (&dat,
484 &size),
485 GNUNET_SQ_result_spec_absolute_time (&exp),
486 GNUNET_SQ_result_spec_variable_size ((void **) &path,
487 &psize),
488 GNUNET_SQ_result_spec_auto_from_type (&key),
489 GNUNET_SQ_result_spec_uint32 (&type),
490 GNUNET_SQ_result_spec_end
491 };
459 492
460 if (0 == plugin->num_items) 493 if (0 == plugin->num_items)
461 return 0; 494 return 0;
@@ -463,60 +496,51 @@ sqlite_plugin_get_random (void *cls,
463 return 1; 496 return 1;
464 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 497 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
465 plugin->num_items); 498 plugin->num_items);
466 GNUNET_snprintf (scratch, 499 if (GNUNET_OK !=
467 sizeof (scratch), 500 GNUNET_SQ_bind (plugin->get_random_stmt,
468 "SELECT value,expire,path,key,type FROM ds090 ORDER BY key LIMIT 1 OFFSET %u", 501 params))
469 off);
470 if (SQLITE_OK !=
471 sq_prepare (plugin->dbh, scratch, &stmt))
472 { 502 {
473 LOG_SQLITE (plugin->dbh,
474 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
475 "sq_prepare");
476 return 0; 503 return 0;
477 } 504 }
478 if (SQLITE_ROW != sqlite3_step (stmt)) 505 if (SQLITE_ROW !=
506 sqlite3_step (plugin->get_random_stmt))
507 {
508 GNUNET_break (0);
509 GNUNET_SQ_reset (plugin->dbh,
510 plugin->get_random_stmt);
511 return 0;
512 }
513 if (GNUNET_OK !=
514 GNUNET_SQ_extract_result (plugin->get_random_stmt,
515 rs))
479 { 516 {
480 GNUNET_break (0); 517 GNUNET_break (0);
481 sqlite3_finalize (stmt); 518 GNUNET_SQ_reset (plugin->dbh,
519 plugin->get_random_stmt);
482 return 0; 520 return 0;
483 } 521 }
484 size = sqlite3_column_bytes (stmt, 0);
485 dat = sqlite3_column_blob (stmt, 0);
486 exp.abs_value_us = sqlite3_column_int64 (stmt, 1);
487 psize = sqlite3_column_bytes (stmt, 2);
488 if (0 != psize % sizeof (struct GNUNET_PeerIdentity)) 522 if (0 != psize % sizeof (struct GNUNET_PeerIdentity))
489 { 523 {
490 GNUNET_break (0); 524 GNUNET_break (0);
491 psize = 0; 525 psize = 0;
526 path = NULL;
492 } 527 }
493 psize /= sizeof (struct GNUNET_PeerIdentity); 528 psize /= sizeof (struct GNUNET_PeerIdentity);
494 if (0 != psize)
495 path = sqlite3_column_blob (stmt, 2);
496 else
497 path = NULL;
498
499 GNUNET_assert (sizeof (struct GNUNET_HashCode) ==
500 sqlite3_column_bytes (stmt, 3));
501 key = sqlite3_column_blob (stmt, 3);
502 type = sqlite3_column_int (stmt, 4);
503
504 ntime = (int64_t) exp.abs_value_us;
505 if (ntime == INT64_MAX)
506 exp = GNUNET_TIME_UNIT_FOREVER_ABS;
507 LOG (GNUNET_ERROR_TYPE_DEBUG, 529 LOG (GNUNET_ERROR_TYPE_DEBUG,
508 "Found %u-byte result with key %s when processing GET-RANDOM\n", 530 "Found %u-byte result with key %s when processing GET-RANDOM\n",
509 (unsigned int) size, 531 (unsigned int) size,
510 GNUNET_h2s (key)); 532 GNUNET_h2s (&key));
511 (void) iter (iter_cls, 533 (void) iter (iter_cls,
512 key, 534 &key,
513 size, 535 size,
514 dat, 536 dat,
515 type, 537 (enum GNUNET_BLOCK_Type) type,
516 exp, 538 exp,
517 psize, 539 psize,
518 path); 540 path);
519 sqlite3_finalize (stmt); 541 GNUNET_SQ_cleanup_result (rs);
542 GNUNET_SQ_reset (plugin->dbh,
543 plugin->get_random_stmt);
520 return 1; 544 return 1;
521} 545}
522 546
@@ -542,83 +566,73 @@ sqlite_plugin_get_closest (void *cls,
542 void *iter_cls) 566 void *iter_cls)
543{ 567{
544 struct Plugin *plugin = cls; 568 struct Plugin *plugin = cls;
545 sqlite3_stmt *stmt; 569 uint32_t num_results32 = num_results;
546 struct GNUNET_TIME_Absolute now; 570 struct GNUNET_TIME_Absolute now;
547 struct GNUNET_TIME_Absolute exp; 571 struct GNUNET_TIME_Absolute exp;
548 unsigned int size; 572 size_t size;
549 const char *dat; 573 void *dat;
550 unsigned int cnt; 574 unsigned int cnt;
551 unsigned int psize; 575 size_t psize;
552 unsigned int type; 576 uint32_t type;
553 int64_t ntime; 577 struct GNUNET_HashCode hc;
554 const struct GNUNET_PeerIdentity *path; 578 struct GNUNET_PeerIdentity *path;
579 struct GNUNET_SQ_QueryParam params[] = {
580 GNUNET_SQ_query_param_auto_from_type (key),
581 GNUNET_SQ_query_param_absolute_time (&now),
582 GNUNET_SQ_query_param_uint32 (&num_results32),
583 GNUNET_SQ_query_param_end
584 };
585 struct GNUNET_SQ_ResultSpec rs[] = {
586 GNUNET_SQ_result_spec_variable_size (&dat,
587 &size),
588 GNUNET_SQ_result_spec_absolute_time (&exp),
589 GNUNET_SQ_result_spec_variable_size ((void **) &path,
590 &psize),
591 GNUNET_SQ_result_spec_uint32 (&type),
592 GNUNET_SQ_result_spec_auto_from_type (&hc),
593 GNUNET_SQ_result_spec_end
594 };
555 595
556 now = GNUNET_TIME_absolute_get (); 596 now = GNUNET_TIME_absolute_get ();
557 LOG (GNUNET_ERROR_TYPE_DEBUG, 597 LOG (GNUNET_ERROR_TYPE_DEBUG,
558 "Processing GET_CLOSEST for key `%4s'\n", 598 "Processing GET_CLOSEST for key `%s'\n",
559 GNUNET_h2s (key)); 599 GNUNET_h2s (key));
560 if (SQLITE_OK != 600 if (GNUNET_OK !=
561 sq_prepare (plugin->dbh, 601 GNUNET_SQ_bind (plugin->get_closest_stmt,
562 "SELECT value,expire,path,type,key FROM ds090 WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?", 602 params))
563 &stmt))
564 {
565 LOG_SQLITE (plugin->dbh,
566 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
567 "sq_prepare");
568 return 0;
569 }
570 ntime = (int64_t) now.abs_value_us;
571 GNUNET_assert (ntime >= 0);
572 if ((SQLITE_OK !=
573 sqlite3_bind_blob (stmt,
574 1,
575 key,
576 sizeof (struct GNUNET_HashCode),
577 SQLITE_TRANSIENT)) ||
578 (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, now.abs_value_us)) ||
579 (SQLITE_OK != sqlite3_bind_int (stmt, 3, num_results)) )
580 { 603 {
581 LOG_SQLITE (plugin->dbh, 604 LOG_SQLITE (plugin->dbh,
582 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 605 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
583 "sqlite3_bind_xxx"); 606 "sqlite3_bind_xxx");
584 sqlite3_finalize (stmt); 607 GNUNET_SQ_reset (plugin->dbh,
608 plugin->get_closest_stmt);
585 return 0; 609 return 0;
586 } 610 }
587 cnt = 0; 611 cnt = 0;
588 while (SQLITE_ROW == sqlite3_step (stmt)) 612 while (SQLITE_ROW ==
613 sqlite3_step (plugin->get_closest_stmt))
589 { 614 {
590 if (sizeof (struct GNUNET_HashCode) != 615 if (GNUNET_OK !=
591 sqlite3_column_bytes (stmt, 4)) 616 GNUNET_SQ_extract_result (plugin->get_closest_stmt,
617 rs))
592 { 618 {
593 GNUNET_break (0); 619 GNUNET_break (0);
594 break; 620 break;
595 } 621 }
596 size = sqlite3_column_bytes (stmt, 0);
597 dat = sqlite3_column_blob (stmt, 0);
598 exp.abs_value_us = sqlite3_column_int64 (stmt, 1);
599 psize = sqlite3_column_bytes (stmt, 2);
600 type = sqlite3_column_int (stmt, 3);
601 key = sqlite3_column_blob (stmt, 4);
602 if (0 != psize % sizeof (struct GNUNET_PeerIdentity)) 622 if (0 != psize % sizeof (struct GNUNET_PeerIdentity))
603 { 623 {
604 GNUNET_break (0); 624 GNUNET_break (0);
605 psize = 0; 625 psize = 0;
626 path = NULL;
606 } 627 }
607 psize /= sizeof (struct GNUNET_PeerIdentity); 628 psize /= sizeof (struct GNUNET_PeerIdentity);
608 if (0 != psize)
609 path = sqlite3_column_blob (stmt, 2);
610 else
611 path = NULL;
612 ntime = (int64_t) exp.abs_value_us;
613 if (ntime == INT64_MAX)
614 exp = GNUNET_TIME_UNIT_FOREVER_ABS;
615 cnt++; 629 cnt++;
616 LOG (GNUNET_ERROR_TYPE_DEBUG, 630 LOG (GNUNET_ERROR_TYPE_DEBUG,
617 "Found %u-byte result at %s when processing GET_CLOSE\n", 631 "Found %u-byte result at %s when processing GET_CLOSE\n",
618 (unsigned int) size, 632 (unsigned int) size,
619 GNUNET_h2s (key)); 633 GNUNET_h2s (&hc));
620 if (GNUNET_OK != iter (iter_cls, 634 if (GNUNET_OK != iter (iter_cls,
621 key, 635 &hc,
622 size, 636 size,
623 dat, 637 dat,
624 type, 638 type,
@@ -626,11 +640,13 @@ sqlite_plugin_get_closest (void *cls,
626 psize, 640 psize,
627 path)) 641 path))
628 { 642 {
629 sqlite3_finalize (stmt); 643 GNUNET_SQ_cleanup_result (rs);
630 break; 644 break;
631 } 645 }
646 GNUNET_SQ_cleanup_result (rs);
632 } 647 }
633 sqlite3_finalize (stmt); 648 GNUNET_SQ_reset (plugin->dbh,
649 plugin->get_closest_stmt);
634 return cnt; 650 return cnt;
635} 651}
636 652
@@ -703,6 +719,50 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
703 plugin->env = env; 719 plugin->env = env;
704 plugin->dbh = dbh; 720 plugin->dbh = dbh;
705 plugin->fn = fn_utf8; 721 plugin->fn = fn_utf8;
722
723 if ( (SQLITE_OK !=
724 sq_prepare (plugin->dbh,
725 "INSERT INTO ds090 (type, expire, key, value, path) "
726 "VALUES (?, ?, ?, ?, ?)",
727 &plugin->insert_stmt)) ||
728 (SQLITE_OK !=
729 sq_prepare (plugin->dbh,
730 "SELECT count(*) FROM ds090 "
731 "WHERE key=? AND type=? AND expire >= ?",
732 &plugin->get_count_stmt)) ||
733 (SQLITE_OK !=
734 sq_prepare (plugin->dbh,
735 "SELECT value,expire,path FROM ds090 "
736 "WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?",
737 &plugin->get_stmt)) ||
738 (SQLITE_OK !=
739 sq_prepare (plugin->dbh,
740 "SELECT _ROWID_,key,value FROM ds090 ORDER BY expire ASC LIMIT 1",
741 &plugin->del_select_stmt)) ||
742 (SQLITE_OK !=
743 sq_prepare (plugin->dbh,
744 "DELETE FROM ds090 WHERE _ROWID_=?",
745 &plugin->del_stmt)) ||
746 (SQLITE_OK !=
747 sq_prepare (plugin->dbh,
748 "SELECT value,expire,path,key,type FROM ds090 "
749 "ORDER BY key LIMIT 1 OFFSET ?",
750 &plugin->get_random_stmt)) ||
751 (SQLITE_OK !=
752 sq_prepare (plugin->dbh,
753 "SELECT value,expire,path,type,key FROM ds090 "
754 "WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?",
755 &plugin->get_closest_stmt))
756 )
757 {
758 LOG_SQLITE (plugin->dbh,
759 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
760 "sq_prepare");
761 (void) sqlite3_close (plugin->dbh);
762 GNUNET_free (plugin);
763 return NULL;
764 }
765
706 api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions); 766 api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions);
707 api->cls = plugin; 767 api->cls = plugin;
708 api->get = &sqlite_plugin_get; 768 api->get = &sqlite_plugin_get;
@@ -741,6 +801,13 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
741 plugin->fn); 801 plugin->fn);
742 GNUNET_free_non_null (plugin->fn); 802 GNUNET_free_non_null (plugin->fn);
743#endif 803#endif
804 sqlite3_finalize (plugin->insert_stmt);
805 sqlite3_finalize (plugin->get_count_stmt);
806 sqlite3_finalize (plugin->get_stmt);
807 sqlite3_finalize (plugin->del_select_stmt);
808 sqlite3_finalize (plugin->del_stmt);
809 sqlite3_finalize (plugin->get_random_stmt);
810 sqlite3_finalize (plugin->get_closest_stmt);
744 result = sqlite3_close (plugin->dbh); 811 result = sqlite3_close (plugin->dbh);
745#if SQLITE_VERSION_NUMBER >= 3007000 812#if SQLITE_VERSION_NUMBER >= 3007000
746 if (SQLITE_BUSY == result) 813 if (SQLITE_BUSY == result)