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