diff options
author | Gabor X Toth <*@tg-x.net> | 2013-08-29 15:14:17 +0000 |
---|---|---|
committer | Gabor X Toth <*@tg-x.net> | 2013-08-29 15:14:17 +0000 |
commit | 81eaa5a9d5ebe1e61790069a2777178abd1b6a2c (patch) | |
tree | 2b24561b930dca7ede2d27590e1c434fe19ed365 /src/psycstore | |
parent | b1ed5b9a472bd56796646a70068eb48da0db3e2f (diff) | |
download | gnunet-81eaa5a9d5ebe1e61790069a2777178abd1b6a2c.tar.gz gnunet-81eaa5a9d5ebe1e61790069a2777178abd1b6a2c.zip |
psycstore: sqlite plugin
Diffstat (limited to 'src/psycstore')
-rw-r--r-- | src/psycstore/Makefile.am | 63 | ||||
-rw-r--r-- | src/psycstore/gnunet-service-psycstore.c | 44 | ||||
-rw-r--r-- | src/psycstore/plugin_psycstore_sqlite.c | 858 | ||||
-rw-r--r-- | src/psycstore/psycstore.conf | 5 | ||||
-rw-r--r-- | src/psycstore/psycstore_api.c | 71 |
5 files changed, 969 insertions, 72 deletions
diff --git a/src/psycstore/Makefile.am b/src/psycstore/Makefile.am index 461ec6c4e..48f8d5ff7 100644 --- a/src/psycstore/Makefile.am +++ b/src/psycstore/Makefile.am | |||
@@ -1,13 +1,6 @@ | |||
1 | INCLUDES = -I$(top_srcdir)/src/include | 1 | INCLUDES = -I$(top_srcdir)/src/include |
2 | 2 | ||
3 | if MINGW | 3 | plugindir = $(libdir)/gnunet |
4 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
5 | endif | ||
6 | |||
7 | if USE_COVERAGE | ||
8 | AM_CFLAGS = --coverage -O0 | ||
9 | XLIB = -lgcov | ||
10 | endif | ||
11 | 4 | ||
12 | pkgcfgdir= $(pkgdatadir)/config.d/ | 5 | pkgcfgdir= $(pkgdatadir)/config.d/ |
13 | 6 | ||
@@ -17,6 +10,22 @@ pkgcfg_DATA = \ | |||
17 | psycstore.conf | 10 | psycstore.conf |
18 | 11 | ||
19 | 12 | ||
13 | if MINGW | ||
14 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
15 | endif | ||
16 | |||
17 | if USE_COVERAGE | ||
18 | AM_CFLAGS = --coverage -O0 | ||
19 | XLIB = -lgcov | ||
20 | endif | ||
21 | |||
22 | if HAVE_SQLITE | ||
23 | SQLITE_PLUGIN = libgnunet_plugin_psycstore_sqlite.la | ||
24 | if HAVE_TESTING | ||
25 | #SQLITE_TESTS = test_plugin_psycstore_sqlite | ||
26 | endif | ||
27 | endif | ||
28 | |||
20 | lib_LTLIBRARIES = libgnunetpsycstore.la | 29 | lib_LTLIBRARIES = libgnunetpsycstore.la |
21 | 30 | ||
22 | libgnunetpsycstore_la_SOURCES = \ | 31 | libgnunetpsycstore_la_SOURCES = \ |
@@ -29,30 +38,50 @@ libgnunetpsycstore_la_LDFLAGS = \ | |||
29 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | 38 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ |
30 | -version-info 0:0:0 | 39 | -version-info 0:0:0 |
31 | libgnunetpsycstore_la_DEPENDENCIES = \ | 40 | libgnunetpsycstore_la_DEPENDENCIES = \ |
32 | $(top_builddir)/src/util/libgnunetutil.la | 41 | $(top_builddir)/src/util/libgnunetutil.la |
33 | 42 | ||
34 | bin_PROGRAMS = | 43 | bin_PROGRAMS = |
35 | 44 | ||
36 | libexec_PROGRAMS = \ | 45 | libexec_PROGRAMS = \ |
37 | gnunet-service-psycstore | 46 | gnunet-service-psycstore |
38 | 47 | ||
39 | gnunet_service_psycstore_SOURCES = \ | 48 | gnunet_service_psycstore_SOURCES = \ |
40 | gnunet-service-psycstore.c | 49 | gnunet-service-psycstore.c |
41 | gnunet_service_psycstore_LDADD = \ | 50 | gnunet_service_psycstore_LDADD = \ |
42 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 51 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
43 | $(top_builddir)/src/util/libgnunetutil.la \ | 52 | $(top_builddir)/src/util/libgnunetutil.la \ |
44 | $(GN_LIBINTL) | 53 | $(GN_LIBINTL) |
45 | gnunet_service_psycstore_DEPENDENCIES = \ | 54 | gnunet_service_psycstore_DEPENDENCIES = \ |
46 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 55 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
47 | $(top_builddir)/src/util/libgnunetutil.la | 56 | $(top_builddir)/src/util/libgnunetutil.la |
57 | |||
58 | |||
59 | plugin_LTLIBRARIES = \ | ||
60 | $(SQLITE_PLUGIN) | ||
61 | |||
62 | libgnunet_plugin_psycstore_sqlite_la_SOURCES = \ | ||
63 | plugin_psycstore_sqlite.c | ||
64 | libgnunet_plugin_psycstore_sqlite_la_LIBADD = \ | ||
65 | $(top_builddir)/src/psycstore/libgnunetpsycstore.la \ | ||
66 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
67 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ | ||
68 | $(LTLIBINTL) | ||
69 | libgnunet_plugin_psycstore_sqlite_la_LDFLAGS = \ | ||
70 | $(GN_PLUGIN_LDFLAGS) | ||
71 | libgnunet_plugin_psycstore_sqlite_la_DEPENDENCIES = \ | ||
72 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
73 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
74 | libgnunetpsycstore.la | ||
75 | |||
48 | 76 | ||
49 | if HAVE_TESTING | 77 | if HAVE_TESTING |
50 | check_PROGRAMS = \ | 78 | check_PROGRAMS = \ |
51 | test_psycstore | 79 | test_psycstore \ |
80 | $(SQLITE_TESTS) | ||
52 | endif | 81 | endif |
53 | 82 | ||
54 | if ENABLE_TEST_RUN | 83 | if ENABLE_TEST_RUN |
55 | TESTS = $(check_PROGRAMS) | 84 | TESTS = $(check_PROGRAMS) |
56 | endif | 85 | endif |
57 | 86 | ||
58 | test_psycstore_SOURCES = \ | 87 | test_psycstore_SOURCES = \ |
@@ -60,13 +89,13 @@ test_psycstore_SOURCES = \ | |||
60 | test_psycstore_LDADD = \ | 89 | test_psycstore_LDADD = \ |
61 | libgnunetpsycstore.la \ | 90 | libgnunetpsycstore.la \ |
62 | $(top_builddir)/src/testing/libgnunettesting.la \ | 91 | $(top_builddir)/src/testing/libgnunettesting.la \ |
63 | $(top_builddir)/src/util/libgnunetutil.la | 92 | $(top_builddir)/src/util/libgnunetutil.la |
64 | test_psycstore_DEPENDENCIES = \ | 93 | test_psycstore_DEPENDENCIES = \ |
65 | libgnunetpsycstore.la \ | 94 | libgnunetpsycstore.la \ |
66 | $(top_builddir)/src/testing/libgnunettesting.la \ | 95 | $(top_builddir)/src/testing/libgnunettesting.la \ |
67 | $(top_builddir)/src/util/libgnunetutil.la | 96 | $(top_builddir)/src/util/libgnunetutil.la |
68 | 97 | ||
69 | EXTRA_DIST = \ | 98 | EXTRA_DIST = \ |
70 | test_psycstore.conf | 99 | test_psycstore.conf |
71 | 100 | ||
72 | 101 | ||
diff --git a/src/psycstore/gnunet-service-psycstore.c b/src/psycstore/gnunet-service-psycstore.c index 977f77e06..d8f7a2690 100644 --- a/src/psycstore/gnunet-service-psycstore.c +++ b/src/psycstore/gnunet-service-psycstore.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "gnunet_protocols.h" | 34 | #include "gnunet_protocols.h" |
35 | #include "gnunet_statistics_service.h" | 35 | #include "gnunet_statistics_service.h" |
36 | #include "gnunet_psycstore_service.h" | 36 | #include "gnunet_psycstore_service.h" |
37 | #include "gnunet_psycstore_plugin.h" | ||
37 | #include "psycstore.h" | 38 | #include "psycstore.h" |
38 | 39 | ||
39 | 40 | ||
@@ -53,9 +54,14 @@ static struct GNUNET_STATISTICS_Handle *stats; | |||
53 | static struct GNUNET_SERVER_NotificationContext *nc; | 54 | static struct GNUNET_SERVER_NotificationContext *nc; |
54 | 55 | ||
55 | /** | 56 | /** |
56 | * Database file. | 57 | * Database handle |
57 | */ | 58 | */ |
58 | static char *db_file; | 59 | static struct GNUNET_PSYCSTORE_PluginFunctions *db; |
60 | |||
61 | /** | ||
62 | * Name of the database plugin | ||
63 | */ | ||
64 | static char *db_lib_name; | ||
59 | 65 | ||
60 | 66 | ||
61 | /** | 67 | /** |
@@ -77,8 +83,9 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
77 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | 83 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); |
78 | stats = NULL; | 84 | stats = NULL; |
79 | } | 85 | } |
80 | GNUNET_free (db_file); | 86 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db)); |
81 | db_file = NULL; | 87 | GNUNET_free (db_lib_name); |
88 | db_lib_name = NULL; | ||
82 | } | 89 | } |
83 | 90 | ||
84 | 91 | ||
@@ -123,7 +130,7 @@ send_result_code (struct GNUNET_SERVER_Client *client, | |||
123 | * @param c configuration to use | 130 | * @param c configuration to use |
124 | */ | 131 | */ |
125 | static void | 132 | static void |
126 | run (void *cls, | 133 | run (void *cls, |
127 | struct GNUNET_SERVER_Handle *server, | 134 | struct GNUNET_SERVER_Handle *server, |
128 | const struct GNUNET_CONFIGURATION_Handle *c) | 135 | const struct GNUNET_CONFIGURATION_Handle *c) |
129 | { | 136 | { |
@@ -132,15 +139,30 @@ run (void *cls, | |||
132 | }; | 139 | }; |
133 | 140 | ||
134 | cfg = c; | 141 | cfg = c; |
142 | |||
143 | /* Loading database plugin */ | ||
144 | char *database; | ||
135 | if (GNUNET_OK != | 145 | if (GNUNET_OK != |
136 | GNUNET_CONFIGURATION_get_value_filename (cfg, "psycstore", | 146 | GNUNET_CONFIGURATION_get_value_string (cfg, "psycstore", "database", |
137 | "DB_FILE", | 147 | &database)) |
138 | &db_file)) | 148 | { |
149 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); | ||
150 | } | ||
151 | else | ||
139 | { | 152 | { |
140 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "psycstore", "DB_FILE"); | 153 | GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_psycstore_%s", database); |
141 | GNUNET_SCHEDULER_shutdown (); | 154 | db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); |
155 | GNUNET_free (database); | ||
156 | } | ||
157 | if (NULL == db) | ||
158 | { | ||
159 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
160 | "Could not load database backend `%s'\n", | ||
161 | db_lib_name); | ||
162 | GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
142 | return; | 163 | return; |
143 | } | 164 | } |
165 | |||
144 | stats = GNUNET_STATISTICS_create ("psycstore", cfg); | 166 | stats = GNUNET_STATISTICS_create ("psycstore", cfg); |
145 | GNUNET_SERVER_add_handlers (server, handlers); | 167 | GNUNET_SERVER_add_handlers (server, handlers); |
146 | nc = GNUNET_SERVER_notification_context_create (server, 1); | 168 | nc = GNUNET_SERVER_notification_context_create (server, 1); |
@@ -160,7 +182,7 @@ int | |||
160 | main (int argc, char *const *argv) | 182 | main (int argc, char *const *argv) |
161 | { | 183 | { |
162 | return (GNUNET_OK == | 184 | return (GNUNET_OK == |
163 | GNUNET_SERVICE_run (argc, argv, "psycstore", | 185 | GNUNET_SERVICE_run (argc, argv, "psycstore", |
164 | GNUNET_SERVICE_OPTION_NONE, | 186 | GNUNET_SERVICE_OPTION_NONE, |
165 | &run, NULL)) ? 0 : 1; | 187 | &run, NULL)) ? 0 : 1; |
166 | } | 188 | } |
diff --git a/src/psycstore/plugin_psycstore_sqlite.c b/src/psycstore/plugin_psycstore_sqlite.c new file mode 100644 index 000000000..8bec31f12 --- /dev/null +++ b/src/psycstore/plugin_psycstore_sqlite.c | |||
@@ -0,0 +1,858 @@ | |||
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 */ | ||
diff --git a/src/psycstore/psycstore.conf b/src/psycstore/psycstore.conf index 7bfe6e126..5b8dfee68 100644 --- a/src/psycstore/psycstore.conf +++ b/src/psycstore/psycstore.conf | |||
@@ -5,6 +5,7 @@ BINARY = gnunet-service-psycstore | |||
5 | UNIXPATH = /tmp/gnunet-service-psycstore.unix | 5 | UNIXPATH = /tmp/gnunet-service-psycstore.unix |
6 | UNIX_MATCH_UID = NO | 6 | UNIX_MATCH_UID = NO |
7 | UNIX_MATCH_GID = YES | 7 | UNIX_MATCH_GID = YES |
8 | DATABASE = sqlite | ||
8 | 9 | ||
9 | # Path to the SQLite database | 10 | [psycstore-sqlite] |
10 | DB_FILE = $SERVICEHOME/psycstore.sqlite | 11 | FILENAME = $SERVICEHOME/psycstore/sqlite.db |
diff --git a/src/psycstore/psycstore_api.c b/src/psycstore/psycstore_api.c index b31b96c3b..d8d5134b6 100644 --- a/src/psycstore/psycstore_api.c +++ b/src/psycstore/psycstore_api.c | |||
@@ -340,22 +340,8 @@ reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
340 | GNUNET_assert (NULL == h->client); | 340 | GNUNET_assert (NULL == h->client); |
341 | h->client = GNUNET_CLIENT_connect ("psycstore", h->cfg); | 341 | h->client = GNUNET_CLIENT_connect ("psycstore", h->cfg); |
342 | GNUNET_assert (NULL != h->client); | 342 | GNUNET_assert (NULL != h->client); |
343 | /* | ||
344 | struct GNUNET_PSYCSTORE_OperationHandle *op; | ||
345 | struct GNUNET_MessageHeader msg; | ||
346 | op = GNUNET_malloc (sizeof (struct GNUNET_PSYCSTORE_OperationHandle) + | ||
347 | sizeof (struct GNUNET_MessageHeader)); | ||
348 | op->h = h; | ||
349 | op->msg = (const struct GNUNET_MessageHeader *) &op[1]; | ||
350 | msg.size = htons (sizeof (msg)); | ||
351 | msg.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_START); | ||
352 | memcpy (&op[1], &msg, sizeof (msg)); | ||
353 | GNUNET_CONTAINER_DLL_insert (h->op_head, | ||
354 | h->op_tail, | ||
355 | op); | ||
356 | transmit_next (h); | 343 | transmit_next (h); |
357 | GNUNET_assert (NULL != h->th); | 344 | GNUNET_assert (NULL != h->th); |
358 | */ | ||
359 | } | 345 | } |
360 | 346 | ||
361 | 347 | ||
@@ -379,6 +365,35 @@ GNUNET_PSYCSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
379 | 365 | ||
380 | 366 | ||
381 | /** | 367 | /** |
368 | * Disconnect from PSYCstore service | ||
369 | * | ||
370 | * @param h handle to destroy | ||
371 | */ | ||
372 | void | ||
373 | GNUNET_PSYCSTORE_disconnect (struct GNUNET_PSYCSTORE_Handle *h) | ||
374 | { | ||
375 | GNUNET_assert (NULL != h); | ||
376 | GNUNET_assert (h->op_head == h->op_tail); | ||
377 | if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
378 | { | ||
379 | GNUNET_SCHEDULER_cancel (h->reconnect_task); | ||
380 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
381 | } | ||
382 | if (NULL != h->th) | ||
383 | { | ||
384 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | ||
385 | h->th = NULL; | ||
386 | } | ||
387 | if (NULL != h->client) | ||
388 | { | ||
389 | GNUNET_CLIENT_disconnect (h->client); | ||
390 | h->client = NULL; | ||
391 | } | ||
392 | GNUNET_free (h); | ||
393 | } | ||
394 | |||
395 | |||
396 | /** | ||
382 | * Cancel a PSYCstore operation. Note that the operation MAY still | 397 | * Cancel a PSYCstore operation. Note that the operation MAY still |
383 | * be executed; this merely cancels the continuation; if the request | 398 | * be executed; this merely cancels the continuation; if the request |
384 | * was already transmitted, the service may still choose to complete | 399 | * was already transmitted, the service may still choose to complete |
@@ -420,32 +435,4 @@ GNUNET_PSYCSTORE_operation_cancel (struct GNUNET_PSYCSTORE_OperationHandle *op) | |||
420 | } | 435 | } |
421 | 436 | ||
422 | 437 | ||
423 | /** | ||
424 | * Disconnect from PSYCstore service | ||
425 | * | ||
426 | * @param h handle to destroy | ||
427 | */ | ||
428 | void | ||
429 | GNUNET_PSYCSTORE_disconnect (struct GNUNET_PSYCSTORE_Handle *h) | ||
430 | { | ||
431 | GNUNET_assert (NULL != h); | ||
432 | GNUNET_assert (h->op_head == h->op_tail); | ||
433 | if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
434 | { | ||
435 | GNUNET_SCHEDULER_cancel (h->reconnect_task); | ||
436 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
437 | } | ||
438 | if (NULL != h->th) | ||
439 | { | ||
440 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | ||
441 | h->th = NULL; | ||
442 | } | ||
443 | if (NULL != h->client) | ||
444 | { | ||
445 | GNUNET_CLIENT_disconnect (h->client); | ||
446 | h->client = NULL; | ||
447 | } | ||
448 | GNUNET_free (h); | ||
449 | } | ||
450 | |||
451 | /* end of psycstore_api.c */ | 438 | /* end of psycstore_api.c */ |