merge
[oweals/gnunet.git] / src / datastore / plugin_datastore_sqlite.c
1  /*
2   * This file is part of GNUnet
3   * Copyright (C) 2009, 2011, 2017 GNUnet e.V.
4   *
5   * GNUnet is free software: you can redistribute it and/or modify it
6   * under the terms of the GNU Affero General Public License as published
7   * by the Free Software Foundation, either version 3 of the License,
8   * or (at your 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   * Affero General Public License for more details.
14   *
15   * You should have received a copy of the GNU Affero General Public License
16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
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 "gnunet_sq_lib.h"
30 #include <sqlite3.h>
31
32
33 /**
34  * We allocate items on the stack at times.  To prevent a stack
35  * overflow, we impose a limit on the maximum size for the data per
36  * item.  64k should be enough.
37  */
38 #define MAX_ITEM_SIZE 65536
39
40 /**
41  * After how many ms "busy" should a DB operation fail for good?
42  * A low value makes sure that we are more responsive to requests
43  * (especially PUTs).  A high value guarantees a higher success
44  * rate (SELECTs in iterate can take several seconds despite LIMIT=1).
45  *
46  * The default value of 250ms should ensure that users do not experience
47  * huge latencies while at the same time allowing operations to succeed
48  * with reasonable probability.
49  */
50 #define BUSY_TIMEOUT_MS 250
51
52
53 /**
54  * Log an error message at log-level 'level' that indicates
55  * a failure of the command 'cmd' on file 'filename'
56  * with the message given by strerror(errno).
57  */
58 #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)
59
60
61 /**
62  * Log an error message at log-level 'level' that indicates
63  * a failure of the command 'cmd' on file 'filename'
64  * with the message given by strerror(errno).
65  */
66 #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)
67
68
69
70 /**
71  * Context for all functions in this plugin.
72  */
73 struct Plugin
74 {
75   /**
76    * Our execution environment.
77    */
78   struct GNUNET_DATASTORE_PluginEnvironment *env;
79
80   /**
81    * Database filename.
82    */
83   char *fn;
84
85   /**
86    * Native SQLite database handle.
87    */
88   sqlite3 *dbh;
89
90   /**
91    * Precompiled SQL for remove_key.
92    */
93   sqlite3_stmt *remove;
94
95   /**
96    * Precompiled SQL for deletion.
97    */
98   sqlite3_stmt *delRow;
99
100   /**
101    * Precompiled SQL for update.
102    */
103   sqlite3_stmt *update;
104
105   /**
106    * Get maximum repl value in database.
107    */
108   sqlite3_stmt *maxRepl;
109
110   /**
111    * Precompiled SQL for replication decrement.
112    */
113   sqlite3_stmt *updRepl;
114
115   /**
116    * Precompiled SQL for replication selection.
117    */
118   sqlite3_stmt *selRepl;
119
120   /**
121    * Precompiled SQL for expiration selection.
122    */
123   sqlite3_stmt *selExpi;
124
125   /**
126    * Precompiled SQL for expiration selection.
127    */
128   sqlite3_stmt *selZeroAnon;
129
130   /**
131    * Precompiled SQL for insertion.
132    */
133   sqlite3_stmt *insertContent;
134
135   /**
136    * Precompiled SQL for selection
137    */
138   sqlite3_stmt *get[8];
139
140   /**
141    * Should the database be dropped on shutdown?
142    */
143   int drop_on_shutdown;
144
145 };
146
147
148 /**
149  * @brief Prepare a SQL statement
150  *
151  * @param dbh handle to the database
152  * @param zSql SQL statement, UTF-8 encoded
153  * @param ppStmt set to the prepared statement
154  * @return 0 on success
155  */
156 static int
157 sq_prepare (sqlite3 *dbh,
158             const char *zSql,
159             sqlite3_stmt **ppStmt)
160 {
161   char *dummy;
162   int result;
163
164   result = sqlite3_prepare_v2 (dbh,
165                                zSql,
166                                strlen (zSql),
167                                ppStmt,
168                                (const char **) &dummy);
169   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
170                    "sqlite",
171                    "Prepared `%s' / %p: %d\n",
172                    zSql,
173                    *ppStmt,
174                    result);
175   return result;
176 }
177
178
179 /**
180  * Create our database indices.
181  *
182  * @param dbh handle to the database
183  */
184 static void
185 create_indices (sqlite3 * dbh)
186 {
187   /* create indices */
188   if (0 !=
189       (SQLITE_OK !=
190        sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_hash ON gn091 (hash)",
191                      NULL, NULL, NULL)) +
192       (SQLITE_OK !=
193        sqlite3_exec (dbh,
194                      "CREATE INDEX IF NOT EXISTS idx_anon_type ON gn091 (anonLevel ASC,type)",
195                      NULL, NULL, NULL)) +
196       (SQLITE_OK !=
197        sqlite3_exec (dbh,
198                      "CREATE INDEX IF NOT EXISTS idx_expire ON gn091 (expire ASC)",
199                      NULL, NULL, NULL)) +
200       (SQLITE_OK !=
201        sqlite3_exec (dbh,
202                      "CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn091 (repl,rvalue)",
203                      NULL, NULL, NULL)) )
204     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite",
205                      "Failed to create indices: %s\n", sqlite3_errmsg (dbh));
206 }
207
208
209 #if 0
210 #define CHECK(a) GNUNET_break(a)
211 #define ENULL NULL
212 #else
213 #define ENULL &e
214 #define ENULL_DEFINED 1
215 #define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
216 #endif
217
218
219 /**
220  * Initialize the database connections and associated
221  * data structures (create tables and indices
222  * as needed as well).
223  *
224  * @param cfg our configuration
225  * @param plugin the plugin context (state for this module)
226  * @return #GNUNET_OK on success
227  */
228 static int
229 database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg,
230                 struct Plugin *plugin)
231 {
232   sqlite3_stmt *stmt;
233   char *afsdir;
234 #if ENULL_DEFINED
235   char *e;
236 #endif
237
238   if (GNUNET_OK !=
239       GNUNET_CONFIGURATION_get_value_filename (cfg,
240                                                "datastore-sqlite",
241                                                "FILENAME",
242                                                &afsdir))
243   {
244     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
245                                "datastore-sqlite",
246                                "FILENAME");
247     return GNUNET_SYSERR;
248   }
249   if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
250   {
251     if (GNUNET_OK !=
252         GNUNET_DISK_directory_create_for_file (afsdir))
253     {
254       GNUNET_break (0);
255       GNUNET_free (afsdir);
256       return GNUNET_SYSERR;
257     }
258     /* database is new or got deleted, reset payload to zero! */
259     if (NULL != plugin->env->duc)
260       plugin->env->duc (plugin->env->cls,
261                         0);
262   }
263   /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
264   plugin->fn = afsdir;
265
266   /* Open database and precompile statements */
267   if (SQLITE_OK !=
268       sqlite3_open (plugin->fn, &plugin->dbh))
269   {
270     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite",
271                      _("Unable to initialize SQLite: %s.\n"),
272                      sqlite3_errmsg (plugin->dbh));
273     return GNUNET_SYSERR;
274   }
275   CHECK (SQLITE_OK ==
276          sqlite3_exec (plugin->dbh,
277                        "PRAGMA temp_store=MEMORY", NULL, NULL,
278                        ENULL));
279   CHECK (SQLITE_OK ==
280          sqlite3_exec (plugin->dbh,
281                        "PRAGMA synchronous=OFF", NULL, NULL,
282                        ENULL));
283   CHECK (SQLITE_OK ==
284          sqlite3_exec (plugin->dbh,
285                        "PRAGMA legacy_file_format=OFF", NULL, NULL,
286                        ENULL));
287   CHECK (SQLITE_OK ==
288          sqlite3_exec (plugin->dbh,
289                        "PRAGMA auto_vacuum=INCREMENTAL", NULL,
290                        NULL, ENULL));
291   CHECK (SQLITE_OK ==
292          sqlite3_exec (plugin->dbh,
293                        "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
294                        ENULL));
295   CHECK (SQLITE_OK ==
296          sqlite3_exec (plugin->dbh,
297                        "PRAGMA page_size=4096", NULL, NULL,
298                        ENULL));
299
300   CHECK (SQLITE_OK ==
301          sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS));
302
303
304   /* We have to do it here, because otherwise precompiling SQL might fail */
305   CHECK (SQLITE_OK ==
306          sq_prepare (plugin->dbh,
307                      "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn091'",
308                      &stmt));
309
310   /* FIXME: SQLite does not have unsigned integers! This is ok for the type column because
311    * we only test equality on it and can cast it to/from uint32_t. For repl, prio, and anonLevel
312    * we do math or inequality tests, so we can't handle the entire range of uint32_t.
313    * This will also cause problems for expiration times after 294247-01-10-04:00:54 UTC.
314    */
315   if ( (SQLITE_DONE ==
316         sqlite3_step (stmt)) &&
317        (SQLITE_OK !=
318         sqlite3_exec (plugin->dbh,
319                       "CREATE TABLE gn091 ("
320                       "  repl INT4 NOT NULL DEFAULT 0,"
321                       "  type INT4 NOT NULL DEFAULT 0,"
322                       "  prio INT4 NOT NULL DEFAULT 0,"
323                       "  anonLevel INT4 NOT NULL DEFAULT 0,"
324                       "  expire INT8 NOT NULL DEFAULT 0,"
325                       "  rvalue INT8 NOT NULL,"
326                       "  hash TEXT NOT NULL DEFAULT '',"
327                       "  vhash TEXT NOT NULL DEFAULT '',"
328                       "  value BLOB NOT NULL DEFAULT '')",
329                       NULL,
330                       NULL,
331                       NULL)) )
332   {
333     LOG_SQLITE (plugin,
334                 GNUNET_ERROR_TYPE_ERROR,
335                 "sqlite3_exec");
336     sqlite3_finalize (stmt);
337     return GNUNET_SYSERR;
338   }
339   sqlite3_finalize (stmt);
340   create_indices (plugin->dbh);
341
342 #define RESULT_COLUMNS "repl, type, prio, anonLevel, expire, hash, value, _ROWID_"
343   if ( (SQLITE_OK !=
344         sq_prepare (plugin->dbh,
345                     "UPDATE gn091 "
346                     "SET prio = prio + ?, "
347                     "repl = repl + ?, "
348                     "expire = MAX(expire, ?) "
349                     "WHERE hash = ? AND vhash = ?",
350                     &plugin->update)) ||
351        (SQLITE_OK !=
352         sq_prepare (plugin->dbh,
353                     "UPDATE gn091 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?",
354                     &plugin->updRepl)) ||
355        (SQLITE_OK !=
356         sq_prepare (plugin->dbh,
357                     "SELECT " RESULT_COLUMNS " FROM gn091 "
358                     "WHERE repl=?2 AND " " (rvalue>=?1 OR "
359                     "  NOT EXISTS (SELECT 1 FROM gn091 "
360                     "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) "
361                     "ORDER BY rvalue ASC LIMIT 1",
362                     &plugin->selRepl)) ||
363        (SQLITE_OK !=
364         sq_prepare (plugin->dbh,
365                     "SELECT MAX(repl) FROM gn091",
366                     &plugin->maxRepl)) ||
367        (SQLITE_OK !=
368         sq_prepare (plugin->dbh,
369                     "SELECT " RESULT_COLUMNS " FROM gn091 "
370                     "WHERE NOT EXISTS (SELECT 1 FROM gn091 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) "
371                     "ORDER BY expire ASC LIMIT 1",
372                     &plugin->selExpi)) ||
373        (SQLITE_OK !=
374         sq_prepare (plugin->dbh,
375                     "SELECT " RESULT_COLUMNS " FROM gn091 "
376                     "WHERE _ROWID_ >= ? AND "
377                     "anonLevel = 0 AND "
378                     "type = ? "
379                     "ORDER BY _ROWID_ ASC LIMIT 1",
380                     &plugin->selZeroAnon)) ||
381        (SQLITE_OK !=
382         sq_prepare (plugin->dbh,
383                     "INSERT INTO gn091 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) "
384                     "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
385                     &plugin->insertContent)) ||
386        (SQLITE_OK !=
387         sq_prepare (plugin->dbh,
388                     "SELECT " RESULT_COLUMNS " FROM gn091 "
389                     "WHERE _ROWID_ >= ?1 "
390                     "ORDER BY _ROWID_ ASC LIMIT 1",
391                     &plugin->get[0])) ||
392        (SQLITE_OK !=
393         sq_prepare (plugin->dbh,
394                     "SELECT " RESULT_COLUMNS " FROM gn091 "
395                     "WHERE _ROWID_ >= ?1 AND "
396                     "type = ?4 "
397                     "ORDER BY _ROWID_ ASC LIMIT 1",
398                     &plugin->get[1])) ||
399        (SQLITE_OK !=
400         sq_prepare (plugin->dbh,
401                     "SELECT " RESULT_COLUMNS " FROM gn091 "
402                     "WHERE _ROWID_ >= ?1 AND "
403                     "hash = ?3 "
404                     "ORDER BY _ROWID_ ASC LIMIT 1",
405                     &plugin->get[2])) ||
406        (SQLITE_OK !=
407         sq_prepare (plugin->dbh,
408                     "SELECT " RESULT_COLUMNS " FROM gn091 "
409                     "WHERE _ROWID_ >= ?1 AND "
410                     "hash = ?3 AND "
411                     "type = ?4 "
412                     "ORDER BY _ROWID_ ASC LIMIT 1",
413                     &plugin->get[3])) ||
414        (SQLITE_OK !=
415         sq_prepare (plugin->dbh,
416                     "SELECT " RESULT_COLUMNS " FROM gn091 "
417                     "WHERE _ROWID_ >= ?1 AND "
418                     "rvalue >= ?2 "
419                     "ORDER BY _ROWID_ ASC LIMIT 1",
420                     &plugin->get[4])) ||
421        (SQLITE_OK !=
422         sq_prepare (plugin->dbh,
423                     "SELECT " RESULT_COLUMNS " FROM gn091 "
424                     "WHERE _ROWID_ >= ?1 AND "
425                     "rvalue >= ?2 AND "
426                     "type = ?4 "
427                     "ORDER BY _ROWID_ ASC LIMIT 1",
428                     &plugin->get[5])) ||
429        (SQLITE_OK !=
430         sq_prepare (plugin->dbh,
431                     "SELECT " RESULT_COLUMNS " FROM gn091 "
432                     "WHERE _ROWID_ >= ?1 AND "
433                     "rvalue >= ?2 AND "
434                     "hash = ?3 "
435                     "ORDER BY _ROWID_ ASC LIMIT 1",
436                     &plugin->get[6])) ||
437        (SQLITE_OK !=
438         sq_prepare (plugin->dbh,
439                     "SELECT " RESULT_COLUMNS " FROM gn091 "
440                     "WHERE _ROWID_ >= ?1 AND "
441                     "rvalue >= ?2 AND "
442                     "hash = ?3 AND "
443                     "type = ?4 "
444                     "ORDER BY _ROWID_ ASC LIMIT 1",
445                     &plugin->get[7])) ||
446        (SQLITE_OK !=
447         sq_prepare (plugin->dbh,
448                     "DELETE FROM gn091 WHERE _ROWID_ = ?",
449                     &plugin->delRow)) ||
450        (SQLITE_OK !=
451         sq_prepare (plugin->dbh,
452                     "DELETE FROM gn091 "
453                     "WHERE hash = ? AND "
454                     "value = ? ",
455                     &plugin->remove)) ||
456        false)
457   {
458     LOG_SQLITE (plugin,
459                 GNUNET_ERROR_TYPE_ERROR,
460                 "precompiling");
461     return GNUNET_SYSERR;
462   }
463   return GNUNET_OK;
464 }
465
466
467 /**
468  * Shutdown database connection and associate data
469  * structures.
470  *
471  * @param plugin the plugin context (state for this module)
472  */
473 static void
474 database_shutdown (struct Plugin *plugin)
475 {
476   int result;
477 #if SQLITE_VERSION_NUMBER >= 3007000
478   sqlite3_stmt *stmt;
479 #endif
480
481   if (NULL != plugin->remove)
482     sqlite3_finalize (plugin->remove);
483   if (NULL != plugin->delRow)
484     sqlite3_finalize (plugin->delRow);
485   if (NULL != plugin->update)
486     sqlite3_finalize (plugin->update);
487   if (NULL != plugin->updRepl)
488     sqlite3_finalize (plugin->updRepl);
489   if (NULL != plugin->selRepl)
490     sqlite3_finalize (plugin->selRepl);
491   if (NULL != plugin->maxRepl)
492     sqlite3_finalize (plugin->maxRepl);
493   if (NULL != plugin->selExpi)
494     sqlite3_finalize (plugin->selExpi);
495   if (NULL != plugin->selZeroAnon)
496     sqlite3_finalize (plugin->selZeroAnon);
497   if (NULL != plugin->insertContent)
498     sqlite3_finalize (plugin->insertContent);
499   for (int i = 0; i < 8; ++i)
500     if (NULL != plugin->get[i])
501       sqlite3_finalize (plugin->get[i]);
502   result = sqlite3_close (plugin->dbh);
503 #if SQLITE_VERSION_NUMBER >= 3007000
504   if (result == SQLITE_BUSY)
505   {
506     GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
507                      "sqlite",
508                      _("Tried to close sqlite without finalizing all prepared statements.\n"));
509     stmt = sqlite3_next_stmt (plugin->dbh,
510                               NULL);
511     while (NULL != stmt)
512     {
513       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
514                        "sqlite",
515                        "Closing statement %p\n",
516                        stmt);
517       result = sqlite3_finalize (stmt);
518       if (result != SQLITE_OK)
519         GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
520                          "sqlite",
521                          "Failed to close statement %p: %d\n",
522                          stmt,
523                          result);
524       stmt = sqlite3_next_stmt (plugin->dbh,
525                                 NULL);
526     }
527     result = sqlite3_close (plugin->dbh);
528   }
529 #endif
530   if (SQLITE_OK != result)
531     LOG_SQLITE (plugin,
532                 GNUNET_ERROR_TYPE_ERROR,
533                 "sqlite3_close");
534   GNUNET_free_non_null (plugin->fn);
535 }
536
537
538 /**
539  * Delete the database entry with the given
540  * row identifier.
541  *
542  * @param plugin the plugin context (state for this module)
543  * @param rid the ID of the row to delete
544  */
545 static int
546 delete_by_rowid (struct Plugin *plugin,
547                  uint64_t rid)
548 {
549   struct GNUNET_SQ_QueryParam params[] = {
550     GNUNET_SQ_query_param_uint64 (&rid),
551     GNUNET_SQ_query_param_end
552   };
553
554   if (GNUNET_OK !=
555       GNUNET_SQ_bind (plugin->delRow,
556                       params))
557     return GNUNET_SYSERR;
558   if (SQLITE_DONE != sqlite3_step (plugin->delRow))
559   {
560     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
561                 "sqlite3_step");
562     GNUNET_SQ_reset (plugin->dbh,
563                      plugin->delRow);
564     return GNUNET_SYSERR;
565   }
566   GNUNET_SQ_reset (plugin->dbh,
567                    plugin->delRow);
568   return GNUNET_OK;
569 }
570
571
572 /**
573  * Store an item in the datastore.
574  *
575  * @param cls closure
576  * @param key key for the item
577  * @param absent true if the key was not found in the bloom filter
578  * @param size number of bytes in @a data
579  * @param data content stored
580  * @param type type of the content
581  * @param priority priority of the content
582  * @param anonymity anonymity-level for the content
583  * @param replication replication-level for the content
584  * @param expiration expiration time for the content
585  * @param cont continuation called with success or failure status
586  * @param cont_cls continuation closure
587  */
588 static void
589 sqlite_plugin_put (void *cls,
590                    const struct GNUNET_HashCode *key,
591                    bool absent,
592                    uint32_t size,
593                    const void *data,
594                    enum GNUNET_BLOCK_Type type,
595                    uint32_t priority,
596                    uint32_t anonymity,
597                    uint32_t replication,
598                    struct GNUNET_TIME_Absolute expiration,
599                    PluginPutCont cont,
600                    void *cont_cls)
601 {
602   struct Plugin *plugin = cls;
603   struct GNUNET_HashCode vhash;
604   char *msg = NULL;
605
606   GNUNET_CRYPTO_hash (data,
607                       size,
608                       &vhash);
609
610   if (!absent)
611   {
612     struct GNUNET_SQ_QueryParam params[] = {
613       GNUNET_SQ_query_param_uint32 (&priority),
614       GNUNET_SQ_query_param_uint32 (&replication),
615       GNUNET_SQ_query_param_absolute_time (&expiration),
616       GNUNET_SQ_query_param_auto_from_type (key),
617       GNUNET_SQ_query_param_auto_from_type (&vhash),
618       GNUNET_SQ_query_param_end
619     };
620
621     if (GNUNET_OK !=
622         GNUNET_SQ_bind (plugin->update,
623                         params))
624     {
625       cont (cont_cls,
626             key,
627             size,
628             GNUNET_SYSERR,
629             _("sqlite bind failure"));
630       return;
631     }
632     if (SQLITE_DONE != sqlite3_step (plugin->update))
633     {
634       LOG_SQLITE_MSG (plugin, &msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
635                       "sqlite3_step");
636       cont (cont_cls,
637             key,
638             size,
639             GNUNET_SYSERR,
640             msg);
641       GNUNET_free_non_null (msg);
642       return;
643     }
644     int changes = sqlite3_changes (plugin->dbh);
645     GNUNET_SQ_reset (plugin->dbh,
646                      plugin->update);
647     if (0 != changes)
648     {
649       cont (cont_cls,
650             key,
651             size,
652             GNUNET_NO,
653             NULL);
654       return;
655     }
656   }
657
658   uint64_t rvalue;
659   uint32_t type32 = (uint32_t) type;
660   struct GNUNET_SQ_QueryParam params[] = {
661     GNUNET_SQ_query_param_uint32 (&replication),
662     GNUNET_SQ_query_param_uint32 (&type32),
663     GNUNET_SQ_query_param_uint32 (&priority),
664     GNUNET_SQ_query_param_uint32 (&anonymity),
665     GNUNET_SQ_query_param_absolute_time (&expiration),
666     GNUNET_SQ_query_param_uint64 (&rvalue),
667     GNUNET_SQ_query_param_auto_from_type (key),
668     GNUNET_SQ_query_param_auto_from_type (&vhash),
669     GNUNET_SQ_query_param_fixed_size (data, size),
670     GNUNET_SQ_query_param_end
671   };
672   int n;
673   int ret;
674   sqlite3_stmt *stmt;
675
676   if (size > MAX_ITEM_SIZE)
677   {
678     cont (cont_cls, key, size, GNUNET_SYSERR, _("Data too large"));
679     return;
680   }
681   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
682                    "Storing in database block with type %u/key `%s'/priority %u/expiration in %s (%s).\n",
683                    type,
684                    GNUNET_h2s (key),
685                    priority,
686                    GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration),
687                                                            GNUNET_YES),
688                    GNUNET_STRINGS_absolute_time_to_string (expiration));
689   stmt = plugin->insertContent;
690   rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
691   if (GNUNET_OK !=
692       GNUNET_SQ_bind (stmt,
693                       params))
694   {
695     cont (cont_cls, key, size, GNUNET_SYSERR, NULL);
696     return;
697   }
698   n = sqlite3_step (stmt);
699   switch (n)
700   {
701   case SQLITE_DONE:
702     if (NULL != plugin->env->duc)
703       plugin->env->duc (plugin->env->cls,
704                         size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
705     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
706                      "Stored new entry (%u bytes)\n",
707                      size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
708     ret = GNUNET_OK;
709     break;
710   case SQLITE_BUSY:
711     GNUNET_break (0);
712     LOG_SQLITE_MSG (plugin,
713                     &msg,
714                     GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
715                     "sqlite3_step");
716     ret = GNUNET_SYSERR;
717     break;
718   default:
719     LOG_SQLITE_MSG (plugin,
720                     &msg,
721                     GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
722                     "sqlite3_step");
723     GNUNET_SQ_reset (plugin->dbh,
724                      stmt);
725     database_shutdown (plugin);
726     database_setup (plugin->env->cfg, plugin);
727     cont (cont_cls, key, size, GNUNET_SYSERR, msg);
728     GNUNET_free_non_null(msg);
729     return;
730   }
731   GNUNET_SQ_reset (plugin->dbh,
732                    stmt);
733   cont (cont_cls, key, size, ret, msg);
734   GNUNET_free_non_null(msg);
735 }
736
737
738 /**
739  * Execute statement that gets a row and call the callback
740  * with the result.  Resets the statement afterwards.
741  *
742  * @param plugin the plugin
743  * @param stmt the statement
744  * @param proc processor to call
745  * @param proc_cls closure for @a proc
746  */
747 static void
748 execute_get (struct Plugin *plugin,
749              sqlite3_stmt *stmt,
750              PluginDatumProcessor proc,
751              void *proc_cls)
752 {
753   int n;
754   struct GNUNET_TIME_Absolute expiration;
755   uint32_t replication;
756   uint32_t type;
757   uint32_t priority;
758   uint32_t anonymity;
759   uint64_t rowid;
760   void *value;
761   size_t value_size;
762   struct GNUNET_HashCode key;
763   int ret;
764   struct GNUNET_SQ_ResultSpec rs[] = {
765     GNUNET_SQ_result_spec_uint32 (&replication),
766     GNUNET_SQ_result_spec_uint32 (&type),
767     GNUNET_SQ_result_spec_uint32 (&priority),
768     GNUNET_SQ_result_spec_uint32 (&anonymity),
769     GNUNET_SQ_result_spec_absolute_time (&expiration),
770     GNUNET_SQ_result_spec_auto_from_type (&key),
771     GNUNET_SQ_result_spec_variable_size (&value,
772                                          &value_size),
773     GNUNET_SQ_result_spec_uint64 (&rowid),
774     GNUNET_SQ_result_spec_end
775   };
776
777   n = sqlite3_step (stmt);
778   switch (n)
779   {
780   case SQLITE_ROW:
781     if (GNUNET_OK !=
782         GNUNET_SQ_extract_result (stmt,
783                                   rs))
784     {
785       GNUNET_break (0);
786       break;
787     }
788     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
789                      "sqlite",
790                      "Found reply in database with expiration %s\n",
791                      GNUNET_STRINGS_absolute_time_to_string (expiration));
792     ret = proc (proc_cls,
793                 &key,
794                 value_size,
795                 value,
796                 type,
797                 priority,
798                 anonymity,
799                 replication,
800                 expiration,
801                 rowid);
802     GNUNET_SQ_cleanup_result (rs);
803     GNUNET_SQ_reset (plugin->dbh,
804                      stmt);
805     if ( (GNUNET_NO == ret) &&
806          (GNUNET_OK == delete_by_rowid (plugin,
807                                         rowid)) &&
808          (NULL != plugin->env->duc) )
809       plugin->env->duc (plugin->env->cls,
810                         -(value_size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
811     return;
812   case SQLITE_DONE:
813     /* database must be empty */
814     break;
815   case SQLITE_BUSY:
816   case SQLITE_ERROR:
817   case SQLITE_MISUSE:
818   default:
819     LOG_SQLITE (plugin,
820                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
821                 "sqlite3_step");
822     if (SQLITE_OK !=
823         sqlite3_reset (stmt))
824       LOG_SQLITE (plugin,
825                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
826                   "sqlite3_reset");
827     GNUNET_break (0);
828     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
829     database_shutdown (plugin);
830     database_setup (plugin->env->cfg,
831                     plugin);
832     return;
833   }
834   GNUNET_SQ_reset (plugin->dbh,
835                    stmt);
836   proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
837 }
838
839
840 /**
841  * Select a subset of the items in the datastore and call
842  * the given processor for the item.
843  *
844  * @param cls our plugin context
845  * @param next_uid return the result with lowest uid >= next_uid
846  * @param type entries of which type should be considered?
847  *        Must not be zero (ANY).
848  * @param proc function to call on the matching value;
849  *        will be called with NULL if no value matches
850  * @param proc_cls closure for @a proc
851  */
852 static void
853 sqlite_plugin_get_zero_anonymity (void *cls,
854                                   uint64_t next_uid,
855                                   enum GNUNET_BLOCK_Type type,
856                                   PluginDatumProcessor proc,
857                                   void *proc_cls)
858 {
859   struct Plugin *plugin = cls;
860   uint32_t type32 = type;
861   struct GNUNET_SQ_QueryParam params[] = {
862     GNUNET_SQ_query_param_uint64 (&next_uid),
863     GNUNET_SQ_query_param_uint32 (&type32),
864     GNUNET_SQ_query_param_end
865   };
866
867   GNUNET_assert (type != GNUNET_BLOCK_TYPE_ANY);
868   if (GNUNET_OK !=
869       GNUNET_SQ_bind (plugin->selZeroAnon,
870                       params))
871   {
872     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
873     return;
874   }
875   execute_get (plugin, plugin->selZeroAnon, proc, proc_cls);
876 }
877
878
879 /**
880  * Get results for a particular key in the datastore.
881  *
882  * @param cls closure
883  * @param next_uid return the result with lowest uid >= next_uid
884  * @param random if true, return a random result instead of using next_uid
885  * @param key maybe NULL (to match all entries)
886  * @param type entries of which type are relevant?
887  *     Use 0 for any type.
888  * @param proc function to call on the matching value;
889  *        will be called with NULL if nothing matches
890  * @param proc_cls closure for @a proc
891  */
892 static void
893 sqlite_plugin_get_key (void *cls,
894                        uint64_t next_uid,
895                        bool random,
896                        const struct GNUNET_HashCode *key,
897                        enum GNUNET_BLOCK_Type type,
898                        PluginDatumProcessor proc,
899                        void *proc_cls)
900 {
901   struct Plugin *plugin = cls;
902   uint64_t rvalue;
903   int use_rvalue = random;
904   uint32_t type32 = (uint32_t) type;
905   int use_type = GNUNET_BLOCK_TYPE_ANY != type;
906   int use_key = NULL != key;
907   sqlite3_stmt *stmt = plugin->get[use_rvalue * 4 + use_key * 2 + use_type];
908   struct GNUNET_SQ_QueryParam params[] = {
909     GNUNET_SQ_query_param_uint64 (&next_uid),
910     GNUNET_SQ_query_param_uint64 (&rvalue),
911     GNUNET_SQ_query_param_auto_from_type (key),
912     GNUNET_SQ_query_param_uint32 (&type32),
913     GNUNET_SQ_query_param_end
914   };
915
916   /* SQLite doesn't like it when you try to bind a parameter greater than the
917    * last numbered parameter, but unused parameters in the middle are OK.
918    */
919   if (! use_type)
920   {
921     params[3] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
922     if (! use_key)
923     {
924       params[2] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
925       if (! use_rvalue)
926         params[1] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
927     }
928   }
929   if (random)
930   {
931     rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
932                                        UINT64_MAX);
933     next_uid = 0;
934   }
935   else
936     rvalue = 0;
937
938   if (GNUNET_OK !=
939       GNUNET_SQ_bind (stmt,
940                       params))
941   {
942     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
943     return;
944   }
945   execute_get (plugin,
946                stmt,
947                proc,
948                proc_cls);
949 }
950
951
952 /**
953  * Context for #repl_proc() function.
954  */
955 struct ReplCtx
956 {
957
958   /**
959    * Function to call for the result (or the NULL).
960    */
961   PluginDatumProcessor proc;
962
963   /**
964    * Closure for @e proc.
965    */
966   void *proc_cls;
967
968   /**
969    * UID to use.
970    */
971   uint64_t uid;
972
973   /**
974    * Yes if UID was set.
975    */
976   int have_uid;
977 };
978
979
980 /**
981  * Wrapper for the processor for #sqlite_plugin_get_replication().
982  * Decrements the replication counter and calls the original
983  * processor.
984  *
985  * @param cls closure
986  * @param key key for the content
987  * @param size number of bytes in @a data
988  * @param data content stored
989  * @param type type of the content
990  * @param priority priority of the content
991  * @param anonymity anonymity-level for the content
992  * @param replication replication-level for the content
993  * @param expiration expiration time for the content
994  * @param uid unique identifier for the datum;
995  *        maybe 0 if no unique identifier is available
996  * @return #GNUNET_OK for normal return,
997  *         #GNUNET_NO to delete the item
998  */
999 static int
1000 repl_proc (void *cls,
1001            const struct GNUNET_HashCode *key,
1002            uint32_t size,
1003            const void *data,
1004            enum GNUNET_BLOCK_Type type,
1005            uint32_t priority,
1006            uint32_t anonymity,
1007            uint32_t replication,
1008            struct GNUNET_TIME_Absolute expiration,
1009            uint64_t uid)
1010 {
1011   struct ReplCtx *rc = cls;
1012   int ret;
1013
1014   if (GNUNET_SYSERR == rc->have_uid)
1015     rc->have_uid = GNUNET_NO;
1016   ret = rc->proc (rc->proc_cls,
1017                   key,
1018                   size,
1019                   data,
1020                   type,
1021                   priority,
1022                   anonymity,
1023                   replication,
1024                   expiration,
1025                   uid);
1026   if (NULL != key)
1027   {
1028     rc->uid = uid;
1029     rc->have_uid = GNUNET_YES;
1030   }
1031   return ret;
1032 }
1033
1034
1035 /**
1036  * Get a random item for replication.  Returns a single random item
1037  * from those with the highest replication counters.  The item's
1038  * replication counter is decremented by one IF it was positive before.
1039  * Call @a proc with all values ZERO or NULL if the datastore is empty.
1040  *
1041  * @param cls closure
1042  * @param proc function to call the value (once only).
1043  * @param proc_cls closure for @a proc
1044  */
1045 static void
1046 sqlite_plugin_get_replication (void *cls,
1047                                PluginDatumProcessor proc,
1048                                void *proc_cls)
1049 {
1050   struct Plugin *plugin = cls;
1051   struct ReplCtx rc;
1052   uint64_t rvalue;
1053   uint32_t repl;
1054   struct GNUNET_SQ_QueryParam params_sel_repl[] = {
1055     GNUNET_SQ_query_param_uint64 (&rvalue),
1056     GNUNET_SQ_query_param_uint32 (&repl),
1057     GNUNET_SQ_query_param_end
1058   };
1059   struct GNUNET_SQ_QueryParam params_upd_repl[] = {
1060     GNUNET_SQ_query_param_uint64 (&rc.uid),
1061     GNUNET_SQ_query_param_end
1062   };
1063
1064   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1065                    "datastore-sqlite",
1066                    "Getting random block based on replication order.\n");
1067   if (SQLITE_ROW !=
1068       sqlite3_step (plugin->maxRepl))
1069   {
1070     GNUNET_SQ_reset (plugin->dbh,
1071                      plugin->maxRepl);
1072     /* DB empty */
1073     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1074     return;
1075   }
1076   repl = sqlite3_column_int (plugin->maxRepl,
1077                              0);
1078   GNUNET_SQ_reset (plugin->dbh,
1079                    plugin->maxRepl);
1080   rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
1081                                      UINT64_MAX);
1082   if (GNUNET_OK !=
1083       GNUNET_SQ_bind (plugin->selRepl,
1084                       params_sel_repl))
1085   {
1086     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1087     return;
1088   }
1089   rc.have_uid = GNUNET_SYSERR;
1090   rc.proc = proc;
1091   rc.proc_cls = proc_cls;
1092   execute_get (plugin,
1093                plugin->selRepl,
1094                &repl_proc,
1095                &rc);
1096   if (GNUNET_YES == rc.have_uid)
1097   {
1098     if (GNUNET_OK !=
1099         GNUNET_SQ_bind (plugin->updRepl,
1100                         params_upd_repl))
1101     {
1102       proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1103       return;
1104     }
1105     if (SQLITE_DONE !=
1106         sqlite3_step (plugin->updRepl))
1107       LOG_SQLITE (plugin,
1108                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1109                   "sqlite3_step");
1110     GNUNET_SQ_reset (plugin->dbh,
1111                      plugin->updRepl);
1112   }
1113   if (GNUNET_SYSERR == rc.have_uid)
1114   {
1115     /* proc was not called at all so far, do it now. */
1116     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1117   }
1118 }
1119
1120
1121 /**
1122  * Get a random item that has expired or has low priority.
1123  * Call @a proc with all values ZERO or NULL if the datastore is empty.
1124  *
1125  * @param cls closure
1126  * @param proc function to call the value (once only).
1127  * @param proc_cls closure for @a proc
1128  */
1129 static void
1130 sqlite_plugin_get_expiration (void *cls, PluginDatumProcessor proc,
1131                               void *proc_cls)
1132 {
1133   struct Plugin *plugin = cls;
1134   sqlite3_stmt *stmt;
1135   struct GNUNET_TIME_Absolute now;
1136   struct GNUNET_SQ_QueryParam params[] = {
1137     GNUNET_SQ_query_param_absolute_time (&now),
1138     GNUNET_SQ_query_param_end
1139   };
1140
1141   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1142                    "sqlite",
1143                    "Getting random block based on expiration and priority order.\n");
1144   now = GNUNET_TIME_absolute_get ();
1145   stmt = plugin->selExpi;
1146   if (GNUNET_OK !=
1147       GNUNET_SQ_bind (stmt,
1148                       params))
1149   {
1150     proc (proc_cls, NULL, 0, NULL, 0, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
1151     return;
1152   }
1153   execute_get (plugin, stmt, proc, proc_cls);
1154 }
1155
1156
1157 /**
1158  * Get all of the keys in the datastore.
1159  *
1160  * @param cls closure
1161  * @param proc function to call on each key
1162  * @param proc_cls closure for @a proc
1163  */
1164 static void
1165 sqlite_plugin_get_keys (void *cls,
1166                         PluginKeyProcessor proc,
1167                         void *proc_cls)
1168 {
1169   struct Plugin *plugin = cls;
1170   struct GNUNET_HashCode key;
1171   struct GNUNET_SQ_ResultSpec results[] = {
1172     GNUNET_SQ_result_spec_auto_from_type (&key),
1173     GNUNET_SQ_result_spec_end
1174   };
1175   sqlite3_stmt *stmt;
1176   int ret;
1177
1178   GNUNET_assert (NULL != proc);
1179   if (SQLITE_OK !=
1180       sq_prepare (plugin->dbh,
1181                   "SELECT hash FROM gn091",
1182                   &stmt))
1183   {
1184     LOG_SQLITE (plugin,
1185                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1186                 "sqlite_prepare");
1187     proc (proc_cls,
1188           NULL,
1189           0);
1190     return;
1191   }
1192   while (SQLITE_ROW == (ret = sqlite3_step (stmt)))
1193   {
1194     if (GNUNET_OK ==
1195         GNUNET_SQ_extract_result (stmt,
1196                                   results))
1197       proc (proc_cls,
1198             &key,
1199             1);
1200     else
1201       GNUNET_break (0);
1202   }
1203   if (SQLITE_DONE != ret)
1204     LOG_SQLITE (plugin,
1205                 GNUNET_ERROR_TYPE_ERROR,
1206                 "sqlite_step");
1207   sqlite3_finalize (stmt);
1208   proc (proc_cls,
1209         NULL,
1210         0);
1211 }
1212
1213
1214 /**
1215  * Drop database.
1216  *
1217  * @param cls our plugin context
1218  */
1219 static void
1220 sqlite_plugin_drop (void *cls)
1221 {
1222   struct Plugin *plugin = cls;
1223
1224   plugin->drop_on_shutdown = GNUNET_YES;
1225 }
1226
1227
1228 /**
1229  * Remove a particular key in the datastore.
1230  *
1231  * @param cls closure
1232  * @param key key for the content
1233  * @param size number of bytes in data
1234  * @param data content stored
1235  * @param cont continuation called with success or failure status
1236  * @param cont_cls continuation closure for @a cont
1237  */
1238 static void
1239 sqlite_plugin_remove_key (void *cls,
1240                           const struct GNUNET_HashCode *key,
1241                           uint32_t size,
1242                           const void *data,
1243                           PluginRemoveCont cont,
1244                           void *cont_cls)
1245 {
1246   struct Plugin *plugin = cls;
1247   struct GNUNET_SQ_QueryParam params[] = {
1248     GNUNET_SQ_query_param_auto_from_type (key),
1249     GNUNET_SQ_query_param_fixed_size (data, size),
1250     GNUNET_SQ_query_param_end
1251   };
1252
1253   if (GNUNET_OK !=
1254       GNUNET_SQ_bind (plugin->remove,
1255                       params))
1256   {
1257     cont (cont_cls,
1258           key,
1259           size,
1260           GNUNET_SYSERR,
1261           "bind failed");
1262     return;
1263   }
1264   if (SQLITE_DONE != sqlite3_step (plugin->remove))
1265   {
1266     LOG_SQLITE (plugin,
1267                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1268                 "sqlite3_step");
1269     GNUNET_SQ_reset (plugin->dbh,
1270                      plugin->remove);
1271     cont (cont_cls,
1272           key,
1273           size,
1274           GNUNET_SYSERR,
1275           "sqlite3_step failed");
1276     return;
1277   }
1278   int changes = sqlite3_changes (plugin->dbh);
1279   GNUNET_SQ_reset (plugin->dbh,
1280                    plugin->remove);
1281   if (0 == changes)
1282   {
1283     cont (cont_cls,
1284           key,
1285           size,
1286           GNUNET_NO,
1287           NULL);
1288     return;
1289   }
1290   if (NULL != plugin->env->duc)
1291     plugin->env->duc (plugin->env->cls,
1292                       -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD));
1293   cont (cont_cls,
1294         key,
1295         size,
1296         GNUNET_OK,
1297         NULL);
1298 }
1299
1300
1301 /**
1302  * Get an estimate of how much space the database is
1303  * currently using.
1304  *
1305  * @param cls the `struct Plugin`
1306  * @return the size of the database on disk (estimate)
1307  */
1308 static void
1309 sqlite_plugin_estimate_size (void *cls,
1310                              unsigned long long *estimate)
1311 {
1312   struct Plugin *plugin = cls;
1313   sqlite3_stmt *stmt;
1314   uint64_t pages;
1315   uint64_t page_size;
1316
1317 #if ENULL_DEFINED
1318   char *e;
1319 #endif
1320
1321   if (NULL == estimate)
1322     return;
1323   if (SQLITE_VERSION_NUMBER < 3006000)
1324   {
1325     GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
1326                      "datastore-sqlite",
1327                      _("sqlite version to old to determine size, assuming zero\n"));
1328     *estimate = 0;
1329     return;
1330   }
1331   CHECK (SQLITE_OK ==
1332          sqlite3_exec (plugin->dbh,
1333                        "VACUUM",
1334                        NULL,
1335                        NULL,
1336                        ENULL));
1337   CHECK (SQLITE_OK ==
1338          sqlite3_exec (plugin->dbh,
1339                        "PRAGMA auto_vacuum=INCREMENTAL",
1340                        NULL,
1341                        NULL, ENULL));
1342   CHECK (SQLITE_OK ==
1343          sq_prepare (plugin->dbh,
1344                      "PRAGMA page_count",
1345                      &stmt));
1346   if (SQLITE_ROW == sqlite3_step (stmt))
1347     pages = sqlite3_column_int64 (stmt,
1348                                   0);
1349   else
1350     pages = 0;
1351   sqlite3_finalize (stmt);
1352   CHECK (SQLITE_OK ==
1353          sq_prepare (plugin->dbh,
1354                      "PRAGMA page_size",
1355                      &stmt));
1356   CHECK (SQLITE_ROW ==
1357          sqlite3_step (stmt));
1358   page_size = sqlite3_column_int64 (stmt, 0);
1359   sqlite3_finalize (stmt);
1360   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1361               _("Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"),
1362               (unsigned long long) pages,
1363               (unsigned long long) page_size);
1364   *estimate = pages * page_size;
1365 }
1366
1367
1368 /**
1369  * Entry point for the plugin.
1370  *
1371  * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment *`
1372  * @return NULL on error, othrewise the plugin context
1373  */
1374 void *
1375 libgnunet_plugin_datastore_sqlite_init (void *cls)
1376 {
1377   static struct Plugin plugin;
1378   struct GNUNET_DATASTORE_PluginEnvironment *env = cls;
1379   struct GNUNET_DATASTORE_PluginFunctions *api;
1380
1381   if (NULL != plugin.env)
1382     return NULL;                /* can only initialize once! */
1383   memset (&plugin,
1384           0,
1385           sizeof (struct Plugin));
1386   plugin.env = env;
1387   if (GNUNET_OK != database_setup (env->cfg, &plugin))
1388   {
1389     database_shutdown (&plugin);
1390     return NULL;
1391   }
1392   api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions);
1393   api->cls = &plugin;
1394   api->estimate_size = &sqlite_plugin_estimate_size;
1395   api->put = &sqlite_plugin_put;
1396   api->get_key = &sqlite_plugin_get_key;
1397   api->get_replication = &sqlite_plugin_get_replication;
1398   api->get_expiration = &sqlite_plugin_get_expiration;
1399   api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity;
1400   api->get_keys = &sqlite_plugin_get_keys;
1401   api->drop = &sqlite_plugin_drop;
1402   api->remove_key = &sqlite_plugin_remove_key;
1403   GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
1404                    "sqlite",
1405                    _("Sqlite database running\n"));
1406   return api;
1407 }
1408
1409
1410 /**
1411  * Exit point from the plugin.
1412  *
1413  * @param cls the plugin context (as returned by "init")
1414  * @return always NULL
1415  */
1416 void *
1417 libgnunet_plugin_datastore_sqlite_done (void *cls)
1418 {
1419   char *fn;
1420   struct GNUNET_DATASTORE_PluginFunctions *api = cls;
1421   struct Plugin *plugin = api->cls;
1422
1423   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1424                    "sqlite",
1425                    "sqlite plugin is done\n");
1426   fn = NULL;
1427   if (plugin->drop_on_shutdown)
1428     fn = GNUNET_strdup (plugin->fn);
1429   database_shutdown (plugin);
1430   plugin->env = NULL;
1431   GNUNET_free (api);
1432   if (NULL != fn)
1433   {
1434     if (0 != UNLINK (fn))
1435       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1436                                 "unlink",
1437                                 fn);
1438     GNUNET_free (fn);
1439   }
1440   return NULL;
1441 }
1442
1443 /* end of plugin_datastore_sqlite.c */