diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-03-12 02:51:36 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-03-12 02:51:36 +0100 |
commit | a707b513688690a3dad9dc39535900da73a79f28 (patch) | |
tree | 0439c267fc54960441ae09f0ca5c62e0c41f2cb7 /src | |
parent | 538d7fde8cb1c0d079f01f2290aa3e3e2744beff (diff) | |
download | gnunet-a707b513688690a3dad9dc39535900da73a79f28.tar.gz gnunet-a707b513688690a3dad9dc39535900da73a79f28.zip |
converting datacache to sqlite, fixing misc. issues in libgnunetsq
Diffstat (limited to 'src')
-rw-r--r-- | src/datacache/Makefile.am | 1 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_sqlite.c | 549 | ||||
-rw-r--r-- | src/datastore/plugin_datastore_sqlite.c | 8 | ||||
-rw-r--r-- | src/include/gnunet_sq_lib.h | 11 | ||||
-rw-r--r-- | src/sq/sq.c | 25 | ||||
-rw-r--r-- | src/sq/sq_query_helper.c | 44 | ||||
-rw-r--r-- | src/sq/sq_result_helper.c | 67 |
7 files changed, 457 insertions, 248 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 |
54 | libgnunet_plugin_datacache_sqlite_la_LIBADD = \ | 54 | libgnunet_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) |
58 | libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \ | 59 | libgnunet_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 | |||
354 | sqlite_plugin_del (void *cls) | 382 | sqlite_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) |
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index 4e65f9d14..54bf4e55d 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c | |||
@@ -855,11 +855,9 @@ execute_get (struct Plugin *plugin, | |||
855 | anonymity, | 855 | anonymity, |
856 | expiration, | 856 | expiration, |
857 | rowid); | 857 | rowid); |
858 | if (SQLITE_OK != | 858 | GNUNET_SQ_cleanup_result (rs); |
859 | sqlite3_reset (stmt)) | 859 | GNUNET_SQ_reset (plugin->dbh, |
860 | LOG_SQLITE (plugin, | 860 | stmt); |
861 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
862 | "sqlite3_reset"); | ||
863 | if ( (GNUNET_NO == ret) && | 861 | if ( (GNUNET_NO == ret) && |
864 | (GNUNET_OK == delete_by_rowid (plugin, | 862 | (GNUNET_OK == delete_by_rowid (plugin, |
865 | rowid)) && | 863 | rowid)) && |
diff --git a/src/include/gnunet_sq_lib.h b/src/include/gnunet_sq_lib.h index 4d2510ee5..c196d7767 100644 --- a/src/include/gnunet_sq_lib.h +++ b/src/include/gnunet_sq_lib.h | |||
@@ -194,6 +194,17 @@ GNUNET_SQ_bind (sqlite3_stmt *stmt, | |||
194 | 194 | ||
195 | 195 | ||
196 | /** | 196 | /** |
197 | * Reset @a stmt and log error. | ||
198 | * | ||
199 | * @param dbh database handle | ||
200 | * @param stmt statement to reset | ||
201 | */ | ||
202 | void | ||
203 | GNUNET_SQ_reset (sqlite3 *dbh, | ||
204 | sqlite3_stmt *stmt); | ||
205 | |||
206 | |||
207 | /** | ||
197 | * Extract data from a Postgres database @a result at row @a row. | 208 | * Extract data from a Postgres database @a result at row @a row. |
198 | * | 209 | * |
199 | * @param cls closure | 210 | * @param cls closure |
diff --git a/src/sq/sq.c b/src/sq/sq.c index 114de2d88..089ebf0ff 100644 --- a/src/sq/sq.c +++ b/src/sq/sq.c | |||
@@ -90,7 +90,12 @@ GNUNET_SQ_extract_result (sqlite3_stmt *result, | |||
90 | j, | 90 | j, |
91 | rs[i].result_size, | 91 | rs[i].result_size, |
92 | rs[i].dst)) | 92 | rs[i].dst)) |
93 | { | ||
94 | for (unsigned int k=0;k<i;k++) | ||
95 | if (NULL != rs[k].cleaner) | ||
96 | rs[k].cleaner (rs[k].cls); | ||
93 | return GNUNET_SYSERR; | 97 | return GNUNET_SYSERR; |
98 | } | ||
94 | GNUNET_assert (0 != rs[i].num_params); | 99 | GNUNET_assert (0 != rs[i].num_params); |
95 | j += rs[i].num_params; | 100 | j += rs[i].num_params; |
96 | } | 101 | } |
@@ -112,4 +117,24 @@ GNUNET_SQ_cleanup_result (struct GNUNET_SQ_ResultSpec *rs) | |||
112 | rs[i].cleaner (rs[i].cls); | 117 | rs[i].cleaner (rs[i].cls); |
113 | } | 118 | } |
114 | 119 | ||
120 | |||
121 | /** | ||
122 | * Reset @a stmt and log error. | ||
123 | * | ||
124 | * @param dbh database handle | ||
125 | * @param stmt statement to reset | ||
126 | */ | ||
127 | void | ||
128 | GNUNET_SQ_reset (sqlite3 *dbh, | ||
129 | sqlite3_stmt *stmt) | ||
130 | { | ||
131 | if (SQLITE_OK != | ||
132 | sqlite3_reset (stmt)) | ||
133 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
134 | "sqlite", | ||
135 | _("Failed to reset sqlite statement with error: %s\n"), | ||
136 | sqlite3_errmsg (dbh)); | ||
137 | } | ||
138 | |||
139 | |||
115 | /* end of sq.c */ | 140 | /* end of sq.c */ |
diff --git a/src/sq/sq_query_helper.c b/src/sq/sq_query_helper.c index 5529c5e6c..a04b4ced4 100644 --- a/src/sq/sq_query_helper.c +++ b/src/sq/sq_query_helper.c | |||
@@ -235,6 +235,40 @@ GNUNET_SQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x) | |||
235 | 235 | ||
236 | 236 | ||
237 | /** | 237 | /** |
238 | * Function called to convert input argument into SQL parameters. | ||
239 | * | ||
240 | * @param cls closure | ||
241 | * @param data pointer to input argument | ||
242 | * @param data_len number of bytes in @a data (if applicable) | ||
243 | * @param stmt sqlite statement to bind parameters for | ||
244 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
245 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
246 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
247 | */ | ||
248 | static int | ||
249 | bind_abstime (void *cls, | ||
250 | const void *data, | ||
251 | size_t data_len, | ||
252 | sqlite3_stmt *stmt, | ||
253 | unsigned int off) | ||
254 | { | ||
255 | const struct GNUNET_TIME_Absolute *u = data; | ||
256 | struct GNUNET_TIME_Absolute abs; | ||
257 | |||
258 | abs = *u; | ||
259 | if (abs.abs_value_us > INT64_MAX) | ||
260 | abs.abs_value_us = INT64_MAX; | ||
261 | GNUNET_assert (sizeof (uint64_t) == data_len); | ||
262 | if (SQLITE_OK != | ||
263 | sqlite3_bind_int64 (stmt, | ||
264 | (int) off, | ||
265 | (sqlite3_int64) abs.abs_value_us)) | ||
266 | return GNUNET_SYSERR; | ||
267 | return GNUNET_OK; | ||
268 | } | ||
269 | |||
270 | |||
271 | /** | ||
238 | * Generate query parameter for an absolute time value. | 272 | * Generate query parameter for an absolute time value. |
239 | * The database must store a 64-bit integer. | 273 | * The database must store a 64-bit integer. |
240 | * | 274 | * |
@@ -243,7 +277,13 @@ GNUNET_SQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x) | |||
243 | struct GNUNET_SQ_QueryParam | 277 | struct GNUNET_SQ_QueryParam |
244 | GNUNET_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x) | 278 | GNUNET_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x) |
245 | { | 279 | { |
246 | return GNUNET_SQ_query_param_uint64 (&x->abs_value_us); | 280 | struct GNUNET_SQ_QueryParam qp = { |
281 | .conv = &bind_abstime, | ||
282 | .data = x, | ||
283 | .size = sizeof (struct GNUNET_TIME_Absolute), | ||
284 | .num_params = 1 | ||
285 | }; | ||
286 | return qp; | ||
247 | } | 287 | } |
248 | 288 | ||
249 | 289 | ||
@@ -269,6 +309,8 @@ bind_nbotime (void *cls, | |||
269 | struct GNUNET_TIME_Absolute abs; | 309 | struct GNUNET_TIME_Absolute abs; |
270 | 310 | ||
271 | abs = GNUNET_TIME_absolute_ntoh (*u); | 311 | abs = GNUNET_TIME_absolute_ntoh (*u); |
312 | if (abs.abs_value_us > INT64_MAX) | ||
313 | abs.abs_value_us = INT64_MAX; | ||
272 | GNUNET_assert (sizeof (uint64_t) == data_len); | 314 | GNUNET_assert (sizeof (uint64_t) == data_len); |
273 | if (SQLITE_OK != | 315 | if (SQLITE_OK != |
274 | sqlite3_bind_int64 (stmt, | 316 | sqlite3_bind_int64 (stmt, |
diff --git a/src/sq/sq_result_helper.c b/src/sq/sq_result_helper.c index eaf606aa4..fad3f3c8d 100644 --- a/src/sq/sq_result_helper.c +++ b/src/sq/sq_result_helper.c | |||
@@ -46,6 +46,15 @@ extract_var_blob (void *cls, | |||
46 | const void *ret; | 46 | const void *ret; |
47 | void **rdst = (void **) dst; | 47 | void **rdst = (void **) dst; |
48 | 48 | ||
49 | if (SQLITE_NULL == | ||
50 | sqlite3_column_type (result, | ||
51 | column)) | ||
52 | { | ||
53 | *rdst = NULL; | ||
54 | *dst_size = 0; | ||
55 | return GNUNET_YES; | ||
56 | } | ||
57 | |||
49 | if (SQLITE_BLOB != | 58 | if (SQLITE_BLOB != |
50 | sqlite3_column_type (result, | 59 | sqlite3_column_type (result, |
51 | column)) | 60 | column)) |
@@ -142,6 +151,14 @@ extract_fixed_blob (void *cls, | |||
142 | int have; | 151 | int have; |
143 | const void *ret; | 152 | const void *ret; |
144 | 153 | ||
154 | if ( (0 == *dst_size) && | ||
155 | (SQLITE_NULL == | ||
156 | sqlite3_column_type (result, | ||
157 | column)) ) | ||
158 | { | ||
159 | return GNUNET_YES; | ||
160 | } | ||
161 | |||
145 | if (SQLITE_BLOB != | 162 | if (SQLITE_BLOB != |
146 | sqlite3_column_type (result, | 163 | sqlite3_column_type (result, |
147 | column)) | 164 | column)) |
@@ -459,6 +476,45 @@ GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig) | |||
459 | 476 | ||
460 | 477 | ||
461 | /** | 478 | /** |
479 | * Extract absolute time value from a Postgres database @a result at row @a row. | ||
480 | * | ||
481 | * @param cls closure | ||
482 | * @param result where to extract data from | ||
483 | * @param column column to extract data from | ||
484 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
485 | * @param[out] dst where to store the result | ||
486 | * @return | ||
487 | * #GNUNET_YES if all results could be extracted | ||
488 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
489 | */ | ||
490 | static int | ||
491 | extract_abs_time (void *cls, | ||
492 | sqlite3_stmt *result, | ||
493 | unsigned int column, | ||
494 | size_t *dst_size, | ||
495 | void *dst) | ||
496 | { | ||
497 | struct GNUNET_TIME_Absolute *u = dst; | ||
498 | struct GNUNET_TIME_Absolute t; | ||
499 | |||
500 | GNUNET_assert (sizeof (uint64_t) == *dst_size); | ||
501 | if (SQLITE_INTEGER != | ||
502 | sqlite3_column_type (result, | ||
503 | column)) | ||
504 | { | ||
505 | GNUNET_break (0); | ||
506 | return GNUNET_SYSERR; | ||
507 | } | ||
508 | t.abs_value_us = (uint64_t) sqlite3_column_int64 (result, | ||
509 | column); | ||
510 | if (INT64_MAX == t.abs_value_us) | ||
511 | t = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
512 | *u = t; | ||
513 | return GNUNET_OK; | ||
514 | } | ||
515 | |||
516 | |||
517 | /** | ||
462 | * Absolute time expected. | 518 | * Absolute time expected. |
463 | * | 519 | * |
464 | * @param[out] at where to store the result | 520 | * @param[out] at where to store the result |
@@ -467,7 +523,14 @@ GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig) | |||
467 | struct GNUNET_SQ_ResultSpec | 523 | struct GNUNET_SQ_ResultSpec |
468 | GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) | 524 | GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) |
469 | { | 525 | { |
470 | return GNUNET_SQ_result_spec_uint64 (&at->abs_value_us); | 526 | struct GNUNET_SQ_ResultSpec rs = { |
527 | .conv = &extract_abs_time, | ||
528 | .dst = at, | ||
529 | .dst_size = sizeof (struct GNUNET_TIME_Absolute), | ||
530 | .num_params = 1 | ||
531 | }; | ||
532 | |||
533 | return rs; | ||
471 | } | 534 | } |
472 | 535 | ||
473 | 536 | ||
@@ -503,6 +566,8 @@ extract_abs_time_nbo (void *cls, | |||
503 | } | 566 | } |
504 | t.abs_value_us = (uint64_t) sqlite3_column_int64 (result, | 567 | t.abs_value_us = (uint64_t) sqlite3_column_int64 (result, |
505 | column); | 568 | column); |
569 | if (INT64_MAX == t.abs_value_us) | ||
570 | t = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
506 | *u = GNUNET_TIME_absolute_hton (t); | 571 | *u = GNUNET_TIME_absolute_hton (t); |
507 | return GNUNET_OK; | 572 | return GNUNET_OK; |
508 | } | 573 | } |