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