psycstore: sqlite plugin
[oweals/gnunet.git] / src / psycstore / plugin_psycstore_sqlite.c
1  /*
2   * This file is part of GNUnet
3   * (C) 2009-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 t  * 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 psycstore/plugin_psycstore_sqlite.c
23  * @brief sqlite-based psycstore backend
24  * @author Gabor X Toth
25  * @author Christian Grothoff
26  */
27
28 #include "platform.h"
29 #include "gnunet_psycstore_plugin.h"
30 #include "gnunet_psycstore_service.h"
31 #include "psycstore.h"
32 #include <sqlite3.h>
33
34 /**
35  * After how many ms "busy" should a DB operation fail for good?  A
36  * low value makes sure that we are more responsive to requests
37  * (especially PUTs).  A high value guarantees a higher success rate
38  * (SELECTs in iterate can take several seconds despite LIMIT=1).
39  *
40  * The default value of 1s should ensure that users do not experience
41  * huge latencies while at the same time allowing operations to
42  * succeed with reasonable probability.
43  */
44 #define BUSY_TIMEOUT_MS 1000
45
46
47 /**
48  * Log an error message at log-level 'level' that indicates
49  * a failure of the command 'cmd' on file 'filename'
50  * with the message given by strerror(errno).
51  */
52 #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "psycstore-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
53
54 #define LOG(kind,...) GNUNET_log_from (kind, "psycstore-sqlite", __VA_ARGS__)
55
56
57 /**
58  * Context for all functions in this plugin.
59  */
60 struct Plugin
61 {
62
63   const struct GNUNET_CONFIGURATION_Handle *cfg;
64
65   /**
66    * Database filename.
67    */
68   char *fn;
69
70   /**
71    * Native SQLite database handle.
72    */
73   sqlite3 *dbh;
74
75   /**
76    * Precompiled SQL for channel_key_store()
77    */
78   sqlite3_stmt *insert_channel_key;
79
80   /**
81    * Precompiled SQL for slave_key_store()
82    */
83   sqlite3_stmt *insert_slave_key;
84
85
86   /**
87    * Precompiled SQL for membership_store()
88    */
89   sqlite3_stmt *insert_membership;
90
91   /**
92    * Precompiled SQL for membership_test()
93    */
94   sqlite3_stmt *select_membership;
95
96
97   /**
98    * Precompiled SQL for fragment_store()
99    */
100   sqlite3_stmt *insert_fragment;
101
102   /**
103    * Precompiled SQL for fragment_add_flags()
104    */
105   sqlite3_stmt *update_fragment_flags;
106
107   /**
108    * Precompiled SQL for fragment_get()
109    */
110   sqlite3_stmt *select_fragment;
111
112   /**
113    * Precompiled SQL for message_get()
114    */
115   sqlite3_stmt *select_message;
116
117   /**
118    * Precompiled SQL for message_get_fragment()
119    */
120   sqlite3_stmt *select_message_fragment;
121
122   /**
123    * Precompiled SQL for counters_get_master()
124    */
125   sqlite3_stmt *select_master_counters;
126
127   /**
128    * Precompiled SQL for counters_get_slave()
129    */
130   sqlite3_stmt *select_slave_counters;
131
132
133   /**
134    * Precompiled SQL for state_set()
135    */
136   sqlite3_stmt *insert_state_current;
137
138   /**
139    * Precompiled SQL for state_set()
140    */
141   sqlite3_stmt *update_state_current;
142
143   /**
144    * Precompiled SQL for state_set_signed()
145    */
146   sqlite3_stmt *update_state_signed;
147
148   /**
149    * Precompiled SQL for state_sync()
150    */
151   sqlite3_stmt *insert_state_sync;
152
153   /**
154    * Precompiled SQL for state_sync()
155    */
156   sqlite3_stmt *delete_state;
157
158   /**
159    * Precompiled SQL for state_sync()
160    */
161   sqlite3_stmt *insert_state_from_sync;
162
163   /**
164    * Precompiled SQL for state_sync()
165    */
166   sqlite3_stmt *delete_state_sync;
167
168   /**
169    * Precompiled SQL for state_get()
170    */
171   sqlite3_stmt *select_state_one;
172
173   /**
174    * Precompiled SQL for state_get_all()
175    */
176   sqlite3_stmt *select_state_prefix;
177
178 };
179
180
181 /**
182  * @brief Prepare a SQL statement
183  *
184  * @param dbh handle to the database
185  * @param sql SQL statement, UTF-8 encoded
186  * @param stmt set to the prepared statement
187  * @return 0 on success
188  */
189 static int
190 sql_prepare (sqlite3 *dbh, const char *sql, sqlite3_stmt **stmt)
191 {
192   char *tail;
193   int result;
194
195   result = sqlite3_prepare_v2 (dbh, sql, strlen (sql), stmt,
196                                (const char **) &tail);
197   LOG (GNUNET_ERROR_TYPE_DEBUG, 
198        "Prepared `%s' / %p: %d\n", sql, *stmt, result);
199   if (result != SQLITE_OK)
200     LOG (GNUNET_ERROR_TYPE_ERROR,
201          _("Error preparing SQL query: %s\n  %s\n"),
202          sqlite3_errmsg (dbh), sql);
203   return result;
204 }
205
206
207 /**
208  * @brief Prepare a SQL statement
209  *
210  * @param dbh handle to the database
211  * @param zSql SQL statement, UTF-8 encoded
212  * @param ppStmt set to the prepared statement
213  * @return 0 on success
214  */
215 static int
216 sql_exec (sqlite3 *dbh, const char *sql)
217 {
218   int result;
219
220   result = sqlite3_exec (dbh, sql, NULL, NULL, NULL);
221   LOG (GNUNET_ERROR_TYPE_DEBUG, 
222        "Executed `%s' / %d\n", sql, result);
223   if (result != SQLITE_OK)
224     LOG (GNUNET_ERROR_TYPE_ERROR,
225          _("Error executing SQL query: %s\n  %s\n"),
226          sqlite3_errmsg (dbh), sql);
227   return result;
228 }
229
230
231 /**
232  * Initialize the database connections and associated
233  * data structures (create tables and indices
234  * as needed as well).
235  *
236  * @param plugin the plugin context (state for this module)
237  * @return GNUNET_OK on success
238  */
239 static int
240 database_setup (struct Plugin *plugin)
241 {
242   char *filename;
243
244   if (GNUNET_OK !=
245       GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "psycstore-sqlite",
246                                                "FILENAME", &filename))
247   {
248     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
249                                "psycstore-sqlite", "FILENAME");
250     return GNUNET_SYSERR;
251   }
252   if (GNUNET_OK != GNUNET_DISK_file_test (filename))
253   {
254     if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (filename))
255     {
256       GNUNET_break (0);
257       GNUNET_free (filename);
258       return GNUNET_SYSERR;
259     }
260   }
261   /* filename should be UTF-8-encoded. If it isn't, it's a bug */
262   plugin->fn = filename;
263
264   /* Open database and precompile statements */
265   if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
266   {
267     LOG (GNUNET_ERROR_TYPE_ERROR,
268          _("Unable to initialize SQLite: %s.\n"),
269          sqlite3_errmsg (plugin->dbh));
270     return GNUNET_SYSERR;
271   }
272
273   sql_exec (plugin->dbh, "PRAGMA temp_store=MEMORY");
274   sql_exec (plugin->dbh, "PRAGMA synchronous=NORMAL");
275   sql_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF");
276   sql_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL");
277   sql_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\"");
278   sql_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE");
279   sql_exec (plugin->dbh, "PRAGMA count_changes=OFF");
280   sql_exec (plugin->dbh, "PRAGMA page_size=4096");
281
282   sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS);
283
284   /* Create tables */
285
286   sql_exec (plugin->dbh,
287             "CREATE TABLE IF NOT EXISTS channels ("
288             "  id INTEGER PRIMARY KEY,"
289             "  pub_key BLOB UNIQUE"
290             ");");
291
292   sql_exec (plugin->dbh,
293             "CREATE TABLE IF NOT EXISTS slaves ("
294             "  id INTEGER PRIMARY KEY,"
295             "  pub_key BLOB UNIQUE"
296             ");");
297
298   sql_exec (plugin->dbh,
299             "CREATE TABLE IF NOT EXISTS membership ("
300             "  channel_id INTEGER NOT NULL REFERENCES channels(id),"
301             "  slave_id INTEGER NOT NULL REFERENCES slaves(id),"
302             "  did_join INTEGER NOT NULL,"
303             "  announced_at INTEGER NOT NULL,"
304             "  effective_since INTEGER NOT NULL,"
305             "  group_generation INTEGER NOT NULL"
306             ");");
307   sql_exec (plugin->dbh,
308             "CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id "
309             "ON membership (channel_id, slave_id);");
310
311   sql_exec (plugin->dbh,
312             "CREATE TABLE IF NOT EXISTS messages ("
313             "  channel_id INTEGER NOT NULL,"
314             "  hop_counter INTEGER NOT NULL,"
315             "  signature BLOB,"
316             "  purpose BLOB,"
317             "  fragment_id INTEGER NOT NULL,"
318             "  fragment_offset INTEGER NOT NULL,"
319             "  message_id INTEGER NOT NULL,"
320             "  group_generation INTEGER NOT NULL,"
321             "  multicast_flags INTEGER NOT NULL,"
322             "  psyc_flags INTEGER NOT NULL,"
323             "  data BLOB,"
324             "  PRIMARY KEY (channel_id, fragment_id),"
325             "  UNIQUE (channel_id, message_id, fragment_offset)"
326             ");");
327
328   sql_exec (plugin->dbh,
329             "CREATE TABLE IF NOT EXISTS state ("
330             "  channel_id INTEGER NOT NULL,"
331             "  name TEXT NOT NULL,"
332             "  value_current BLOB, "
333             "  value_signed BLOB, "
334             "  PRIMARY KEY (channel_id, name)"
335             ");");
336
337   sql_exec (plugin->dbh,
338             "CREATE TABLE IF NOT EXISTS state_sync ("
339             "  channel_id INTEGER NOT NULL,"
340             "  name TEXT NOT NULL,"
341             "  value BLOB, "
342             "  PRIMARY KEY (channel_id, name)"
343             ");");
344
345   /* Prepare statements */
346
347   sql_prepare (plugin->dbh,
348                "INSERT OR IGNORE INTO channels (pub_key) VALUES (?);",
349                &plugin->insert_channel_key);
350
351   sql_prepare (plugin->dbh,
352                "INSERT OR IGNORE INTO slaves (pub_key) VALUES (?);",
353                &plugin->insert_slave_key);
354
355   sql_prepare (plugin->dbh,
356                "INSERT INTO membership "
357                " (channel_id, slave_id, did_join, announced_at, "
358                "  effective_since, group_generation) "
359                "VALUES ((SELECT id FROM channels WHERE pub_key = ?), "
360                "        (SELECT id FROM slaves WHERE pub_key = ?), "
361                "        ?, ?, ?, ?);",
362                &plugin->insert_membership);
363
364   sql_prepare (plugin->dbh,
365                "SELECT did_join FROM membership "
366                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
367                "      AND slave_id = ? AND effective_since <= ? "
368                "ORDER BY announced_at DESC LIMIT 1;",
369                &plugin->select_membership);
370
371   sql_prepare (plugin->dbh,
372                "INSERT INTO messages "
373                " (channel_id, hop_counter, signature, purpose, "
374                "  fragment_id, fragment_offset, message_id, "
375                "  group_generation, multicast_flags, psyc_flags, data) "
376                "VALUES ((SELECT id FROM channels WHERE pub_key = ?), "
377                "        ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
378                &plugin->insert_fragment);
379
380   sql_prepare (plugin->dbh,
381                "UPDATE messages "
382                "SET multicast_flags = multicast_flags | ?, "
383                "    psyc_flags = psyc_flags | ? "
384                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
385                "      AND message_id = ?;",
386                &plugin->update_fragment_flags);
387
388   sql_prepare (plugin->dbh,
389                "SELECT hop_counter, signature, purpose, "
390                "       fragment_offset, message_id, group_generation, "
391                "       multicast_flags, psyc_flags, data "
392                "FROM messages "
393                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
394                "      AND fragment_id = ?;",
395                &plugin->select_fragment);
396
397   sql_prepare (plugin->dbh,
398                "SELECT hop_counter, signature, purpose, "
399                "       fragment_id, fragment_offset, group_generation, "
400                "       multicast_flags, psyc_flags, data "
401                "FROM messages "
402                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
403                "      AND message_id = ?;",
404                &plugin->select_message);
405
406   sql_prepare (plugin->dbh,
407                "SELECT hop_counter, signature, purpose, "
408                "       fragment_id, message_id, group_generation, "
409                "       multicast_flags, psyc_flags, data "
410                "FROM messages "
411                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
412                "      AND message_id = ? AND fragment_offset = ?;",
413                &plugin->select_message_fragment);
414
415   sql_prepare (plugin->dbh,
416                "SELECT max(fragment_id), max(message_id), max(group_generation) "
417                "FROM messages "
418                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
419                &plugin->select_master_counters);
420
421   sql_prepare (plugin->dbh,
422                "SELECT max(message_id) "
423                "FROM messages "
424                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
425                "      AND psyc_flags & ?;",
426                &plugin->select_slave_counters);
427
428   sql_prepare (plugin->dbh,
429                "INSERT OR REPLACE INTO state (channel_id, name, value_current) "
430                "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);",
431                &plugin->insert_state_current);
432
433   sql_prepare (plugin->dbh,
434                "UPDATE state "
435                "SET value_current = ? "
436                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
437                "      AND name = ?;",
438                &plugin->update_state_current);
439
440   sql_prepare (plugin->dbh,
441                "UPDATE state "
442                "SET value_signed = value_current "
443                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) ",
444                &plugin->update_state_signed);
445
446   sql_prepare (plugin->dbh,
447                "INSERT INTO state_sync (channel_id, name, value) "
448                "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);",
449                &plugin->insert_state_sync);
450
451   sql_prepare (plugin->dbh,
452                "DELETE FROM state "
453                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
454                &plugin->delete_state);
455
456   sql_prepare (plugin->dbh,
457                "INSERT INTO state "
458                " (channel_id, name, value_current, value_signed) "
459                "SELECT channel_id, name, value, value "
460                "FROM state_sync "
461                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
462                &plugin->insert_state_from_sync);
463
464   sql_prepare (plugin->dbh,
465                "DELETE FROM state_sync "
466                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
467                &plugin->delete_state_sync);
468
469   sql_prepare (plugin->dbh,
470                "SELECT value_current "
471                "FROM state "
472                "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
473                "      AND name = ?;",
474                &plugin->select_state_one);
475
476   sql_prepare (plugin->dbh,
477                "SELECT value_current "
478                "FROM state "
479                "WHERE name LIKE ? OR name LIKE ?;",
480                &plugin->select_state_prefix);
481
482   return GNUNET_OK;
483 }
484
485
486 /**
487  * Shutdown database connection and associate data
488  * structures.
489  * @param plugin the plugin context (state for this module)
490  */
491 static void
492 database_shutdown (struct Plugin *plugin)
493 {
494   int result;
495   sqlite3_stmt *stmt;
496
497   if (NULL != plugin->insert_channel_key)
498     sqlite3_finalize (plugin->insert_channel_key);
499
500   if (NULL != plugin->insert_slave_key)
501     sqlite3_finalize (plugin->insert_slave_key);
502
503   if (NULL != plugin->insert_membership)
504     sqlite3_finalize (plugin->insert_membership);
505
506   if (NULL != plugin->select_membership)
507     sqlite3_finalize (plugin->select_membership);
508
509   if (NULL != plugin->insert_fragment)
510     sqlite3_finalize (plugin->insert_fragment);
511
512   if (NULL != plugin->update_fragment_flags)
513     sqlite3_finalize (plugin->update_fragment_flags);
514
515   if (NULL != plugin->select_fragment)
516     sqlite3_finalize (plugin->select_fragment);
517
518   if (NULL != plugin->select_message)
519     sqlite3_finalize (plugin->select_message);
520
521   if (NULL != plugin->select_message_fragment)
522     sqlite3_finalize (plugin->select_message_fragment);
523
524   if (NULL != plugin->select_master_counters)
525     sqlite3_finalize (plugin->select_master_counters);
526
527   if (NULL != plugin->select_slave_counters)
528     sqlite3_finalize (plugin->select_slave_counters);
529
530   if (NULL != plugin->insert_state_current)
531     sqlite3_finalize (plugin->insert_state_current);
532
533   if (NULL != plugin->update_state_current)
534     sqlite3_finalize (plugin->update_state_current);
535
536   if (NULL != plugin->update_state_signed)
537     sqlite3_finalize (plugin->update_state_signed);
538
539   if (NULL != plugin->insert_state_sync)
540     sqlite3_finalize (plugin->insert_state_sync);
541
542   if (NULL != plugin->delete_state)
543     sqlite3_finalize (plugin->delete_state);
544
545   if (NULL != plugin->insert_state_from_sync)
546     sqlite3_finalize (plugin->insert_state_from_sync);
547
548   if (NULL != plugin->delete_state_sync)
549     sqlite3_finalize (plugin->delete_state_sync);
550
551   if (NULL != plugin->select_state_one)
552     sqlite3_finalize (plugin->select_state_one);
553
554   if (NULL != plugin->select_state_prefix)
555     sqlite3_finalize (plugin->select_state_prefix);
556
557   result = sqlite3_close (plugin->dbh);
558   if (result == SQLITE_BUSY)
559   {
560     LOG (GNUNET_ERROR_TYPE_WARNING,
561          _("Tried to close sqlite without finalizing all prepared statements.\n"));
562     stmt = sqlite3_next_stmt (plugin->dbh, NULL);
563     while (stmt != NULL)
564     {
565       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
566                        "Closing statement %p\n", stmt);
567       result = sqlite3_finalize (stmt);
568       if (result != SQLITE_OK)
569         GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite",
570                          "Failed to close statement %p: %d\n", stmt, result);
571       stmt = sqlite3_next_stmt (plugin->dbh, NULL);
572     }
573     result = sqlite3_close (plugin->dbh);
574   }
575   if (SQLITE_OK != result)
576     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
577
578   GNUNET_free_non_null (plugin->fn);
579 }
580
581
582 /** 
583  * Store join/leave events for a PSYC channel in order to be able to answer
584  * membership test queries later.
585  *
586  * @see GNUNET_PSYCSTORE_membership_store()
587  *
588  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
589  */
590 int
591 libgnunet_plugin_psycstore_sqlite_membership_store
592  (void *cls, 
593   const struct GNUNET_HashCode *channel_key,
594   const struct GNUNET_HashCode *slave_key,
595   int did_join,
596   uint64_t announced_at,
597   uint64_t effective_since,
598   uint64_t group_generation) {
599
600
601 }
602
603 /** 
604  * Test if a member was admitted to the channel at the given message ID.
605  *
606  * @see GNUNET_PSYCSTORE_membership_test()
607  * 
608  * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not,
609  *         #GNUNET_SYSERR if there was en error.
610  */
611 int
612 libgnunet_plugin_psycstore_sqlite_membership_test
613  (void *cls,
614   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
615   const struct GNUNET_CRYPTO_EccPublicKey *slave_key,
616   uint64_t message_id,
617   uint64_t group_generation) {
618
619 }
620
621 /** 
622  * Store a message fragment sent to a channel.
623  *
624  * @see GNUNET_PSYCSTORE_fragment_store()
625  * 
626  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
627  */
628 int
629 libgnunet_plugin_psycstore_sqlite_fragment_store
630  (void *cls,
631   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
632   const struct GNUNET_MULTICAST_MessageHeader *message) {
633
634 }
635
636 /** 
637  * Set additional flags for a given message.
638  *
639  * @param message_id ID of the message.
640  * @param flags Flags to add.
641  * 
642  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
643  */
644 int
645 libgnunet_plugin_psycstore_sqlite_fragment_add_flags
646  (void *cls,
647   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
648   uint64_t message_id,
649   uint64_t multicast_flags,
650   uint64_t psyc_flags) {
651
652 }
653
654 /** 
655  * Retrieve a message fragment by fragment ID.
656  *
657  * @see GNUNET_PSYCSTORE_fragment_get()
658  * 
659  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
660  */
661 int
662 libgnunet_plugin_psycstore_sqlite_fragment_get
663  (void *cls,
664   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
665   uint64_t fragment_id,
666   GNUNET_PSYCSTORE_FragmentCallback cb,
667   void *cb_cls) {
668
669 }
670
671 /** 
672  * Retrieve all fragments of a message.
673  *
674  * @see GNUNET_PSYCSTORE_message_get()
675  * 
676  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
677  */
678 int
679 libgnunet_plugin_psycstore_sqlite_message_get
680  (void *cls,
681   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
682   uint64_t message_id,
683   GNUNET_PSYCSTORE_FragmentCallback cb,
684   void *cb_cls) {
685
686 }
687
688 /** 
689  * Retrieve a fragment of message specified by its message ID and fragment
690  * offset.
691  *
692  * @see GNUNET_PSYCSTORE_message_get_fragment()
693  * 
694  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
695  */
696 int
697 libgnunet_plugin_psycstore_sqlite_message_get_fragment
698  (void *cls,
699   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
700   uint64_t message_id,
701   uint64_t fragment_offset,
702   GNUNET_PSYCSTORE_FragmentCallback cb,
703   void *cb_cls)
704 {
705
706 }
707
708 /** 
709  * Retrieve latest values of counters for a channel master.
710  *
711  * @see GNUNET_PSYCSTORE_counters_get_master()
712  * 
713  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
714  */
715 int
716 libgnunet_plugin_psycstore_sqlite_counters_get_master
717  (void *cls,
718   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
719   uint64_t *fragment_id,
720   uint64_t *message_id,
721   uint64_t *group_generation)
722 {
723
724 }
725
726 /** 
727  * Retrieve latest values of counters for a channel slave. 
728  *
729  * @see GNUNET_PSYCSTORE_counters_get_slave()
730  * 
731  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
732  */
733 int
734 libgnunet_plugin_psycstore_sqlite_counters_get_slave
735  (void *cls,
736   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
737   uint64_t *max_state_msg_id) {
738
739 }
740
741 /** 
742  * Set a state variable to the given value.
743  *
744  * @see GNUNET_PSYCSTORE_state_modify()
745  * 
746  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
747  */
748 int
749 libgnunet_plugin_psycstore_sqlite_state_set
750  (struct GNUNET_PSYCSTORE_Handle *h,
751   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
752   const char *name,
753   size_t value_size,
754   const void *value) {
755
756 }
757
758 /** 
759  * Retrieve a state variable by name.
760  *
761  * @param name Name of the variable to retrieve.
762  * @param[out] value_size Size of value.
763  * @param[out] value Returned value.
764  * 
765  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
766  */
767 int
768 libgnunet_plugin_psycstore_sqlite_state_get
769  (struct GNUNET_PSYCSTORE_Handle *h,
770   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
771   const char *name,
772   GNUNET_PSYCSTORE_StateCallback cb,
773   void *cb_cls) {
774
775 }
776
777 /** 
778  * Retrieve all state variables for a channel with the given prefix.
779  *
780  * @see GNUNET_PSYCSTORE_state_get_all()
781  * 
782  * @return #GNUNET_OK on success, else #GNUNET_SYSERR
783  */
784 int
785 libgnunet_plugin_psycstore_sqlite_state_get_all
786  (struct GNUNET_PSYCSTORE_Handle *h,
787   const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
788   const char *name,
789   GNUNET_PSYCSTORE_StateCallback cb,
790   void *cb_cls) {
791
792 }
793
794
795 /**
796  * Entry point for the plugin.
797  *
798  * @param cls the "struct GNUNET_PSYCSTORE_PluginEnvironment*"
799  * @return NULL on error, otherwise the plugin context
800  */
801 void *
802 libgnunet_plugin_psycstore_sqlite_init (void *cls)
803 {
804   static struct Plugin plugin;
805   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
806   struct GNUNET_PSYCSTORE_PluginFunctions *api;
807
808   if (NULL != plugin.cfg)
809     return NULL;                /* can only initialize once! */
810   memset (&plugin, 0, sizeof (struct Plugin));
811   plugin.cfg = cfg;  
812   if (GNUNET_OK != database_setup (&plugin))
813   {
814     database_shutdown (&plugin);
815     return NULL;
816   }
817   api = GNUNET_new (struct GNUNET_PSYCSTORE_PluginFunctions);
818   api->cls = &plugin;
819   api->membership_store = &libgnunet_plugin_psycstore_sqlite_membership_store;
820   api->membership_test = &libgnunet_plugin_psycstore_sqlite_membership_test;
821   api->fragment_store = &libgnunet_plugin_psycstore_sqlite_fragment_store;
822   api->fragment_add_flags = &libgnunet_plugin_psycstore_sqlite_fragment_add_flags;
823   api->fragment_get = &libgnunet_plugin_psycstore_sqlite_fragment_get;
824   api->message_get = &libgnunet_plugin_psycstore_sqlite_message_get;
825   api->message_get_fragment = &libgnunet_plugin_psycstore_sqlite_message_get_fragment;
826   api->counters_get_master = &libgnunet_plugin_psycstore_sqlite_counters_get_master;
827   api->counters_get_slave = &libgnunet_plugin_psycstore_sqlite_counters_get_slave;
828   api->state_set = &libgnunet_plugin_psycstore_sqlite_state_set;
829   api->state_get = &libgnunet_plugin_psycstore_sqlite_state_get;
830   api->state_get_all = &libgnunet_plugin_psycstore_sqlite_state_get_all;
831
832   LOG (GNUNET_ERROR_TYPE_INFO, 
833        _("Sqlite database running\n"));
834   return api;
835 }
836
837
838 /**
839  * Exit point from the plugin.
840  *
841  * @param cls the plugin context (as returned by "init")
842  * @return always NULL
843  */
844 void *
845 libgnunet_plugin_psycstore_sqlite_done (void *cls)
846 {
847   struct GNUNET_PSYCSTORE_PluginFunctions *api = cls;
848   struct Plugin *plugin = api->cls;
849
850   database_shutdown (plugin);
851   plugin->cfg = NULL;
852   GNUNET_free (api);
853   LOG (GNUNET_ERROR_TYPE_DEBUG, 
854        "sqlite plugin is finished\n");
855   return NULL;
856 }
857
858 /* end of plugin_psycstore_sqlite.c */