TUN_IFNAME is the tunnel interface, not EXIT_IFNAME
[oweals/gnunet.git] / src / psycstore / plugin_psycstore_sqlite.c
1 /*
2  * This file is part of GNUnet
3  * Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 /**
22  * @file psycstore/plugin_psycstore_sqlite.c
23  * @brief sqlite-based psycstore backend
24  * @author Gabor X Toth
25  * @author Christian Grothoff
26  */
27
28 /*
29  * FIXME: SQLite3 only supports signed 64-bit integers natively,
30  *        thus it can only store 63 bits of the uint64_t's.
31  */
32
33 #include "platform.h"
34 #include "gnunet_psycstore_plugin.h"
35 #include "gnunet_psycstore_service.h"
36 #include "gnunet_multicast_service.h"
37 #include "gnunet_crypto_lib.h"
38 #include "gnunet_env_lib.h"
39 #include "psycstore.h"
40 #include <sqlite3.h>
41
42 /**
43  * After how many ms "busy" should a DB operation fail for good?  A
44  * low value makes sure that we are more responsive to requests
45  * (especially PUTs).  A high value guarantees a higher success rate
46  * (SELECTs in iterate can take several seconds despite LIMIT=1).
47  *
48  * The default value of 1s should ensure that users do not experience
49  * huge latencies while at the same time allowing operations to
50  * succeed with reasonable probability.
51  */
52 #define BUSY_TIMEOUT_MS 1000
53
54 #define DEBUG_PSYCSTORE GNUNET_EXTRA_LOGGING
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, level, cmd) do { GNUNET_log_from (level, "psycstore-sqlite", _("`%s' failed at %s:%d with error: %s (%d)\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh), sqlite3_errcode(db->dbh)); } while(0)
62
63 #define LOG(kind,...) GNUNET_log_from (kind, "psycstore-sqlite", __VA_ARGS__)
64
65 enum Transactions {
66   TRANSACTION_NONE = 0,
67   TRANSACTION_STATE_MODIFY
68 };
69
70 /**
71  * Context for all functions in this plugin.
72  */
73 struct Plugin
74 {
75
76   const struct GNUNET_CONFIGURATION_Handle *cfg;
77
78   /**
79    * Database filename.
80    */
81   char *fn;
82
83   /**
84    * Native SQLite database handle.
85    */
86   sqlite3 *dbh;
87
88   /**
89    * Current transaction.
90    */
91   enum Transactions transaction;
92
93   sqlite3_stmt *transaction_begin;
94
95   sqlite3_stmt *transaction_commit;
96
97   sqlite3_stmt *transaction_rollback;
98
99   /**
100    * Precompiled SQL for channel_key_store()
101    */
102   sqlite3_stmt *insert_channel_key;
103
104   /**
105    * Precompiled SQL for slave_key_store()
106    */
107   sqlite3_stmt *insert_slave_key;
108
109
110   /**
111    * Precompiled SQL for membership_store()
112    */
113   sqlite3_stmt *insert_membership;
114
115   /**
116    * Precompiled SQL for membership_test()
117    */
118   sqlite3_stmt *select_membership;
119
120
121   /**
122    * Precompiled SQL for fragment_store()
123    */
124   sqlite3_stmt *insert_fragment;
125
126   /**
127    * Precompiled SQL for message_add_flags()
128    */
129   sqlite3_stmt *update_message_flags;
130
131   /**
132    * Precompiled SQL for fragment_get()
133    */
134   sqlite3_stmt *select_fragments;
135
136   /**
137    * Precompiled SQL for fragment_get()
138    */
139   sqlite3_stmt *select_latest_fragments;
140
141   /**
142    * Precompiled SQL for message_get()
143    */
144   sqlite3_stmt *select_messages;
145
146   /**
147    * Precompiled SQL for message_get()
148    */
149   sqlite3_stmt *select_latest_messages;
150
151   /**
152    * Precompiled SQL for message_get_fragment()
153    */
154   sqlite3_stmt *select_message_fragment;
155
156   /**
157    * Precompiled SQL for counters_get_message()
158    */
159   sqlite3_stmt *select_counters_message;
160
161   /**
162    * Precompiled SQL for counters_get_state()
163    */
164   sqlite3_stmt *select_counters_state;
165
166   /**
167    * Precompiled SQL for state_modify_end()
168    */
169   sqlite3_stmt *update_state_hash_message_id;
170
171   /**
172    * Precompiled SQL for state_sync_end()
173    */
174   sqlite3_stmt *update_max_state_message_id;
175
176   /**
177    * Precompiled SQL for state_modify_op()
178    */
179   sqlite3_stmt *insert_state_current;
180
181   /**
182    * Precompiled SQL for state_modify_end()
183    */
184   sqlite3_stmt *delete_state_empty;
185
186   /**
187    * Precompiled SQL for state_set_signed()
188    */
189   sqlite3_stmt *update_state_signed;
190
191   /**
192    * Precompiled SQL for state_sync()
193    */
194   sqlite3_stmt *insert_state_sync;
195
196   /**
197    * Precompiled SQL for state_sync()
198    */
199   sqlite3_stmt *delete_state;
200
201   /**
202    * Precompiled SQL for state_sync()
203    */
204   sqlite3_stmt *insert_state_from_sync;
205
206   /**
207    * Precompiled SQL for state_sync()
208    */
209   sqlite3_stmt *delete_state_sync;
210
211   /**
212    * Precompiled SQL for state_get_signed()
213    */
214   sqlite3_stmt *select_state_signed;
215
216   /**
217    * Precompiled SQL for state_get()
218    */
219   sqlite3_stmt *select_state_one;
220
221   /**
222    * Precompiled SQL for state_get_prefix()
223    */
224   sqlite3_stmt *select_state_prefix;
225
226 };
227
228 #if DEBUG_PSYCSTORE
229
230 static void
231 sql_trace (void *cls, const char *sql)
232 {
233   LOG (GNUNET_ERROR_TYPE_DEBUG, "SQL query:\n%s\n", sql);
234 }
235
236 #endif
237
238 /**
239  * @brief Prepare a SQL statement
240  *
241  * @param dbh handle to the database
242  * @param sql SQL statement, UTF-8 encoded
243  * @param stmt set to the prepared statement
244  * @return 0 on success
245  */
246 static int
247 sql_prepare (sqlite3 *dbh, const char *sql, sqlite3_stmt **stmt)
248 {
249   char *tail;
250   int result;
251
252   result = sqlite3_prepare_v2 (dbh, sql, strlen (sql), stmt,
253                                (const char **) &tail);
254   LOG (GNUNET_ERROR_TYPE_DEBUG,
255        "Prepared `%s' / %p: %d\n", sql, *stmt, result);
256   if (result != SQLITE_OK)
257     LOG (GNUNET_ERROR_TYPE_ERROR,
258          _("Error preparing SQL query: %s\n  %s\n"),
259          sqlite3_errmsg (dbh), sql);
260   return result;
261 }
262
263
264 /**
265  * @brief Prepare a SQL statement
266  *
267  * @param dbh handle to the database
268  * @param sql SQL statement, UTF-8 encoded
269  * @return 0 on success
270  */
271 static int
272 sql_exec (sqlite3 *dbh, const char *sql)
273 {
274   int result;
275
276   result = sqlite3_exec (dbh, sql, NULL, NULL, NULL);
277   LOG (GNUNET_ERROR_TYPE_DEBUG,
278        "Executed `%s' / %d\n", sql, result);
279   if (result != SQLITE_OK)
280     LOG (GNUNET_ERROR_TYPE_ERROR,
281          _("Error executing SQL query: %s\n  %s\n"),
282          sqlite3_errmsg (dbh), sql);
283   return result;
284 }
285
286
287 /**
288  * Initialize the database connections and associated
289  * data structures (create tables and indices
290  * as needed as well).
291  *
292  * @param plugin the plugin context (state for this module)
293  * @return GNUNET_OK on success
294  */
295 static int
296 database_setup (struct Plugin *plugin)
297 {
298   char *filename;
299
300   if (GNUNET_OK !=
301       GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "psycstore-sqlite",
302                                                "FILENAME", &filename))
303   {
304     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
305                                "psycstore-sqlite", "FILENAME");
306     return GNUNET_SYSERR;
307   }
308   if (GNUNET_OK != GNUNET_DISK_file_test (filename))
309   {
310     if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (filename))
311     {
312       GNUNET_break (0);
313       GNUNET_free (filename);
314       return GNUNET_SYSERR;
315     }
316   }
317   /* filename should be UTF-8-encoded. If it isn't, it's a bug */
318   plugin->fn = filename;
319
320   /* Open database and precompile statements */
321   if (SQLITE_OK != sqlite3_open (plugin->fn, &plugin->dbh))
322   {
323     LOG (GNUNET_ERROR_TYPE_ERROR,
324          _("Unable to initialize SQLite: %s.\n"),
325          sqlite3_errmsg (plugin->dbh));
326     return GNUNET_SYSERR;
327   }
328
329 #if DEBUG_PSYCSTORE
330   sqlite3_trace (plugin->dbh, &sql_trace, NULL);
331 #endif
332
333   sql_exec (plugin->dbh, "PRAGMA temp_store=MEMORY");
334   sql_exec (plugin->dbh, "PRAGMA synchronous=NORMAL");
335   sql_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF");
336   sql_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL");
337   sql_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\"");
338 #if ! DEBUG_PSYCSTORE
339   sql_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE");
340 #endif
341   sql_exec (plugin->dbh, "PRAGMA page_size=4096");
342
343   sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS);
344
345   /* Create tables */
346
347   sql_exec (plugin->dbh,
348             "CREATE TABLE IF NOT EXISTS channels (\n"
349             "  id INTEGER PRIMARY KEY,\n"
350             "  pub_key BLOB UNIQUE,\n"
351             "  max_state_message_id INTEGER,\n" // last applied state message ID
352             "  state_hash_message_id INTEGER\n" // last message ID with a state hash
353             ");");
354
355   sql_exec (plugin->dbh,
356             "CREATE TABLE IF NOT EXISTS slaves (\n"
357             "  id INTEGER PRIMARY KEY,\n"
358             "  pub_key BLOB UNIQUE\n"
359             ");");
360
361   sql_exec (plugin->dbh,
362             "CREATE TABLE IF NOT EXISTS membership (\n"
363             "  channel_id INTEGER NOT NULL REFERENCES channels(id),\n"
364             "  slave_id INTEGER NOT NULL REFERENCES slaves(id),\n"
365             "  did_join INTEGER NOT NULL,\n"
366             "  announced_at INTEGER NOT NULL,\n"
367             "  effective_since INTEGER NOT NULL,\n"
368             "  group_generation INTEGER NOT NULL\n"
369             ");");
370   sql_exec (plugin->dbh,
371             "CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id "
372             "ON membership (channel_id, slave_id);");
373
374   /** @todo messages table: add method_name column */
375   sql_exec (plugin->dbh,
376             "CREATE TABLE IF NOT EXISTS messages (\n"
377             "  channel_id INTEGER NOT NULL REFERENCES channels(id),\n"
378             "  hop_counter INTEGER NOT NULL,\n"
379             "  signature BLOB,\n"
380             "  purpose BLOB,\n"
381             "  fragment_id INTEGER NOT NULL,\n"
382             "  fragment_offset INTEGER NOT NULL,\n"
383             "  message_id INTEGER NOT NULL,\n"
384             "  group_generation INTEGER NOT NULL,\n"
385             "  multicast_flags INTEGER NOT NULL,\n"
386             "  psycstore_flags INTEGER NOT NULL,\n"
387             "  data BLOB,\n"
388             "  PRIMARY KEY (channel_id, fragment_id),\n"
389             "  UNIQUE (channel_id, message_id, fragment_offset)\n"
390             ");");
391
392   sql_exec (plugin->dbh,
393             "CREATE TABLE IF NOT EXISTS state (\n"
394             "  channel_id INTEGER NOT NULL REFERENCES channels(id),\n"
395             "  name TEXT NOT NULL,\n"
396             "  value_current BLOB,\n"
397             "  value_signed BLOB,\n"
398             "  PRIMARY KEY (channel_id, name)\n"
399             ");");
400
401   sql_exec (plugin->dbh,
402             "CREATE TABLE IF NOT EXISTS state_sync (\n"
403             "  channel_id INTEGER NOT NULL REFERENCES channels(id),\n"
404             "  name TEXT NOT NULL,\n"
405             "  value BLOB,\n"
406             "  PRIMARY KEY (channel_id, name)\n"
407             ");");
408
409   /* Prepare statements */
410
411   sql_prepare (plugin->dbh, "BEGIN;", &plugin->transaction_begin);
412
413   sql_prepare (plugin->dbh, "COMMIT;", &plugin->transaction_commit);
414
415   sql_prepare (plugin->dbh, "ROLLBACK;", &plugin->transaction_rollback);
416
417   sql_prepare (plugin->dbh,
418                "INSERT OR IGNORE INTO channels (pub_key) VALUES (?);",
419                &plugin->insert_channel_key);
420
421   sql_prepare (plugin->dbh,
422                "INSERT OR IGNORE INTO slaves (pub_key) VALUES (?);",
423                &plugin->insert_slave_key);
424
425   sql_prepare (plugin->dbh,
426                "INSERT INTO membership\n"
427                " (channel_id, slave_id, did_join, announced_at,\n"
428                "  effective_since, group_generation)\n"
429                "VALUES ((SELECT id FROM channels WHERE pub_key = ?),\n"
430                "        (SELECT id FROM slaves WHERE pub_key = ?),\n"
431                "        ?, ?, ?, ?);",
432                &plugin->insert_membership);
433
434   sql_prepare (plugin->dbh,
435                "SELECT did_join FROM membership\n"
436                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
437                "      AND slave_id = (SELECT id FROM slaves WHERE pub_key = ?)\n"
438                "      AND effective_since <= ? AND did_join = 1\n"
439                "ORDER BY announced_at DESC LIMIT 1;",
440                &plugin->select_membership);
441
442   sql_prepare (plugin->dbh,
443                "INSERT OR IGNORE INTO messages\n"
444                " (channel_id, hop_counter, signature, purpose,\n"
445                "  fragment_id, fragment_offset, message_id,\n"
446                "  group_generation, multicast_flags, psycstore_flags, data)\n"
447                "VALUES ((SELECT id FROM channels WHERE pub_key = ?),\n"
448                "        ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
449                &plugin->insert_fragment);
450
451   sql_prepare (plugin->dbh,
452                "UPDATE messages\n"
453                "SET psycstore_flags = psycstore_flags | ?\n"
454                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
455                "      AND message_id = ? AND fragment_offset = 0;",
456                &plugin->update_message_flags);
457
458   sql_prepare (plugin->dbh,
459                "SELECT hop_counter, signature, purpose, fragment_id,\n"
460                "       fragment_offset, message_id, group_generation,\n"
461                "       multicast_flags, psycstore_flags, data\n"
462                "FROM messages\n"
463                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
464                "      AND ? <= fragment_id AND fragment_id <= ?;",
465                &plugin->select_fragments);
466
467   /** @todo select_messages: add method_prefix filter */
468   sql_prepare (plugin->dbh,
469                "SELECT hop_counter, signature, purpose, fragment_id,\n"
470                "       fragment_offset, message_id, group_generation,\n"
471                "       multicast_flags, psycstore_flags, data\n"
472                "FROM messages\n"
473                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
474                "      AND ? <= message_id AND message_id <= ?;",
475                &plugin->select_messages);
476
477   sql_prepare (plugin->dbh,
478                "SELECT * FROM\n"
479                "(SELECT hop_counter, signature, purpose, fragment_id,\n"
480                "        fragment_offset, message_id, group_generation,\n"
481                "        multicast_flags, psycstore_flags, data\n"
482                " FROM messages\n"
483                " WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
484                " ORDER BY fragment_id DESC\n"
485                " LIMIT ?)\n"
486                "ORDER BY fragment_id;",
487                &plugin->select_latest_fragments);
488
489   /** @todo select_latest_messages: add method_prefix filter */
490   sql_prepare (plugin->dbh,
491                "SELECT hop_counter, signature, purpose, fragment_id,\n"
492                "       fragment_offset, message_id, group_generation,\n"
493                "        multicast_flags, psycstore_flags, data\n"
494                "FROM messages\n"
495                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
496                "      AND message_id IN\n"
497                "      (SELECT message_id\n"
498                "       FROM messages\n"
499                "       WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
500                "       GROUP BY message_id\n"
501                "       ORDER BY message_id\n"
502                "       DESC LIMIT ?)\n"
503                "ORDER BY fragment_id;",
504                &plugin->select_latest_messages);
505
506   sql_prepare (plugin->dbh,
507                "SELECT hop_counter, signature, purpose, fragment_id,\n"
508                "       fragment_offset, message_id, group_generation,\n"
509                "       multicast_flags, psycstore_flags, data\n"
510                "FROM messages\n"
511                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
512                "      AND message_id = ? AND fragment_offset = ?;",
513                &plugin->select_message_fragment);
514
515   sql_prepare (plugin->dbh,
516                "SELECT fragment_id, message_id, group_generation\n"
517                "FROM messages\n"
518                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
519                "ORDER BY fragment_id DESC LIMIT 1;",
520                &plugin->select_counters_message);
521
522   sql_prepare (plugin->dbh,
523                "SELECT max_state_message_id\n"
524                "FROM channels\n"
525                "WHERE pub_key = ? AND max_state_message_id IS NOT NULL;",
526                &plugin->select_counters_state);
527
528   sql_prepare (plugin->dbh,
529                "UPDATE channels\n"
530                "SET max_state_message_id = ?\n"
531                "WHERE pub_key = ?;",
532                &plugin->update_max_state_message_id);
533
534   sql_prepare (plugin->dbh,
535                "UPDATE channels\n"
536                "SET state_hash_message_id = ?\n"
537                "WHERE pub_key = ?;",
538                &plugin->update_state_hash_message_id);
539
540   sql_prepare (plugin->dbh,
541                "INSERT OR REPLACE INTO state\n"
542                "  (channel_id, name, value_current, value_signed)\n"
543                "SELECT new.channel_id, new.name,\n"
544                "       new.value_current, old.value_signed\n"
545                "FROM (SELECT (SELECT id FROM channels WHERE pub_key = ?)\n"
546                "             AS channel_id,\n"
547                "             ? AS name, ? AS value_current) AS new\n"
548                "LEFT JOIN (SELECT channel_id, name, value_signed\n"
549                "           FROM state) AS old\n"
550                "ON new.channel_id = old.channel_id AND new.name = old.name;",
551                &plugin->insert_state_current);
552
553   sql_prepare (plugin->dbh,
554                "DELETE FROM state\n"
555                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
556                "      AND (value_current IS NULL OR length(value_current) = 0)\n"
557                "      AND (value_signed IS NULL OR length(value_signed) = 0);",
558                &plugin->delete_state_empty);
559
560   sql_prepare (plugin->dbh,
561                "UPDATE state\n"
562                "SET value_signed = value_current\n"
563                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
564                &plugin->update_state_signed);
565
566   sql_prepare (plugin->dbh,
567                "DELETE FROM state\n"
568                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
569                &plugin->delete_state);
570
571   sql_prepare (plugin->dbh,
572                "INSERT INTO state_sync (channel_id, name, value)\n"
573                "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);",
574                &plugin->insert_state_sync);
575
576   sql_prepare (plugin->dbh,
577                "INSERT INTO state\n"
578                " (channel_id, name, value_current, value_signed)\n"
579                "SELECT channel_id, name, value, value\n"
580                "FROM state_sync\n"
581                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
582                &plugin->insert_state_from_sync);
583
584   sql_prepare (plugin->dbh,
585                "DELETE FROM state_sync\n"
586                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
587                &plugin->delete_state_sync);
588
589   sql_prepare (plugin->dbh,
590                "SELECT value_current\n"
591                "FROM state\n"
592                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
593                "      AND name = ?;",
594                &plugin->select_state_one);
595
596   sql_prepare (plugin->dbh,
597                "SELECT name, value_current\n"
598                "FROM state\n"
599                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
600                "      AND (name = ? OR name LIKE ?);",
601                &plugin->select_state_prefix);
602
603   sql_prepare (plugin->dbh,
604                "SELECT name, value_signed\n"
605                "FROM state\n"
606                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)"
607                "      AND value_signed IS NOT NULL;",
608                &plugin->select_state_signed);
609
610   return GNUNET_OK;
611 }
612
613
614 /**
615  * Shutdown database connection and associate data
616  * structures.
617  * @param plugin the plugin context (state for this module)
618  */
619 static void
620 database_shutdown (struct Plugin *plugin)
621 {
622   int result;
623   sqlite3_stmt *stmt;
624   while (NULL != (stmt = sqlite3_next_stmt (plugin->dbh, NULL)))
625   {
626     result = sqlite3_finalize (stmt);
627     if (SQLITE_OK != result)
628       LOG (GNUNET_ERROR_TYPE_WARNING,
629            "Failed to close statement %p: %d\n", stmt, result);
630   }
631   if (SQLITE_OK != sqlite3_close (plugin->dbh))
632     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
633
634   GNUNET_free_non_null (plugin->fn);
635 }
636
637 /**
638  * Execute a prepared statement with a @a channel_key argument.
639  *
640  * @param plugin Plugin handle.
641  * @param stmt Statement to execute.
642  * @param channel_key Public key of the channel.
643  *
644  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
645  */
646 static int
647 exec_channel (struct Plugin *plugin, sqlite3_stmt *stmt,
648               const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key)
649 {
650   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
651                                       sizeof (*channel_key), SQLITE_STATIC))
652   {
653     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
654                 "sqlite3_bind");
655   }
656   else if (SQLITE_DONE != sqlite3_step (stmt))
657   {
658     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
659                 "sqlite3_step");
660   }
661
662   if (SQLITE_OK != sqlite3_reset (stmt))
663   {
664     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
665                 "sqlite3_reset");
666     return GNUNET_SYSERR;
667   }
668
669   return GNUNET_OK;
670 }
671
672 /**
673  * Begin a transaction.
674  */
675 static int
676 transaction_begin (struct Plugin *plugin, enum Transactions transaction)
677 {
678   sqlite3_stmt *stmt = plugin->transaction_begin;
679
680   if (SQLITE_DONE != sqlite3_step (stmt))
681   {
682     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
683                 "sqlite3_step");
684   }
685   if (SQLITE_OK != sqlite3_reset (stmt))
686   {
687     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
688                 "sqlite3_reset");
689     return GNUNET_SYSERR;
690   }
691
692   plugin->transaction = transaction;
693   return GNUNET_OK;
694 }
695
696
697 /**
698  * Commit current transaction.
699  */
700 static int
701 transaction_commit (struct Plugin *plugin)
702 {
703   sqlite3_stmt *stmt = plugin->transaction_commit;
704
705   if (SQLITE_DONE != sqlite3_step (stmt))
706   {
707     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
708                 "sqlite3_step");
709   }
710   if (SQLITE_OK != sqlite3_reset (stmt))
711   {
712     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
713                 "sqlite3_reset");
714     return GNUNET_SYSERR;
715   }
716
717   plugin->transaction = TRANSACTION_NONE;
718   return GNUNET_OK;
719 }
720
721
722 /**
723  * Roll back current transaction.
724  */
725 static int
726 transaction_rollback (struct Plugin *plugin)
727 {
728   sqlite3_stmt *stmt = plugin->transaction_rollback;
729
730   if (SQLITE_DONE != sqlite3_step (stmt))
731   {
732     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
733                 "sqlite3_step");
734   }
735   if (SQLITE_OK != sqlite3_reset (stmt))
736   {
737     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
738                 "sqlite3_reset");
739     return GNUNET_SYSERR;
740   }
741   plugin->transaction = TRANSACTION_NONE;
742   return GNUNET_OK;
743 }
744
745
746 static int
747 channel_key_store (struct Plugin *plugin,
748                    const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key)
749 {
750   sqlite3_stmt *stmt = plugin->insert_channel_key;
751
752   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
753                                       sizeof (*channel_key), SQLITE_STATIC))
754   {
755     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
756                 "sqlite3_bind");
757   }
758   else if (SQLITE_DONE != sqlite3_step (stmt))
759   {
760     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
761                 "sqlite3_step");
762   }
763
764   if (SQLITE_OK != sqlite3_reset (stmt))
765   {
766     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
767                 "sqlite3_reset");
768     return GNUNET_SYSERR;
769   }
770
771   return GNUNET_OK;
772 }
773
774
775 static int
776 slave_key_store (struct Plugin *plugin,
777                  const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key)
778 {
779   sqlite3_stmt *stmt = plugin->insert_slave_key;
780
781   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, slave_key,
782                                       sizeof (*slave_key), SQLITE_STATIC))
783   {
784     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
785                 "sqlite3_bind");
786   }
787   else if (SQLITE_DONE != sqlite3_step (stmt))
788   {
789     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
790                 "sqlite3_step");
791   }
792
793
794   if (SQLITE_OK != sqlite3_reset (stmt))
795   {
796     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
797                 "sqlite3_reset");
798     return GNUNET_SYSERR;
799   }
800
801   return GNUNET_OK;
802 }
803
804
805 /**
806  * Store join/leave events for a PSYC channel in order to be able to answer
807  * membership test queries later.
808  *
809  * @see GNUNET_PSYCSTORE_membership_store()
810  *
811  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
812  */
813 static int
814 membership_store (void *cls,
815                   const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
816                   const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
817                   int did_join,
818                   uint64_t announced_at,
819                   uint64_t effective_since,
820                   uint64_t group_generation)
821 {
822   struct Plugin *plugin = cls;
823   sqlite3_stmt *stmt = plugin->insert_membership;
824
825   GNUNET_assert (TRANSACTION_NONE == plugin->transaction);
826
827   if (announced_at > INT64_MAX ||
828       effective_since > INT64_MAX ||
829       group_generation > INT64_MAX)
830   {
831     GNUNET_break (0);
832     return GNUNET_SYSERR;
833   }
834
835   if (GNUNET_OK != channel_key_store (plugin, channel_key)
836       || GNUNET_OK != slave_key_store (plugin, slave_key))
837     return GNUNET_SYSERR;
838
839   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
840                                       sizeof (*channel_key), SQLITE_STATIC)
841       || SQLITE_OK != sqlite3_bind_blob (stmt, 2, slave_key,
842                                          sizeof (*slave_key), SQLITE_STATIC)
843       || SQLITE_OK != sqlite3_bind_int (stmt, 3, did_join)
844       || SQLITE_OK != sqlite3_bind_int64 (stmt, 4, announced_at)
845       || SQLITE_OK != sqlite3_bind_int64 (stmt, 5, effective_since)
846       || SQLITE_OK != sqlite3_bind_int64 (stmt, 6, group_generation))
847   {
848     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
849                 "sqlite3_bind");
850   }
851   else if (SQLITE_DONE != sqlite3_step (stmt))
852   {
853     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
854                 "sqlite3_step");
855   }
856
857   if (SQLITE_OK != sqlite3_reset (stmt))
858   {
859     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
860                 "sqlite3_reset");
861     return GNUNET_SYSERR;
862   }
863
864   return GNUNET_OK;
865 }
866
867 /**
868  * Test if a member was admitted to the channel at the given message ID.
869  *
870  * @see GNUNET_PSYCSTORE_membership_test()
871  *
872  * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not,
873  *         #GNUNET_SYSERR if there was en error.
874  */
875 static int
876 membership_test (void *cls,
877                  const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
878                  const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
879                  uint64_t message_id)
880 {
881   struct Plugin *plugin = cls;
882   sqlite3_stmt *stmt = plugin->select_membership;
883   int ret = GNUNET_SYSERR;
884
885   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
886                                       sizeof (*channel_key), SQLITE_STATIC)
887       || SQLITE_OK != sqlite3_bind_blob (stmt, 2, slave_key,
888                                          sizeof (*slave_key), SQLITE_STATIC)
889       || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_id))
890   {
891     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
892                 "sqlite3_bind");
893   }
894   else
895   {
896     switch (sqlite3_step (stmt))
897     {
898     case SQLITE_DONE:
899       ret = GNUNET_NO;
900       break;
901     case SQLITE_ROW:
902       ret = GNUNET_YES;
903     }
904   }
905
906   if (SQLITE_OK != sqlite3_reset (stmt))
907   {
908     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
909                 "sqlite3_reset");
910   }
911
912   return ret;
913 }
914
915 /**
916  * Store a message fragment sent to a channel.
917  *
918  * @see GNUNET_PSYCSTORE_fragment_store()
919  *
920  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
921  */
922 static int
923 fragment_store (void *cls,
924                 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
925                 const struct GNUNET_MULTICAST_MessageHeader *msg,
926                 uint32_t psycstore_flags)
927 {
928   struct Plugin *plugin = cls;
929   sqlite3_stmt *stmt = plugin->insert_fragment;
930
931   GNUNET_assert (TRANSACTION_NONE == plugin->transaction);
932
933   uint64_t fragment_id = GNUNET_ntohll (msg->fragment_id);
934   uint64_t fragment_offset = GNUNET_ntohll (msg->fragment_offset);
935   uint64_t message_id = GNUNET_ntohll (msg->message_id);
936   uint64_t group_generation = GNUNET_ntohll (msg->group_generation);
937
938   if (fragment_id > INT64_MAX || fragment_offset > INT64_MAX ||
939       message_id > INT64_MAX || group_generation > INT64_MAX)
940   {
941     LOG (GNUNET_ERROR_TYPE_ERROR,
942          "Tried to store fragment with a field > INT64_MAX: "
943          "%lu, %lu, %lu, %lu\n", fragment_id, fragment_offset,
944          message_id, group_generation);
945     GNUNET_break (0);
946     return GNUNET_SYSERR;
947   }
948
949   if (GNUNET_OK != channel_key_store (plugin, channel_key))
950     return GNUNET_SYSERR;
951
952   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
953                                       sizeof (*channel_key), SQLITE_STATIC)
954       || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, ntohl (msg->hop_counter) )
955       || SQLITE_OK != sqlite3_bind_blob (stmt, 3, (const void *) &msg->signature,
956                                          sizeof (msg->signature), SQLITE_STATIC)
957       || SQLITE_OK != sqlite3_bind_blob (stmt, 4, (const void *) &msg->purpose,
958                                          sizeof (msg->purpose), SQLITE_STATIC)
959       || SQLITE_OK != sqlite3_bind_int64 (stmt, 5, fragment_id)
960       || SQLITE_OK != sqlite3_bind_int64 (stmt, 6, fragment_offset)
961       || SQLITE_OK != sqlite3_bind_int64 (stmt, 7, message_id)
962       || SQLITE_OK != sqlite3_bind_int64 (stmt, 8, group_generation)
963       || SQLITE_OK != sqlite3_bind_int64 (stmt, 9, ntohl (msg->flags))
964       || SQLITE_OK != sqlite3_bind_int64 (stmt, 10, psycstore_flags)
965       || SQLITE_OK != sqlite3_bind_blob (stmt, 11, (const void *) &msg[1],
966                                          ntohs (msg->header.size)
967                                          - sizeof (*msg), SQLITE_STATIC))
968   {
969     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
970                 "sqlite3_bind");
971   }
972   else if (SQLITE_DONE != sqlite3_step (stmt))
973   {
974     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
975                 "sqlite3_step");
976   }
977
978   if (SQLITE_OK != sqlite3_reset (stmt))
979   {
980     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
981                 "sqlite3_reset");
982     return GNUNET_SYSERR;
983   }
984
985   return GNUNET_OK;
986 }
987
988 /**
989  * Set additional flags for a given message.
990  *
991  * They are OR'd with any existing flags set.
992  *
993  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
994  */
995 static int
996 message_add_flags (void *cls,
997                    const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
998                    uint64_t message_id,
999                    uint64_t psycstore_flags)
1000 {
1001   struct Plugin *plugin = cls;
1002   sqlite3_stmt *stmt = plugin->update_message_flags;
1003   int ret = GNUNET_SYSERR;
1004
1005   if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, psycstore_flags)
1006       || SQLITE_OK != sqlite3_bind_blob (stmt, 2, channel_key,
1007                                          sizeof (*channel_key), SQLITE_STATIC)
1008       || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_id))
1009   {
1010     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1011                 "sqlite3_bind");
1012   }
1013   else
1014   {
1015     switch (sqlite3_step (stmt))
1016     {
1017     case SQLITE_DONE:
1018       ret = sqlite3_total_changes (plugin->dbh) > 0 ? GNUNET_OK : GNUNET_NO;
1019       break;
1020     default:
1021       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1022                   "sqlite3_step");
1023     }
1024   }
1025
1026   if (SQLITE_OK != sqlite3_reset (stmt))
1027   {
1028     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1029                 "sqlite3_reset");
1030     return GNUNET_SYSERR;
1031   }
1032
1033   return ret;
1034 }
1035
1036 static int
1037 fragment_row (sqlite3_stmt *stmt, GNUNET_PSYCSTORE_FragmentCallback cb,
1038               void *cb_cls)
1039 {
1040   int data_size = sqlite3_column_bytes (stmt, 9);
1041   struct GNUNET_MULTICAST_MessageHeader *msg
1042     = GNUNET_malloc (sizeof (*msg) + data_size);
1043
1044   msg->header.size = htons (sizeof (*msg) + data_size);
1045   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
1046   msg->hop_counter = htonl ((uint32_t) sqlite3_column_int64 (stmt, 0));
1047   memcpy (&msg->signature,
1048           sqlite3_column_blob (stmt, 1),
1049           sqlite3_column_bytes (stmt, 1));
1050   memcpy (&msg->purpose,
1051           sqlite3_column_blob (stmt, 2),
1052           sqlite3_column_bytes (stmt, 2));
1053   msg->fragment_id = GNUNET_htonll (sqlite3_column_int64 (stmt, 3));
1054   msg->fragment_offset = GNUNET_htonll (sqlite3_column_int64 (stmt, 4));
1055   msg->message_id = GNUNET_htonll (sqlite3_column_int64 (stmt, 5));
1056   msg->group_generation = GNUNET_htonll (sqlite3_column_int64 (stmt, 6));
1057   msg->flags = htonl (sqlite3_column_int64 (stmt, 7));
1058   memcpy (&msg[1], sqlite3_column_blob (stmt, 9), data_size);
1059
1060   return cb (cb_cls, (void *) msg, sqlite3_column_int64 (stmt, 8));
1061 }
1062
1063
1064 static int
1065 fragment_select (struct Plugin *plugin, sqlite3_stmt *stmt,
1066                  uint64_t *returned_fragments,
1067                  GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls)
1068 {
1069   int ret = GNUNET_SYSERR;
1070   int sql_ret;
1071
1072   do
1073   {
1074     sql_ret = sqlite3_step (stmt);
1075     switch (sql_ret)
1076     {
1077     case SQLITE_DONE:
1078       if (ret != GNUNET_OK)
1079         ret = GNUNET_NO;
1080       break;
1081     case SQLITE_ROW:
1082       ret = fragment_row (stmt, cb, cb_cls);
1083       (*returned_fragments)++;
1084       if (ret != GNUNET_YES)
1085         sql_ret = SQLITE_DONE;
1086       break;
1087     default:
1088       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1089                   "sqlite3_step");
1090     }
1091   }
1092   while (sql_ret == SQLITE_ROW);
1093
1094   return ret;
1095 }
1096
1097 /**
1098  * Retrieve a message fragment range by fragment ID.
1099  *
1100  * @see GNUNET_PSYCSTORE_fragment_get()
1101  *
1102  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1103  */
1104 static int
1105 fragment_get (void *cls,
1106               const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1107               uint64_t first_fragment_id,
1108               uint64_t last_fragment_id,
1109               uint64_t *returned_fragments,
1110               GNUNET_PSYCSTORE_FragmentCallback cb,
1111               void *cb_cls)
1112 {
1113   struct Plugin *plugin = cls;
1114   sqlite3_stmt *stmt = plugin->select_fragments;
1115   int ret = GNUNET_SYSERR;
1116   *returned_fragments = 0;
1117
1118   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1119                                       sizeof (*channel_key),
1120                                       SQLITE_STATIC)
1121       || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, first_fragment_id)
1122       || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, last_fragment_id))
1123   {
1124     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1125                 "sqlite3_bind");
1126   }
1127   else
1128   {
1129     ret = fragment_select (plugin, stmt, returned_fragments, cb, cb_cls);
1130   }
1131
1132   if (SQLITE_OK != sqlite3_reset (stmt))
1133   {
1134     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1135                 "sqlite3_reset");
1136   }
1137
1138   return ret;
1139 }
1140
1141
1142 /**
1143  * Retrieve a message fragment range by fragment ID.
1144  *
1145  * @see GNUNET_PSYCSTORE_fragment_get_latest()
1146  *
1147  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1148  */
1149 static int
1150 fragment_get_latest (void *cls,
1151                      const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1152                      uint64_t fragment_limit,
1153                      uint64_t *returned_fragments,
1154                      GNUNET_PSYCSTORE_FragmentCallback cb,
1155                      void *cb_cls)
1156 {
1157   struct Plugin *plugin = cls;
1158   sqlite3_stmt *stmt = plugin->select_latest_fragments;
1159   int ret = GNUNET_SYSERR;
1160   *returned_fragments = 0;
1161
1162   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1163                                       sizeof (*channel_key),
1164                                       SQLITE_STATIC)
1165       || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, fragment_limit))
1166   {
1167     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1168                 "sqlite3_bind");
1169   }
1170   else
1171   {
1172     ret = fragment_select (plugin, stmt, returned_fragments, cb, cb_cls);
1173   }
1174
1175   if (SQLITE_OK != sqlite3_reset (stmt))
1176   {
1177     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1178                 "sqlite3_reset");
1179   }
1180
1181   return ret;
1182 }
1183
1184
1185 /**
1186  * Retrieve all fragments of a message ID range.
1187  *
1188  * @see GNUNET_PSYCSTORE_message_get()
1189  *
1190  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1191  */
1192 static int
1193 message_get (void *cls,
1194              const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1195              uint64_t first_message_id,
1196              uint64_t last_message_id,
1197              uint64_t *returned_fragments,
1198              GNUNET_PSYCSTORE_FragmentCallback cb,
1199              void *cb_cls)
1200 {
1201   struct Plugin *plugin = cls;
1202   sqlite3_stmt *stmt = plugin->select_messages;
1203   int ret = GNUNET_SYSERR;
1204   *returned_fragments = 0;
1205
1206   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1207                                       sizeof (*channel_key),
1208                                       SQLITE_STATIC)
1209       || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, first_message_id)
1210       || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, last_message_id))
1211   {
1212     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1213                 "sqlite3_bind");
1214   }
1215   else
1216   {
1217     ret = fragment_select (plugin, stmt, returned_fragments, cb, cb_cls);
1218   }
1219
1220   if (SQLITE_OK != sqlite3_reset (stmt))
1221   {
1222     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1223                 "sqlite3_reset");
1224   }
1225
1226   return ret;
1227 }
1228
1229
1230 /**
1231  * Retrieve all fragments of the latest messages.
1232  *
1233  * @see GNUNET_PSYCSTORE_message_get_latest()
1234  *
1235  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1236  */
1237 static int
1238 message_get_latest (void *cls,
1239                     const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1240                     uint64_t message_limit,
1241                     uint64_t *returned_fragments,
1242                     GNUNET_PSYCSTORE_FragmentCallback cb,
1243                     void *cb_cls)
1244 {
1245   struct Plugin *plugin = cls;
1246   sqlite3_stmt *stmt = plugin->select_latest_messages;
1247   int ret = GNUNET_SYSERR;
1248   *returned_fragments = 0;
1249
1250   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1251                                       sizeof (*channel_key),
1252                                       SQLITE_STATIC)
1253       || SQLITE_OK != sqlite3_bind_blob (stmt, 2, channel_key,
1254                                          sizeof (*channel_key),
1255                                          SQLITE_STATIC)
1256       || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_limit))
1257   {
1258     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1259                 "sqlite3_bind");
1260   }
1261   else
1262   {
1263     ret = fragment_select (plugin, stmt, returned_fragments, cb, cb_cls);
1264   }
1265
1266   if (SQLITE_OK != sqlite3_reset (stmt))
1267   {
1268     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1269                 "sqlite3_reset");
1270   }
1271
1272   return ret;
1273 }
1274
1275
1276 /**
1277  * Retrieve a fragment of message specified by its message ID and fragment
1278  * offset.
1279  *
1280  * @see GNUNET_PSYCSTORE_message_get_fragment()
1281  *
1282  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1283  */
1284 static int
1285 message_get_fragment (void *cls,
1286                       const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1287                       uint64_t message_id,
1288                       uint64_t fragment_offset,
1289                       GNUNET_PSYCSTORE_FragmentCallback cb,
1290                       void *cb_cls)
1291 {
1292   struct Plugin *plugin = cls;
1293   sqlite3_stmt *stmt = plugin->select_message_fragment;
1294   int ret = GNUNET_SYSERR;
1295
1296   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1297                                       sizeof (*channel_key),
1298                                       SQLITE_STATIC)
1299       || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, message_id)
1300       || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, fragment_offset))
1301   {
1302     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1303                 "sqlite3_bind");
1304   }
1305   else
1306   {
1307     switch (sqlite3_step (stmt))
1308     {
1309     case SQLITE_DONE:
1310       ret = GNUNET_NO;
1311       break;
1312     case SQLITE_ROW:
1313       ret = fragment_row (stmt, cb, cb_cls);
1314       break;
1315     default:
1316       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1317                   "sqlite3_step");
1318     }
1319   }
1320
1321   if (SQLITE_OK != sqlite3_reset (stmt))
1322   {
1323     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1324                 "sqlite3_reset");
1325   }
1326
1327   return ret;
1328 }
1329
1330 /**
1331  * Retrieve the max. values of message counters for a channel.
1332  *
1333  * @see GNUNET_PSYCSTORE_counters_get()
1334  *
1335  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1336  */
1337 static int
1338 counters_message_get (void *cls,
1339                       const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1340                       uint64_t *max_fragment_id,
1341                       uint64_t *max_message_id,
1342                       uint64_t *max_group_generation)
1343 {
1344   struct Plugin *plugin = cls;
1345   sqlite3_stmt *stmt = plugin->select_counters_message;
1346   int ret = GNUNET_SYSERR;
1347
1348   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1349                                       sizeof (*channel_key),
1350                                       SQLITE_STATIC))
1351   {
1352     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1353                 "sqlite3_bind");
1354   }
1355   else
1356   {
1357     switch (sqlite3_step (stmt))
1358     {
1359     case SQLITE_DONE:
1360       ret = GNUNET_NO;
1361       break;
1362     case SQLITE_ROW:
1363       *max_fragment_id = sqlite3_column_int64 (stmt, 0);
1364       *max_message_id = sqlite3_column_int64 (stmt, 1);
1365       *max_group_generation = sqlite3_column_int64 (stmt, 2);
1366       ret = GNUNET_OK;
1367       break;
1368     default:
1369       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1370                   "sqlite3_step");
1371     }
1372   }
1373
1374   if (SQLITE_OK != sqlite3_reset (stmt))
1375   {
1376     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1377                 "sqlite3_reset");
1378   }
1379
1380   return ret;
1381 }
1382
1383 /**
1384  * Retrieve the max. values of state counters for a channel.
1385  *
1386  * @see GNUNET_PSYCSTORE_counters_get()
1387  *
1388  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1389  */
1390 static int
1391 counters_state_get (void *cls,
1392                     const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1393                     uint64_t *max_state_message_id)
1394 {
1395   struct Plugin *plugin = cls;
1396   sqlite3_stmt *stmt = plugin->select_counters_state;
1397   int ret = GNUNET_SYSERR;
1398
1399   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1400                                       sizeof (*channel_key),
1401                                       SQLITE_STATIC))
1402   {
1403     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1404                 "sqlite3_bind");
1405   }
1406   else
1407   {
1408     switch (sqlite3_step (stmt))
1409     {
1410     case SQLITE_DONE:
1411       ret = GNUNET_NO;
1412       break;
1413     case SQLITE_ROW:
1414       *max_state_message_id = sqlite3_column_int64 (stmt, 0);
1415       ret = GNUNET_OK;
1416       break;
1417     default:
1418       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1419                   "sqlite3_step");
1420     }
1421   }
1422
1423   if (SQLITE_OK != sqlite3_reset (stmt))
1424   {
1425     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1426                 "sqlite3_reset");
1427   }
1428
1429   return ret;
1430 }
1431
1432
1433 /**
1434  * Assign a value to a state variable.
1435  *
1436  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1437  */
1438 static int
1439 state_assign (struct Plugin *plugin, sqlite3_stmt *stmt,
1440               const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1441               const char *name, const void *value, size_t value_size)
1442 {
1443   int ret = GNUNET_SYSERR;
1444
1445   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1446                                       sizeof (*channel_key), SQLITE_STATIC)
1447       || SQLITE_OK != sqlite3_bind_text (stmt, 2, name, -1, SQLITE_STATIC)
1448       || SQLITE_OK != sqlite3_bind_blob (stmt, 3, value, value_size,
1449                                          SQLITE_STATIC))
1450   {
1451     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1452                 "sqlite3_bind");
1453   }
1454   else
1455   {
1456     switch (sqlite3_step (stmt))
1457     {
1458     case SQLITE_DONE:
1459       ret = 0 < sqlite3_total_changes (plugin->dbh) ? GNUNET_OK : GNUNET_NO;
1460       break;
1461     default:
1462       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1463                   "sqlite3_step");
1464     }
1465   }
1466
1467   if (SQLITE_OK != sqlite3_reset (stmt))
1468   {
1469     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1470                 "sqlite3_reset");
1471     return GNUNET_SYSERR;
1472   }
1473
1474   return ret;
1475 }
1476
1477
1478 static int
1479 update_message_id (struct Plugin *plugin, sqlite3_stmt *stmt,
1480                    const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1481                    uint64_t message_id)
1482 {
1483   if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, message_id)
1484       || SQLITE_OK != sqlite3_bind_blob (stmt, 2, channel_key,
1485                                          sizeof (*channel_key), SQLITE_STATIC))
1486   {
1487     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1488                 "sqlite3_bind");
1489   }
1490   else if (SQLITE_DONE != sqlite3_step (stmt))
1491   {
1492     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1493                 "sqlite3_step");
1494   }
1495   if (SQLITE_OK != sqlite3_reset (stmt))
1496   {
1497     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1498                 "sqlite3_reset");
1499     return GNUNET_SYSERR;
1500   }
1501   return GNUNET_OK;
1502 }
1503
1504
1505 /**
1506  * Begin modifying current state.
1507  */
1508 static int
1509 state_modify_begin (void *cls,
1510                     const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1511                     uint64_t message_id, uint64_t state_delta)
1512 {
1513   struct Plugin *plugin = cls;
1514
1515   if (state_delta > 0)
1516   {
1517     /**
1518      * We can only apply state modifiers in the current message if modifiers in
1519      * the previous stateful message (message_id - state_delta) were already
1520      * applied.
1521      */
1522
1523     uint64_t max_state_message_id = 0;
1524     int ret = counters_state_get (plugin, channel_key, &max_state_message_id);
1525     if (GNUNET_OK != ret)
1526       return ret;
1527
1528     if (message_id - state_delta != max_state_message_id)
1529       return GNUNET_NO;
1530   }
1531
1532   // Make sure no other transaction is going on.
1533   if (TRANSACTION_NONE != plugin->transaction)
1534       if (GNUNET_OK != transaction_rollback (plugin))
1535           return GNUNET_SYSERR;
1536
1537   return transaction_begin (plugin, TRANSACTION_STATE_MODIFY);
1538 }
1539
1540
1541 /**
1542  * Set the current value of state variable.
1543  *
1544  * @see GNUNET_PSYCSTORE_state_modify()
1545  *
1546  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1547  */
1548 static int
1549 state_modify_op (void *cls,
1550                  const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1551                  enum GNUNET_ENV_Operator op,
1552                  const char *name, const void *value, size_t value_size)
1553 {
1554   struct Plugin *plugin = cls;
1555   GNUNET_assert (TRANSACTION_STATE_MODIFY == plugin->transaction);
1556
1557   switch (op)
1558   {
1559   case GNUNET_ENV_OP_ASSIGN:
1560     return state_assign (plugin, plugin->insert_state_current, channel_key,
1561                          name, value, value_size);
1562
1563   /// @todo implement more state operations
1564   default:
1565     return GNUNET_SYSERR;
1566   }
1567 }
1568
1569
1570 /**
1571  * End modifying current state.
1572  */
1573 static int
1574 state_modify_end (void *cls,
1575                   const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1576                   uint64_t message_id)
1577 {
1578   struct Plugin *plugin = cls;
1579   GNUNET_assert (TRANSACTION_STATE_MODIFY == plugin->transaction);
1580
1581   return
1582     GNUNET_OK == exec_channel (plugin, plugin->delete_state_empty, channel_key)
1583     && GNUNET_OK == update_message_id (plugin,
1584                                        plugin->update_max_state_message_id,
1585                                        channel_key, message_id)
1586     && GNUNET_OK == transaction_commit (plugin)
1587     ? GNUNET_OK : GNUNET_SYSERR;
1588 }
1589
1590
1591 /**
1592  * Begin state synchronization.
1593  */
1594 static int
1595 state_sync_begin (void *cls,
1596                   const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key)
1597 {
1598   struct Plugin *plugin = cls;
1599   return exec_channel (plugin, plugin->delete_state_sync, channel_key);
1600 }
1601
1602
1603 /**
1604  * Assign current value of a state variable.
1605  *
1606  * @see GNUNET_PSYCSTORE_state_modify()
1607  *
1608  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1609  */
1610 static int
1611 state_sync_assign (void *cls,
1612                 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1613                 const char *name, const void *value, size_t value_size)
1614 {
1615   struct Plugin *plugin = cls;
1616   return state_assign (cls, plugin->insert_state_sync, channel_key,
1617                        name, value, value_size);
1618 }
1619
1620
1621 /**
1622  * End modifying current state.
1623  */
1624 static int
1625 state_sync_end (void *cls,
1626                 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1627                 uint64_t max_state_message_id,
1628                 uint64_t state_hash_message_id)
1629 {
1630   struct Plugin *plugin = cls;
1631   int ret = GNUNET_SYSERR;
1632
1633   GNUNET_OK == transaction_begin (plugin, TRANSACTION_NONE)
1634     && GNUNET_OK == exec_channel (plugin, plugin->delete_state, channel_key)
1635     && GNUNET_OK == exec_channel (plugin, plugin->insert_state_from_sync,
1636                                   channel_key)
1637     && GNUNET_OK == exec_channel (plugin, plugin->delete_state_sync,
1638                                   channel_key)
1639     && GNUNET_OK == update_message_id (plugin,
1640                                        plugin->update_state_hash_message_id,
1641                                        channel_key, state_hash_message_id)
1642     && GNUNET_OK == update_message_id (plugin,
1643                                        plugin->update_max_state_message_id,
1644                                        channel_key, max_state_message_id)
1645     && GNUNET_OK == transaction_commit (plugin)
1646     ? ret = GNUNET_OK
1647     : transaction_rollback (plugin);
1648   return ret;
1649 }
1650
1651
1652 /**
1653  * Delete the whole state.
1654  *
1655  * @see GNUNET_PSYCSTORE_state_reset()
1656  *
1657  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1658  */
1659 static int
1660 state_reset (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key)
1661 {
1662   struct Plugin *plugin = cls;
1663   return exec_channel (plugin, plugin->delete_state, channel_key);
1664 }
1665
1666
1667 /**
1668  * Update signed values of state variables in the state store.
1669  *
1670  * @see GNUNET_PSYCSTORE_state_hash_update()
1671  *
1672  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1673  */
1674 static int
1675 state_update_signed (void *cls,
1676                      const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key)
1677 {
1678   struct Plugin *plugin = cls;
1679   return exec_channel (plugin, plugin->update_state_signed, channel_key);
1680 }
1681
1682
1683 /**
1684  * Retrieve a state variable by name.
1685  *
1686  * @see GNUNET_PSYCSTORE_state_get()
1687  *
1688  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1689  */
1690 static int
1691 state_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1692            const char *name, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls)
1693 {
1694   struct Plugin *plugin = cls;
1695   int ret = GNUNET_SYSERR;
1696
1697   sqlite3_stmt *stmt = plugin->select_state_one;
1698
1699   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1700                                       sizeof (*channel_key),
1701                                       SQLITE_STATIC)
1702       || SQLITE_OK != sqlite3_bind_text (stmt, 2, name, -1, SQLITE_STATIC))
1703   {
1704     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1705                 "sqlite3_bind");
1706   }
1707   else
1708   {
1709     switch (sqlite3_step (stmt))
1710     {
1711     case SQLITE_DONE:
1712       ret = GNUNET_NO;
1713       break;
1714     case SQLITE_ROW:
1715       ret = cb (cb_cls, name, sqlite3_column_blob (stmt, 0),
1716                 sqlite3_column_bytes (stmt, 0));
1717       break;
1718     default:
1719       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1720                   "sqlite3_step");
1721     }
1722   }
1723
1724   if (SQLITE_OK != sqlite3_reset (stmt))
1725   {
1726     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1727                 "sqlite3_reset");
1728   }
1729
1730   return ret;
1731 }
1732
1733
1734 /**
1735  * Retrieve all state variables for a channel with the given prefix.
1736  *
1737  * @see GNUNET_PSYCSTORE_state_get_prefix()
1738  *
1739  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1740  */
1741 static int
1742 state_get_prefix (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1743                   const char *name, GNUNET_PSYCSTORE_StateCallback cb,
1744                   void *cb_cls)
1745 {
1746   struct Plugin *plugin = cls;
1747   int ret = GNUNET_SYSERR;
1748   sqlite3_stmt *stmt = plugin->select_state_prefix;
1749   size_t name_len = strlen (name);
1750   char *name_prefix;
1751
1752   GNUNET_asprintf (&name_prefix,
1753                    "%s_%%",
1754                    name);
1755   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1756                                       sizeof (*channel_key), SQLITE_STATIC)
1757       || SQLITE_OK != sqlite3_bind_text (stmt, 2, name, name_len, SQLITE_STATIC)
1758       || SQLITE_OK != sqlite3_bind_text (stmt, 3, name_prefix, name_len + 2,
1759                                          SQLITE_STATIC))
1760   {
1761     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1762                 "sqlite3_bind");
1763   }
1764   else
1765   {
1766     int sql_ret;
1767     do
1768     {
1769       sql_ret = sqlite3_step (stmt);
1770       switch (sql_ret)
1771       {
1772       case SQLITE_DONE:
1773         if (ret != GNUNET_OK)
1774           ret = GNUNET_NO;
1775         break;
1776       case SQLITE_ROW:
1777         ret = cb (cb_cls, (const char *) sqlite3_column_text (stmt, 0),
1778                   sqlite3_column_blob (stmt, 1),
1779                   sqlite3_column_bytes (stmt, 1));
1780         if (ret != GNUNET_YES)
1781           sql_ret = SQLITE_DONE;
1782         break;
1783       default:
1784         LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1785                     "sqlite3_step");
1786       }
1787     }
1788     while (sql_ret == SQLITE_ROW);
1789   }
1790   if (SQLITE_OK != sqlite3_reset (stmt))
1791   {
1792     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1793                 "sqlite3_reset");
1794   }
1795   GNUNET_free (name_prefix);
1796   return ret;
1797 }
1798
1799
1800 /**
1801  * Retrieve all signed state variables for a channel.
1802  *
1803  * @see GNUNET_PSYCSTORE_state_get_signed()
1804  *
1805  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1806  */
1807 static int
1808 state_get_signed (void *cls,
1809                   const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
1810                   GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls)
1811 {
1812   struct Plugin *plugin = cls;
1813   int ret = GNUNET_SYSERR;
1814
1815   sqlite3_stmt *stmt = plugin->select_state_signed;
1816
1817   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1818                                       sizeof (*channel_key), SQLITE_STATIC))
1819   {
1820     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1821                 "sqlite3_bind");
1822   }
1823   else
1824   {
1825     int sql_ret;
1826     do
1827     {
1828       sql_ret = sqlite3_step (stmt);
1829       switch (sql_ret)
1830       {
1831       case SQLITE_DONE:
1832         if (ret != GNUNET_OK)
1833           ret = GNUNET_NO;
1834         break;
1835       case SQLITE_ROW:
1836         ret = cb (cb_cls, (const char *) sqlite3_column_text (stmt, 0),
1837                   sqlite3_column_blob (stmt, 1),
1838                   sqlite3_column_bytes (stmt, 1));
1839         if (ret != GNUNET_YES)
1840           sql_ret = SQLITE_DONE;
1841         break;
1842       default:
1843         LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1844                     "sqlite3_step");
1845       }
1846     }
1847     while (sql_ret == SQLITE_ROW);
1848   }
1849
1850   if (SQLITE_OK != sqlite3_reset (stmt))
1851   {
1852     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1853                 "sqlite3_reset");
1854   }
1855
1856   return ret;
1857 }
1858
1859
1860 /**
1861  * Entry point for the plugin.
1862  *
1863  * @param cls The struct GNUNET_CONFIGURATION_Handle.
1864  * @return NULL on error, otherwise the plugin context
1865  */
1866 void *
1867 libgnunet_plugin_psycstore_sqlite_init (void *cls)
1868 {
1869   static struct Plugin plugin;
1870   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1871   struct GNUNET_PSYCSTORE_PluginFunctions *api;
1872
1873   if (NULL != plugin.cfg)
1874     return NULL;                /* can only initialize once! */
1875   memset (&plugin, 0, sizeof (struct Plugin));
1876   plugin.cfg = cfg;
1877   if (GNUNET_OK != database_setup (&plugin))
1878   {
1879     database_shutdown (&plugin);
1880     return NULL;
1881   }
1882   api = GNUNET_new (struct GNUNET_PSYCSTORE_PluginFunctions);
1883   api->cls = &plugin;
1884   api->membership_store = &membership_store;
1885   api->membership_test = &membership_test;
1886   api->fragment_store = &fragment_store;
1887   api->message_add_flags = &message_add_flags;
1888   api->fragment_get = &fragment_get;
1889   api->fragment_get_latest = &fragment_get_latest;
1890   api->message_get = &message_get;
1891   api->message_get_latest = &message_get_latest;
1892   api->message_get_fragment = &message_get_fragment;
1893   api->counters_message_get = &counters_message_get;
1894   api->counters_state_get = &counters_state_get;
1895   api->state_modify_begin = &state_modify_begin;
1896   api->state_modify_op = &state_modify_op;
1897   api->state_modify_end = &state_modify_end;
1898   api->state_sync_begin = &state_sync_begin;
1899   api->state_sync_assign = &state_sync_assign;
1900   api->state_sync_end = &state_sync_end;
1901   api->state_reset = &state_reset;
1902   api->state_update_signed = &state_update_signed;
1903   api->state_get = &state_get;
1904   api->state_get_prefix = &state_get_prefix;
1905   api->state_get_signed = &state_get_signed;
1906
1907   LOG (GNUNET_ERROR_TYPE_INFO, _("SQLite database running\n"));
1908   return api;
1909 }
1910
1911
1912 /**
1913  * Exit point from the plugin.
1914  *
1915  * @param cls The plugin context (as returned by "init")
1916  * @return Always NULL
1917  */
1918 void *
1919 libgnunet_plugin_psycstore_sqlite_done (void *cls)
1920 {
1921   struct GNUNET_PSYCSTORE_PluginFunctions *api = cls;
1922   struct Plugin *plugin = api->cls;
1923
1924   database_shutdown (plugin);
1925   plugin->cfg = NULL;
1926   GNUNET_free (api);
1927   LOG (GNUNET_ERROR_TYPE_DEBUG, "SQLite plugin is finished\n");
1928   return NULL;
1929 }
1930
1931 /* end of plugin_psycstore_sqlite.c */