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