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