fix #4546
[oweals/gnunet.git] / src / datastore / plugin_datastore_sqlite.c
1  /*
2   * This file is part of GNUnet
3   * Copyright (C) 2009, 2011 GNUnet e.V.
4   *
5   * GNUnet is free software; you can redistribute it and/or modify
6   * it under the terms of the GNU General Public License as published
7   * by the Free Software Foundation; either version 3, or (at your
8   * option) any later version.
9   *
10   * GNUnet is distributed in the hope that it will be useful, but
11   * WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   * General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with GNUnet; see the file COPYING.  If not, write to the
17   * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18   * Boston, MA 02110-1301, USA.
19   */
20
21 /**
22  * @file datastore/plugin_datastore_sqlite.c
23  * @brief sqlite-based datastore backend
24  * @author Christian Grothoff
25  */
26
27 #include "platform.h"
28 #include "gnunet_datastore_plugin.h"
29 #include <sqlite3.h>
30
31
32 /**
33  * We allocate items on the stack at times.  To prevent a stack
34  * overflow, we impose a limit on the maximum size for the data per
35  * item.  64k should be enough.
36  */
37 #define MAX_ITEM_SIZE 65536
38
39 /**
40  * After how many ms "busy" should a DB operation fail for good?
41  * A low value makes sure that we are more responsive to requests
42  * (especially PUTs).  A high value guarantees a higher success
43  * rate (SELECTs in iterate can take several seconds despite LIMIT=1).
44  *
45  * The default value of 250ms should ensure that users do not experience
46  * huge latencies while at the same time allowing operations to succeed
47  * with reasonable probability.
48  */
49 #define BUSY_TIMEOUT_MS 250
50
51
52 /**
53  * Log an error message at log-level 'level' that indicates
54  * a failure of the command 'cmd' on file 'filename'
55  * with the message given by strerror(errno).
56  */
57 #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
58
59
60 /**
61  * Log an error message at log-level 'level' that indicates
62  * a failure of the command 'cmd' on file 'filename'
63  * with the message given by strerror(errno).
64  */
65 #define LOG_SQLITE_MSG(db, msg, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); GNUNET_asprintf(msg, _("`%s' failed at %s:%u with error: %s"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
66
67
68
69 /**
70  * Context for all functions in this plugin.
71  */
72 struct Plugin
73 {
74   /**
75    * Our execution environment.
76    */
77   struct GNUNET_DATASTORE_PluginEnvironment *env;
78
79   /**
80    * Database filename.
81    */
82   char *fn;
83
84   /**
85    * Native SQLite database handle.
86    */
87   sqlite3 *dbh;
88
89   /**
90    * Precompiled SQL for deletion.
91    */
92   sqlite3_stmt *delRow;
93
94   /**
95    * Precompiled SQL for update.
96    */
97   sqlite3_stmt *updPrio;
98
99   /**
100    * Get maximum repl value in database.
101    */
102   sqlite3_stmt *maxRepl;
103
104   /**
105    * Precompiled SQL for replication decrement.
106    */
107   sqlite3_stmt *updRepl;
108
109   /**
110    * Precompiled SQL for replication selection.
111    */
112   sqlite3_stmt *selRepl;
113
114   /**
115    * Precompiled SQL for expiration selection.
116    */
117   sqlite3_stmt *selExpi;
118
119   /**
120    * Precompiled SQL for expiration selection.
121    */
122   sqlite3_stmt *selZeroAnon;
123
124   /**
125    * Precompiled SQL for insertion.
126    */
127   sqlite3_stmt *insertContent;
128
129   /**
130    * Should the database be dropped on shutdown?
131    */
132   int drop_on_shutdown;
133
134 };
135
136
137 /**
138  * @brief Prepare a SQL statement
139  *
140  * @param dbh handle to the database
141  * @param zSql SQL statement, UTF-8 encoded
142  * @param ppStmt set to the prepared statement
143  * @return 0 on success
144  */
145 static int
146 sq_prepare (sqlite3 *dbh,
147             const char *zSql,
148             sqlite3_stmt **ppStmt)
149 {
150   char *dummy;
151   int result;
152
153   result =
154       sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt,
155                           (const char **) &dummy);
156   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
157                    "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result);
158   return result;
159 }
160
161
162 /**
163  * Create our database indices.
164  *
165  * @param dbh handle to the database
166  */
167 static void
168 create_indices (sqlite3 * dbh)
169 {
170   /* create indices */
171   if ((SQLITE_OK !=
172        sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_hash ON gn090 (hash)",
173                      NULL, NULL, NULL)) ||
174       (SQLITE_OK !=
175        sqlite3_exec (dbh,
176                      "CREATE INDEX IF NOT EXISTS idx_hash_vhash ON gn090 (hash,vhash)",
177                      NULL, NULL, NULL)) ||
178       (SQLITE_OK !=
179        sqlite3_exec (dbh,
180                      "CREATE INDEX IF NOT EXISTS idx_expire_repl ON gn090 (expire ASC,repl DESC)",
181                      NULL, NULL, NULL)) ||
182       (SQLITE_OK !=
183        sqlite3_exec (dbh,
184                      "CREATE INDEX IF NOT EXISTS idx_comb ON gn090 (anonLevel ASC,expire ASC,prio,type,hash)",
185                      NULL, NULL, NULL)) ||
186       (SQLITE_OK !=
187        sqlite3_exec (dbh,
188                      "CREATE INDEX IF NOT EXISTS idx_anon_type_hash ON gn090 (anonLevel ASC,type,hash)",
189                      NULL, NULL, NULL)) ||
190       (SQLITE_OK !=
191        sqlite3_exec (dbh,
192                      "CREATE INDEX IF NOT EXISTS idx_expire ON gn090 (expire ASC)",
193                      NULL, NULL, NULL)) ||
194       (SQLITE_OK !=
195        sqlite3_exec (dbh,
196                      "CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn090 (repl,rvalue)",
197                      NULL, NULL, NULL)) ||
198       (SQLITE_OK !=
199        sqlite3_exec (dbh,
200                      "CREATE INDEX IF NOT EXISTS idx_repl ON gn090 (repl DESC)",
201                      NULL, NULL, NULL)))
202     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite",
203                      "Failed to create indices: %s\n", sqlite3_errmsg (dbh));
204 }
205
206
207 #if 0
208 #define CHECK(a) GNUNET_break(a)
209 #define ENULL NULL
210 #else
211 #define ENULL &e
212 #define ENULL_DEFINED 1
213 #define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
214 #endif
215
216
217 /**
218  * Initialize the database connections and associated
219  * data structures (create tables and indices
220  * as needed as well).
221  *
222  * @param cfg our configuration
223  * @param plugin the plugin context (state for this module)
224  * @return #GNUNET_OK on success
225  */
226 static int
227 database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
228                 struct Plugin *plugin)
229 {
230   sqlite3_stmt *stmt;
231   char *afsdir;
232
233 #if ENULL_DEFINED
234   char *e;
235 #endif
236
237   if (GNUNET_OK !=
238       GNUNET_CONFIGURATION_get_value_filename (cfg, "datastore-sqlite",
239                                                "FILENAME", &afsdir))
240   {
241     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
242                                "datastore-sqlite", "FILENAME");
243     return GNUNET_SYSERR;
244   }
245   if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
246   {
247     if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir))
248     {
249       GNUNET_break (0);
250       GNUNET_free (afsdir);
251       return GNUNET_SYSERR;
252     }
253     /* database is new or got deleted, reset payload to zero! */
254     plugin->env->duc (plugin->env->cls, 0);
255   }
256   /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
257   plugin->fn = afsdir;
258
259   /* Open database and precompile statements */
260   if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
261   {
262     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite",
263                      _("Unable to initialize SQLite: %s.\n"),
264                      sqlite3_errmsg (plugin->dbh));
265     return GNUNET_SYSERR;
266   }
267   CHECK (SQLITE_OK ==
268          sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL,
269                        ENULL));
270   CHECK (SQLITE_OK ==
271          sqlite3_exec (plugin->dbh, "PRAGMA synchronous=OFF", NULL, NULL,
272                        ENULL));
273   CHECK (SQLITE_OK ==
274          sqlite3_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF", NULL, NULL,
275                        ENULL));
276   CHECK (SQLITE_OK ==
277          sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL,
278                        NULL, ENULL));
279   CHECK (SQLITE_OK ==
280          sqlite3_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
281                        ENULL));
282   CHECK (SQLITE_OK ==
283          sqlite3_exec (plugin->dbh, "PRAGMA page_size=4092", NULL, NULL,
284                        ENULL));
285
286   CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS));
287
288
289   /* We have to do it here, because otherwise precompiling SQL might fail */
290   CHECK (SQLITE_OK ==
291          sq_prepare (plugin->dbh,
292                      "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn090'",
293                      &stmt));
294   if ((sqlite3_step (stmt) == SQLITE_DONE) &&
295       (sqlite3_exec
296        (plugin->dbh,
297         "CREATE TABLE gn090 (" "  repl INT4 NOT NULL DEFAULT 0,"
298         "  type INT4 NOT NULL DEFAULT 0," "  prio INT4 NOT NULL DEFAULT 0,"
299         "  anonLevel INT4 NOT NULL DEFAULT 0,"
300         "  expire INT8 NOT NULL DEFAULT 0," "  rvalue INT8 NOT NULL,"
301         "  hash TEXT NOT NULL DEFAULT ''," "  vhash TEXT NOT NULL DEFAULT '',"
302         "  value BLOB NOT NULL DEFAULT '')", NULL, NULL, NULL) != SQLITE_OK))
303   {
304     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec");
305     sqlite3_finalize (stmt);
306     return GNUNET_SYSERR;
307   }
308   sqlite3_finalize (stmt);
309   create_indices (plugin->dbh);
310
311   if ((sq_prepare
312        (plugin->dbh,
313         "UPDATE gn090 "
314         "SET prio = prio + ?, expire = MAX(expire,?) WHERE _ROWID_ = ?",
315         &plugin->updPrio) != SQLITE_OK) ||
316       (sq_prepare
317        (plugin->dbh,
318         "UPDATE gn090 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?",
319         &plugin->updRepl) != SQLITE_OK) ||
320       (sq_prepare
321        (plugin->dbh,
322         "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 "
323 #if SQLITE_VERSION_NUMBER >= 3007000
324         "INDEXED BY idx_repl_rvalue "
325 #endif
326         "WHERE repl=?2 AND " " (rvalue>=?1 OR "
327         "  NOT EXISTS (SELECT 1 FROM gn090 "
328 #if SQLITE_VERSION_NUMBER >= 3007000
329         "INDEXED BY idx_repl_rvalue "
330 #endif
331         "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) "
332         "ORDER BY rvalue ASC LIMIT 1", &plugin->selRepl) != SQLITE_OK) ||
333       (sq_prepare (plugin->dbh, "SELECT MAX(repl) FROM gn090"
334 #if SQLITE_VERSION_NUMBER >= 3007000
335                    " INDEXED BY idx_repl_rvalue"
336 #endif
337                    "", &plugin->maxRepl) != SQLITE_OK) ||
338       (sq_prepare
339        (plugin->dbh,
340         "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 "
341 #if SQLITE_VERSION_NUMBER >= 3007000
342         "INDEXED BY idx_expire "
343 #endif
344         "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) ||
346       (sq_prepare
347        (plugin->dbh,
348         "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 "
349 #if SQLITE_VERSION_NUMBER >= 3007000
350         "INDEXED BY idx_anon_type_hash "
351 #endif
352         "WHERE (anonLevel = 0 AND type=?1) "
353         "ORDER BY hash DESC LIMIT 1 OFFSET ?2",
354         &plugin->selZeroAnon) != SQLITE_OK) ||
355       (sq_prepare
356        (plugin->dbh,
357         "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) "
358         "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
359         &plugin->insertContent) != SQLITE_OK) ||
360       (sq_prepare
361        (plugin->dbh, "DELETE FROM gn090 WHERE _ROWID_ = ?",
362         &plugin->delRow) != SQLITE_OK))
363   {
364     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "precompiling");
365     return GNUNET_SYSERR;
366   }
367
368   return GNUNET_OK;
369 }
370
371
372 /**
373  * Shutdown database connection and associate data
374  * structures.
375  *
376  * @param plugin the plugin context (state for this module)
377  */
378 static void
379 database_shutdown (struct Plugin *plugin)
380 {
381   int result;
382
383 #if SQLITE_VERSION_NUMBER >= 3007000
384   sqlite3_stmt *stmt;
385 #endif
386
387   if (plugin->delRow != NULL)
388     sqlite3_finalize (plugin->delRow);
389   if (plugin->updPrio != NULL)
390     sqlite3_finalize (plugin->updPrio);
391   if (plugin->updRepl != NULL)
392     sqlite3_finalize (plugin->updRepl);
393   if (plugin->selRepl != NULL)
394     sqlite3_finalize (plugin->selRepl);
395   if (plugin->maxRepl != NULL)
396     sqlite3_finalize (plugin->maxRepl);
397   if (plugin->selExpi != NULL)
398     sqlite3_finalize (plugin->selExpi);
399   if (plugin->selZeroAnon != NULL)
400     sqlite3_finalize (plugin->selZeroAnon);
401   if (plugin->insertContent != NULL)
402     sqlite3_finalize (plugin->insertContent);
403   result = sqlite3_close (plugin->dbh);
404 #if SQLITE_VERSION_NUMBER >= 3007000
405   if (result == SQLITE_BUSY)
406   {
407     GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite",
408                      _
409                      ("Tried to close sqlite without finalizing all prepared statements.\n"));
410     stmt = sqlite3_next_stmt (plugin->dbh, NULL);
411     while (stmt != NULL)
412     {
413       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
414                        "Closing statement %p\n", stmt);
415       result = sqlite3_finalize (stmt);
416       if (result != SQLITE_OK)
417         GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite",
418                          "Failed to close statement %p: %d\n", stmt, result);
419       stmt = sqlite3_next_stmt (plugin->dbh, NULL);
420     }
421     result = sqlite3_close (plugin->dbh);
422   }
423 #endif
424   if (SQLITE_OK != result)
425     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
426
427   GNUNET_free_non_null (plugin->fn);
428 }
429
430
431 /**
432  * Delete the database entry with the given
433  * row identifier.
434  *
435  * @param plugin the plugin context (state for this module)
436  * @param rid the ID of the row to delete
437  */
438 static int
439 delete_by_rowid (struct Plugin *plugin,
440                  unsigned long long rid)
441 {
442   if (SQLITE_OK != sqlite3_bind_int64 (plugin->delRow, 1, rid))
443   {
444     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
445                 "sqlite3_bind_XXXX");
446     if (SQLITE_OK != sqlite3_reset (plugin->delRow))
447       LOG_SQLITE (plugin,
448                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
449                   "sqlite3_reset");
450     return GNUNET_SYSERR;
451   }
452   if (SQLITE_DONE != sqlite3_step (plugin->delRow))
453   {
454     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
455                 "sqlite3_step");
456     if (SQLITE_OK != sqlite3_reset (plugin->delRow))
457       LOG_SQLITE (plugin,
458                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
459                   "sqlite3_reset");
460     return GNUNET_SYSERR;
461   }
462   if (SQLITE_OK != sqlite3_reset (plugin->delRow))
463     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
464                 "sqlite3_reset");
465   return GNUNET_OK;
466 }
467
468
469 /**
470  * Store an item in the datastore.
471  *
472  * @param cls closure
473  * @param key key for the item
474  * @param size number of bytes in @a data
475  * @param data content stored
476  * @param type type of the content
477  * @param priority priority of the content
478  * @param anonymity anonymity-level for the content
479  * @param replication replication-level for the content
480  * @param expiration expiration time for the content
481  * @param cont continuation called with success or failure status
482  * @param cont_cls continuation closure
483  */
484 static void
485 sqlite_plugin_put (void *cls,
486                    const struct GNUNET_HashCode *key,
487                    uint32_t size,
488                    const void *data,
489                    enum GNUNET_BLOCK_Type type,
490                    uint32_t priority,
491                    uint32_t anonymity,
492                    uint32_t replication,
493                    struct GNUNET_TIME_Absolute expiration,
494                    PluginPutCont cont,
495                    void *cont_cls)
496 {
497   struct Plugin *plugin = cls;
498   int n;
499   int ret;
500   sqlite3_stmt *stmt;
501   struct GNUNET_HashCode vhash;
502   uint64_t rvalue;
503   char *msg = NULL;
504
505   if (size > MAX_ITEM_SIZE)
506   {
507     cont (cont_cls, key, size, GNUNET_SYSERR, _("Data too large"));
508     return;
509   }
510   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
511                    "Storing in database block with type %u/key `%s'/priority %u/expiration in %s (%s).\n",
512                    type,
513                    GNUNET_h2s (key),
514                    priority,
515                    GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration),
516                                                            GNUNET_YES),
517                    GNUNET_STRINGS_absolute_time_to_string (expiration));
518   GNUNET_CRYPTO_hash (data, size, &vhash);
519   stmt = plugin->insertContent;
520   rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
521   if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, replication)) ||
522       (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) ||
523       (SQLITE_OK != sqlite3_bind_int (stmt, 3, priority)) ||
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   {
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);
542     GNUNET_free_non_null(msg);
543     return;
544   }
545   n = sqlite3_step (stmt);
546   switch (n)
547   {
548   case SQLITE_DONE:
549     plugin->env->duc (plugin->env->cls, size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
550     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
551                      "Stored new entry (%u bytes)\n",
552                      size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
553     ret = GNUNET_OK;
554     break;
555   case SQLITE_BUSY:
556     GNUNET_break (0);
557     LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
558                     "sqlite3_step");
559     ret = GNUNET_SYSERR;
560     break;
561   default:
562     LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
563                     "sqlite3_step");
564     if (SQLITE_OK != sqlite3_reset (stmt))
565       LOG_SQLITE (plugin,
566                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
567                   "sqlite3_reset");
568     database_shutdown (plugin);
569     database_setup (plugin->env->cfg, plugin);
570     cont (cont_cls, key, size, GNUNET_SYSERR, msg);
571     GNUNET_free_non_null(msg);
572     return;
573   }
574   if (SQLITE_OK != sqlite3_reset (stmt))
575     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
576                 "sqlite3_reset");
577   cont (cont_cls, key, size, ret, msg);
578   GNUNET_free_non_null(msg);
579 }
580
581
582 /**
583  * Update the priority for a particular key in the datastore.  If
584  * the expiration time in value is different than the time found in
585  * the datastore, the higher value should be kept.  For the
586  * anonymity level, the lower value is to be used.  The specified
587  * priority should be added to the existing priority, ignoring the
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  *
593  * @param cls the plugin context (state for this module)
594  * @param uid unique identifier of the datum
595  * @param delta by how much should the priority
596  *     change?  If priority + delta < 0 the
597  *     priority should be set to 0 (never go
598  *     negative).
599  * @param expire new expiration time should be the
600  *     MAX of any existing expiration time and
601  *     this value
602  * @param cont continuation called with success or failure status
603  * @param cons_cls continuation closure
604  */
605 static void
606 sqlite_plugin_update (void *cls,
607                       uint64_t uid,
608                       int delta,
609                       struct GNUNET_TIME_Absolute expire,
610                       PluginUpdateCont cont,
611                       void *cont_cls)
612 {
613   struct Plugin *plugin = cls;
614   int n;
615   char *msg = NULL;
616
617   if ((SQLITE_OK != sqlite3_bind_int (plugin->updPrio, 1, delta)) ||
618       (SQLITE_OK != sqlite3_bind_int64 (plugin->updPrio, 2, expire.abs_value_us))
619       || (SQLITE_OK != sqlite3_bind_int64 (plugin->updPrio, 3, uid)))
620   {
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);
628     GNUNET_free_non_null(msg);
629     return;
630   }
631   n = sqlite3_step (plugin->updPrio);
632   if (SQLITE_OK != sqlite3_reset (plugin->updPrio))
633     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
634                 "sqlite3_reset");
635   switch (n)
636   {
637   case SQLITE_DONE:
638     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Block updated\n");
639     cont (cont_cls, GNUNET_OK, NULL);
640     return;
641   case SQLITE_BUSY:
642     LOG_SQLITE_MSG (plugin, &msg,
643                     GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
644                     "sqlite3_step");
645     cont (cont_cls, GNUNET_NO, msg);
646     GNUNET_free_non_null(msg);
647     return;
648   default:
649     LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
650                     "sqlite3_step");
651     cont (cont_cls, GNUNET_SYSERR, msg);
652     GNUNET_free_non_null(msg);
653     return;
654   }
655 }
656
657
658 /**
659  * Execute statement that gets a row and call the callback
660  * with the result.  Resets the statement afterwards.
661  *
662  * @param plugin the plugin
663  * @param stmt the statement
664  * @param proc processor to call
665  * @param proc_cls closure for @a proc
666  */
667 static void
668 execute_get (struct Plugin *plugin,
669              sqlite3_stmt *stmt,
670              PluginDatumProcessor proc,
671              void *proc_cls)
672 {
673   int n;
674   struct GNUNET_TIME_Absolute expiration;
675   unsigned long long rowid;
676   unsigned int size;
677   int ret;
678
679   n = sqlite3_step (stmt);
680   switch (n)
681   {
682   case SQLITE_ROW:
683     size = sqlite3_column_bytes (stmt, 5);
684     rowid = sqlite3_column_int64 (stmt, 6);
685     if (sqlite3_column_bytes (stmt, 4) != sizeof (struct GNUNET_HashCode))
686     {
687       GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite",
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;
697     }
698     expiration.abs_value_us = sqlite3_column_int64 (stmt, 3);
699     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
700                      "Found reply in database with expiration %s\n",
701                      GNUNET_STRINGS_absolute_time_to_string (expiration));
702     ret = proc (proc_cls, sqlite3_column_blob (stmt, 4) /* key */ ,
703                 size, sqlite3_column_blob (stmt, 5) /* data */ ,
704                 sqlite3_column_int (stmt, 0) /* type */ ,
705                 sqlite3_column_int (stmt, 1) /* priority */ ,
706                 sqlite3_column_int (stmt, 2) /* anonymity */ ,
707                 expiration, rowid);
708     if (SQLITE_OK != sqlite3_reset (stmt))
709       LOG_SQLITE (plugin,
710                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
711                   "sqlite3_reset");
712     if ((GNUNET_NO == ret) && (GNUNET_OK == delete_by_rowid (plugin, rowid)))
713       plugin->env->duc (plugin->env->cls,
714                         -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
715     return;
716   case SQLITE_DONE:
717     /* 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;
723   case SQLITE_BUSY:
724   case SQLITE_ERROR:
725   case SQLITE_MISUSE:
726   default:
727     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
728                 "sqlite3_step");
729     if (SQLITE_OK != sqlite3_reset (stmt))
730       LOG_SQLITE (plugin,
731                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
732                   "sqlite3_reset");
733     GNUNET_break (0);
734     database_shutdown (plugin);
735     database_setup (plugin->env->cfg, plugin);
736     break;
737   }
738   if (SQLITE_OK != sqlite3_reset (stmt))
739     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
740                 "sqlite3_reset");
741   proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
742 }
743
744
745 /**
746  * Select a subset of the items in the datastore and call
747  * the given processor for the item.
748  *
749  * @param cls our plugin context
750  * @param offset offset of the result (modulo num-results);
751  *               specific ordering does not matter for the offset
752  * @param type entries of which type should be considered?
753  *        Use 0 for any type.
754  * @param proc function to call on each matching value;
755  *        will be called once with a NULL value at the end
756  * @param proc_cls closure for @a proc
757  */
758 static void
759 sqlite_plugin_get_zero_anonymity (void *cls, uint64_t offset,
760                                   enum GNUNET_BLOCK_Type type,
761                                   PluginDatumProcessor proc, void *proc_cls)
762 {
763   struct Plugin *plugin = cls;
764   sqlite3_stmt *stmt;
765
766   GNUNET_assert (type != GNUNET_BLOCK_TYPE_ANY);
767   stmt = plugin->selZeroAnon;
768   if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) ||
769       (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, offset)))
770   {
771     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
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;
779   }
780   execute_get (plugin, stmt, proc, proc_cls);
781 }
782
783
784 /**
785  * Get results for a particular key in the datastore.
786  *
787  * @param cls closure
788  * @param offset offset (mod count).
789  * @param key key to match, never NULL
790  * @param vhash hash of the value, maybe NULL (to
791  *        match all values that have the right key).
792  *        Note that for DBlocks there is no difference
793  *        betwen key and vhash, but for other blocks
794  *        there may be!
795  * @param type entries of which type are relevant?
796  *     Use 0 for any type.
797  * @param proc function to call on each matching value;
798  *        will be called once with a NULL value at the end
799  * @param proc_cls closure for @a proc
800  */
801 static void
802 sqlite_plugin_get_key (void *cls,
803                        uint64_t offset,
804                        const struct GNUNET_HashCode *key,
805                        const struct GNUNET_HashCode *vhash,
806                        enum GNUNET_BLOCK_Type type,
807                        PluginDatumProcessor proc,
808                        void *proc_cls)
809 {
810   struct Plugin *plugin = cls;
811   int ret;
812   int total;
813   int limit_off;
814   unsigned int sqoff;
815   sqlite3_stmt *stmt;
816   char scratch[256];
817
818   GNUNET_assert (proc != NULL);
819   GNUNET_assert (key != NULL);
820   GNUNET_snprintf (scratch, sizeof (scratch),
821                    "SELECT count(*) FROM gn090 WHERE hash=?%s%s",
822                    vhash == NULL ? "" : " AND vhash=?",
823                    type == 0 ? "" : " AND type=?");
824   if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK)
825   {
826     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
827                 "sqlite_prepare");
828     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
829     return;
830   }
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   {
875     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
876                 "sqlite_prepare");
877     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
878     return;
879   }
880   sqoff = 1;
881   ret = sqlite3_bind_blob (stmt, sqoff++, key,
882                            sizeof (struct GNUNET_HashCode),
883                            SQLITE_TRANSIENT);
884   if ((vhash != NULL) && (ret == SQLITE_OK))
885     ret = sqlite3_bind_blob (stmt, sqoff++, vhash,
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   {
894     LOG_SQLITE (plugin,
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;
899   }
900   execute_get (plugin, stmt, proc, proc_cls);
901   sqlite3_finalize (stmt);
902 }
903
904
905 /**
906  * Context for #repl_proc() function.
907  */
908 struct ReplCtx
909 {
910
911   /**
912    * Function to call for the result (or the NULL).
913    */
914   PluginDatumProcessor proc;
915
916   /**
917    * Closure for @e proc.
918    */
919   void *proc_cls;
920
921   /**
922    * UID to use.
923    */
924   uint64_t uid;
925
926   /**
927    * Yes if UID was set.
928    */
929   int have_uid;
930 };
931
932
933 /**
934  * Wrapper for the processor for #sqlite_plugin_get_replication().
935  * Decrements the replication counter and calls the original
936  * processor.
937  *
938  * @param cls closure
939  * @param key key for the content
940  * @param size number of bytes in @a data
941  * @param data content stored
942  * @param type type of the content
943  * @param priority priority of the content
944  * @param anonymity anonymity-level for the content
945  * @param expiration expiration time for the content
946  * @param uid unique identifier for the datum;
947  *        maybe 0 if no unique identifier is available
948  * @return #GNUNET_OK for normal return,
949  *         #GNUNET_NO to delete the item
950  */
951 static int
952 repl_proc (void *cls,
953            const struct GNUNET_HashCode *key,
954            uint32_t size,
955            const void *data,
956            enum GNUNET_BLOCK_Type type,
957            uint32_t priority,
958            uint32_t anonymity,
959            struct GNUNET_TIME_Absolute expiration,
960            uint64_t uid)
961 {
962   struct ReplCtx *rc = cls;
963   int ret;
964
965   ret = rc->proc (rc->proc_cls,
966                   key,
967                   size, data,
968                   type,
969                   priority,
970                   anonymity,
971                   expiration, uid);
972   if (NULL != key)
973   {
974     rc->uid = uid;
975     rc->have_uid = GNUNET_YES;
976   }
977   return ret;
978 }
979
980
981 /**
982  * Get a random item for replication.  Returns a single random item
983  * from those with the highest replication counters.  The item's
984  * replication counter is decremented by one IF it was positive before.
985  * Call @a proc with all values ZERO or NULL if the datastore is empty.
986  *
987  * @param cls closure
988  * @param proc function to call the value (once only).
989  * @param proc_cls closure for @a proc
990  */
991 static void
992 sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc,
993                                void *proc_cls)
994 {
995   struct Plugin *plugin = cls;
996   struct ReplCtx rc;
997   uint64_t rvalue;
998   uint32_t repl;
999   sqlite3_stmt *stmt;
1000
1001   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
1002                    "Getting random block based on replication order.\n");
1003   rc.have_uid = GNUNET_NO;
1004   rc.proc = proc;
1005   rc.proc_cls = proc_cls;
1006   stmt = plugin->maxRepl;
1007   if (SQLITE_ROW != sqlite3_step (stmt))
1008   {
1009     if (SQLITE_OK != sqlite3_reset (stmt))
1010       LOG_SQLITE (plugin,
1011                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1012                   "sqlite3_reset");
1013     /* DB empty */
1014     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1015     return;
1016   }
1017   repl = sqlite3_column_int (stmt, 0);
1018   if (SQLITE_OK != sqlite3_reset (stmt))
1019     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1020                 "sqlite3_reset");
1021   stmt = plugin->selRepl;
1022   rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
1023   if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, rvalue))
1024   {
1025     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
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   {
1036     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
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;
1044   }
1045   execute_get (plugin, stmt, &repl_proc, &rc);
1046   if (GNUNET_YES == rc.have_uid)
1047   {
1048     if (SQLITE_OK != sqlite3_bind_int64 (plugin->updRepl, 1, rc.uid))
1049     {
1050       LOG_SQLITE (plugin,
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;
1058     }
1059     if (SQLITE_DONE != sqlite3_step (plugin->updRepl))
1060       LOG_SQLITE (plugin,
1061                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1062                   "sqlite3_step");
1063     if (SQLITE_OK != sqlite3_reset (plugin->updRepl))
1064       LOG_SQLITE (plugin,
1065                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1066                   "sqlite3_reset");
1067   }
1068 }
1069
1070
1071 /**
1072  * Get a random item that has expired or has low priority.
1073  * Call @a proc with all values ZERO or NULL if the datastore is empty.
1074  *
1075  * @param cls closure
1076  * @param proc function to call the value (once only).
1077  * @param proc_cls closure for @a proc
1078  */
1079 static void
1080 sqlite_plugin_get_expiration (void *cls, PluginDatumProcessor proc,
1081                               void *proc_cls)
1082 {
1083   struct Plugin *plugin = cls;
1084   sqlite3_stmt *stmt;
1085   struct GNUNET_TIME_Absolute now;
1086
1087   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
1088                    "Getting random block based on expiration and priority order.\n");
1089   now = GNUNET_TIME_absolute_get ();
1090   stmt = plugin->selExpi;
1091   if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, now.abs_value_us))
1092   {
1093     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
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;
1101   }
1102   execute_get (plugin, stmt, proc, proc_cls);
1103 }
1104
1105
1106 /**
1107  * Get all of the keys in the datastore.
1108  *
1109  * @param cls closure
1110  * @param proc function to call on each key
1111  * @param proc_cls closure for @a proc
1112  */
1113 static void
1114 sqlite_plugin_get_keys (void *cls,
1115                         PluginKeyProcessor proc,
1116                         void *proc_cls)
1117 {
1118   struct Plugin *plugin = cls;
1119   const struct GNUNET_HashCode *key;
1120   sqlite3_stmt *stmt;
1121   int ret;
1122
1123   GNUNET_assert (proc != NULL);
1124   if (sq_prepare (plugin->dbh, "SELECT hash FROM gn090", &stmt) != SQLITE_OK)
1125   {
1126     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1127                 "sqlite_prepare");
1128     proc (proc_cls, NULL, 0);
1129     return;
1130   }
1131   while (SQLITE_ROW == (ret = sqlite3_step (stmt)))
1132   {
1133     key = sqlite3_column_blob (stmt, 0);
1134     if (sizeof (struct GNUNET_HashCode) == sqlite3_column_bytes (stmt, 0))
1135       proc (proc_cls, key, 1);
1136     else
1137       GNUNET_break (0);
1138   }
1139   if (SQLITE_DONE != ret)
1140     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step");
1141   sqlite3_finalize (stmt);
1142   proc (proc_cls, NULL, 0);
1143 }
1144
1145
1146 /**
1147  * Drop database.
1148  *
1149  * @param cls our plugin context
1150  */
1151 static void
1152 sqlite_plugin_drop (void *cls)
1153 {
1154   struct Plugin *plugin = cls;
1155
1156   plugin->drop_on_shutdown = GNUNET_YES;
1157 }
1158
1159
1160 /**
1161  * Get an estimate of how much space the database is
1162  * currently using.
1163  *
1164  * @param cls the `struct Plugin`
1165  * @return the size of the database on disk (estimate)
1166  */
1167 static void
1168 sqlite_plugin_estimate_size (void *cls, unsigned long long *estimate)
1169 {
1170   struct Plugin *plugin = cls;
1171   sqlite3_stmt *stmt;
1172   uint64_t pages;
1173   uint64_t page_size;
1174
1175 #if ENULL_DEFINED
1176   char *e;
1177 #endif
1178
1179   if (NULL == estimate)
1180     return;
1181   if (SQLITE_VERSION_NUMBER < 3006000)
1182   {
1183     GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "datastore-sqlite",
1184                      _
1185                      ("sqlite version to old to determine size, assuming zero\n"));
1186     *estimate = 0;
1187     return;
1188   }
1189   CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "VACUUM", NULL, NULL, ENULL));
1190   CHECK (SQLITE_OK ==
1191          sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL,
1192                        NULL, ENULL));
1193   CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_count", &stmt));
1194   if (SQLITE_ROW == sqlite3_step (stmt))
1195     pages = sqlite3_column_int64 (stmt, 0);
1196   else
1197     pages = 0;
1198   sqlite3_finalize (stmt);
1199   CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_size", &stmt));
1200   CHECK (SQLITE_ROW == sqlite3_step (stmt));
1201   page_size = sqlite3_column_int64 (stmt, 0);
1202   sqlite3_finalize (stmt);
1203   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1204               _
1205               ("Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"),
1206               (unsigned long long) pages, (unsigned long long) page_size);
1207   *estimate = pages * page_size;
1208 }
1209
1210
1211 /**
1212  * Entry point for the plugin.
1213  *
1214  * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment *`
1215  * @return NULL on error, othrewise the plugin context
1216  */
1217 void *
1218 libgnunet_plugin_datastore_sqlite_init (void *cls)
1219 {
1220   static struct Plugin plugin;
1221   struct GNUNET_DATASTORE_PluginEnvironment *env = cls;
1222   struct GNUNET_DATASTORE_PluginFunctions *api;
1223
1224   if (plugin.env != NULL)
1225     return NULL;                /* can only initialize once! */
1226   memset (&plugin, 0, sizeof (struct Plugin));
1227   plugin.env = env;
1228   if (GNUNET_OK != database_setup (env->cfg, &plugin))
1229   {
1230     database_shutdown (&plugin);
1231     return NULL;
1232   }
1233   api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions);
1234   api->cls = &plugin;
1235   api->estimate_size = &sqlite_plugin_estimate_size;
1236   api->put = &sqlite_plugin_put;
1237   api->update = &sqlite_plugin_update;
1238   api->get_key = &sqlite_plugin_get_key;
1239   api->get_replication = &sqlite_plugin_get_replication;
1240   api->get_expiration = &sqlite_plugin_get_expiration;
1241   api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity;
1242   api->get_keys = &sqlite_plugin_get_keys;
1243   api->drop = &sqlite_plugin_drop;
1244   GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "sqlite",
1245                    _("Sqlite database running\n"));
1246   return api;
1247 }
1248
1249
1250 /**
1251  * Exit point from the plugin.
1252  *
1253  * @param cls the plugin context (as returned by "init")
1254  * @return always NULL
1255  */
1256 void *
1257 libgnunet_plugin_datastore_sqlite_done (void *cls)
1258 {
1259   char *fn;
1260   struct GNUNET_DATASTORE_PluginFunctions *api = cls;
1261   struct Plugin *plugin = api->cls;
1262
1263   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
1264                    "sqlite plugin is done\n");
1265   fn = NULL;
1266   if (plugin->drop_on_shutdown)
1267     fn = GNUNET_strdup (plugin->fn);
1268   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
1269                    "Shutting down database\n");
1270   database_shutdown (plugin);
1271   plugin->env = NULL;
1272   GNUNET_free (api);
1273   if (fn != NULL)
1274   {
1275     if (0 != UNLINK (fn))
1276       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
1277     GNUNET_free (fn);
1278   }
1279   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
1280                    "sqlite plugin is finished\n");
1281   return NULL;
1282 }
1283
1284 /* end of plugin_datastore_sqlite.c */