aboutsummaryrefslogtreecommitdiff
path: root/src/psycstore
diff options
context:
space:
mode:
authorGabor X Toth <*@tg-x.net>2013-09-03 22:33:21 +0000
committerGabor X Toth <*@tg-x.net>2013-09-03 22:33:21 +0000
commiteb9556bf2983ca19a5cbcf7cf460a0b2509b290a (patch)
tree285d31e951f7ecf9308b22257adcadd5b07d80ea /src/psycstore
parent37bafa60a6f0e447cb5b61547404f0902fa7ad41 (diff)
downloadgnunet-eb9556bf2983ca19a5cbcf7cf460a0b2509b290a.tar.gz
gnunet-eb9556bf2983ca19a5cbcf7cf460a0b2509b290a.zip
PSYCstore SQLite backend; API fixes/enhancements
Diffstat (limited to 'src/psycstore')
-rw-r--r--src/psycstore/Makefile.am13
-rw-r--r--src/psycstore/gnunet-service-psycstore.c59
-rw-r--r--src/psycstore/plugin_psycstore_sqlite.c1172
-rw-r--r--src/psycstore/psycstore.conf2
-rw-r--r--src/psycstore/psycstore.h28
-rw-r--r--src/psycstore/psycstore_api.c44
-rw-r--r--src/psycstore/test_plugin_psycstore.c375
-rw-r--r--src/psycstore/test_plugin_psycstore_sqlite.conf2
-rw-r--r--src/psycstore/test_psycstore.c33
-rw-r--r--src/psycstore/test_psycstore.conf11
10 files changed, 1486 insertions, 253 deletions
diff --git a/src/psycstore/Makefile.am b/src/psycstore/Makefile.am
index 48f8d5ff7..6f5c7187f 100644
--- a/src/psycstore/Makefile.am
+++ b/src/psycstore/Makefile.am
@@ -22,7 +22,7 @@ endif
22if HAVE_SQLITE 22if HAVE_SQLITE
23SQLITE_PLUGIN = libgnunet_plugin_psycstore_sqlite.la 23SQLITE_PLUGIN = libgnunet_plugin_psycstore_sqlite.la
24if HAVE_TESTING 24if HAVE_TESTING
25#SQLITE_TESTS = test_plugin_psycstore_sqlite 25SQLITE_TESTS = test_plugin_psycstore_sqlite
26endif 26endif
27endif 27endif
28 28
@@ -99,3 +99,14 @@ EXTRA_DIST = \
99 test_psycstore.conf 99 test_psycstore.conf
100 100
101 101
102test_plugin_psycstore_sqlite_SOURCES = \
103 test_plugin_psycstore.c
104test_plugin_psycstore_sqlite_LDADD = \
105 $(top_builddir)/src/testing/libgnunettesting.la \
106 $(top_builddir)/src/util/libgnunetutil.la
107
108test_plugin_psycstore_postgres_SOURCES = \
109 test_plugin_psycstore.c
110test_plugin_psycstore_postgres_LDADD = \
111 $(top_builddir)/src/testing/libgnunettesting.la \
112 $(top_builddir)/src/util/libgnunetutil.la
diff --git a/src/psycstore/gnunet-service-psycstore.c b/src/psycstore/gnunet-service-psycstore.c
index d8f7a2690..5bc35d227 100644
--- a/src/psycstore/gnunet-service-psycstore.c
+++ b/src/psycstore/gnunet-service-psycstore.c
@@ -101,27 +101,72 @@ send_result_code (struct GNUNET_SERVER_Client *client,
101 uint32_t result_code, 101 uint32_t result_code,
102 const char *emsg) 102 const char *emsg)
103{ 103{
104 struct GNUNET_PSYCSTORE_ResultCodeMessage *rcm; 104 struct ResultCodeMessage *rcm;
105 size_t elen; 105 size_t elen;
106 106
107 if (NULL == emsg) 107 if (NULL == emsg)
108 elen = 0; 108 elen = 0;
109 else 109 else
110 elen = strlen (emsg) + 1; 110 elen = strlen (emsg) + 1;
111 rcm = GNUNET_malloc (sizeof (struct GNUNET_PSYCSTORE_ResultCodeMessage) + elen); 111 rcm = GNUNET_malloc (sizeof (struct ResultCodeMessage) + elen);
112 rcm->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE); 112 rcm->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE);
113 rcm->header.size = htons (sizeof (struct GNUNET_PSYCSTORE_ResultCodeMessage) + elen); 113 rcm->header.size = htons (sizeof (struct ResultCodeMessage) + elen);
114 rcm->result_code = htonl (result_code); 114 rcm->result_code = htonl (result_code);
115 memcpy (&rcm[1], emsg, elen); 115 memcpy (&rcm[1], emsg, elen);
116 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 116 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
117 "Sending result %d (%s) to client\n", 117 "Sending result %d (%s) to client\n",
118 (int) result_code, 118 (int) result_code,
119 emsg); 119 emsg);
120 GNUNET_SERVER_notification_context_unicast (nc, client, &rcm->header, GNUNET_NO); 120 GNUNET_SERVER_notification_context_unicast (nc, client, &rcm->header,
121 GNUNET_NO);
121 GNUNET_free (rcm); 122 GNUNET_free (rcm);
122} 123}
123 124
124 125
126static void
127handle_membership_store (void *cls,
128 struct GNUNET_SERVER_Client *client,
129 const struct GNUNET_MessageHeader *message)
130{
131 const struct MembershipStoreMessage *msg =
132 (const struct MembershipStoreMessage *) message;
133
134 int res = db->membership_store (db->cls, msg->channel_key, msg->slave_key,
135 msg->did_join, msg->announced_at,
136 msg->effective_since, msg->group_generation);
137
138 if (res != GNUNET_OK)
139 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
140 _("Failed to store membership information!\n"));
141
142 send_result_code (client, res, NULL);
143}
144
145
146static void
147handle_membership_test (void *cls,
148 struct GNUNET_SERVER_Client *client,
149 const struct GNUNET_MessageHeader *message)
150{
151 const struct MembershipTestMessage *msg =
152 (const struct MembershipTestMessage *) message;
153
154 int res = db->membership_test (db->cls, msg->channel_key, msg->slave_key,
155 msg->message_id);
156 switch (res)
157 {
158 case GNUNET_YES:
159 case GNUNET_NO:
160 break;
161 default:
162 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
163 _("Failed to test membership!\n"));
164 }
165
166 send_result_code (client, res, NULL);
167}
168
169
125/** 170/**
126 * Handle PSYCstore clients. 171 * Handle PSYCstore clients.
127 * 172 *
@@ -135,6 +180,12 @@ run (void *cls,
135 const struct GNUNET_CONFIGURATION_Handle *c) 180 const struct GNUNET_CONFIGURATION_Handle *c)
136{ 181{
137 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 182 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
183 {&handle_membership_store, NULL,
184 GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE,
185 sizeof (struct MembershipStoreMessage)},
186 {&handle_membership_test, NULL,
187 GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST,
188 sizeof (struct MembershipTestMessage)},
138 {NULL, NULL, 0, 0} 189 {NULL, NULL, 0, 0}
139 }; 190 };
140 191
diff --git a/src/psycstore/plugin_psycstore_sqlite.c b/src/psycstore/plugin_psycstore_sqlite.c
index 8bec31f12..f214e1c60 100644
--- a/src/psycstore/plugin_psycstore_sqlite.c
+++ b/src/psycstore/plugin_psycstore_sqlite.c
@@ -25,9 +25,16 @@ t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 */ 26 */
27 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
28#include "platform.h" 33#include "platform.h"
29#include "gnunet_psycstore_plugin.h" 34#include "gnunet_psycstore_plugin.h"
30#include "gnunet_psycstore_service.h" 35#include "gnunet_psycstore_service.h"
36#include "gnunet_multicast_service.h"
37#include "gnunet_crypto_lib.h"
31#include "psycstore.h" 38#include "psycstore.h"
32#include <sqlite3.h> 39#include <sqlite3.h>
33 40
@@ -43,13 +50,14 @@ t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43 */ 50 */
44#define BUSY_TIMEOUT_MS 1000 51#define BUSY_TIMEOUT_MS 1000
45 52
53#define DEBUG_PSYCSTORE GNUNET_EXTRA_LOGGING
46 54
47/** 55/**
48 * Log an error message at log-level 'level' that indicates 56 * Log an error message at log-level 'level' that indicates
49 * a failure of the command 'cmd' on file 'filename' 57 * a failure of the command 'cmd' on file 'filename'
50 * with the message given by strerror(errno). 58 * with the message given by strerror(errno).
51 */ 59 */
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) 60#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)
53 61
54#define LOG(kind,...) GNUNET_log_from (kind, "psycstore-sqlite", __VA_ARGS__) 62#define LOG(kind,...) GNUNET_log_from (kind, "psycstore-sqlite", __VA_ARGS__)
55 63
@@ -100,9 +108,9 @@ struct Plugin
100 sqlite3_stmt *insert_fragment; 108 sqlite3_stmt *insert_fragment;
101 109
102 /** 110 /**
103 * Precompiled SQL for fragment_add_flags() 111 * Precompiled SQL for message_add_flags()
104 */ 112 */
105 sqlite3_stmt *update_fragment_flags; 113 sqlite3_stmt *update_message_flags;
106 114
107 /** 115 /**
108 * Precompiled SQL for fragment_get() 116 * Precompiled SQL for fragment_get()
@@ -122,12 +130,12 @@ struct Plugin
122 /** 130 /**
123 * Precompiled SQL for counters_get_master() 131 * Precompiled SQL for counters_get_master()
124 */ 132 */
125 sqlite3_stmt *select_master_counters; 133 sqlite3_stmt *select_counters_master;
126 134
127 /** 135 /**
128 * Precompiled SQL for counters_get_slave() 136 * Precompiled SQL for counters_get_slave()
129 */ 137 */
130 sqlite3_stmt *select_slave_counters; 138 sqlite3_stmt *select_counters_slave;
131 139
132 140
133 /** 141 /**
@@ -136,11 +144,6 @@ struct Plugin
136 sqlite3_stmt *insert_state_current; 144 sqlite3_stmt *insert_state_current;
137 145
138 /** 146 /**
139 * Precompiled SQL for state_set()
140 */
141 sqlite3_stmt *update_state_current;
142
143 /**
144 * Precompiled SQL for state_set_signed() 147 * Precompiled SQL for state_set_signed()
145 */ 148 */
146 sqlite3_stmt *update_state_signed; 149 sqlite3_stmt *update_state_signed;
@@ -166,6 +169,11 @@ struct Plugin
166 sqlite3_stmt *delete_state_sync; 169 sqlite3_stmt *delete_state_sync;
167 170
168 /** 171 /**
172 * Precompiled SQL for state_get_signed()
173 */
174 sqlite3_stmt *select_state_signed;
175
176 /**
169 * Precompiled SQL for state_get() 177 * Precompiled SQL for state_get()
170 */ 178 */
171 sqlite3_stmt *select_state_one; 179 sqlite3_stmt *select_state_one;
@@ -177,6 +185,15 @@ struct Plugin
177 185
178}; 186};
179 187
188#if DEBUG_PSYCSTORE
189
190static void
191sql_trace (void *cls, const char *sql)
192{
193 LOG (GNUNET_ERROR_TYPE_DEBUG, "SQL query:\n%s\n", sql);
194}
195
196#endif
180 197
181/** 198/**
182 * @brief Prepare a SQL statement 199 * @brief Prepare a SQL statement
@@ -208,8 +225,7 @@ sql_prepare (sqlite3 *dbh, const char *sql, sqlite3_stmt **stmt)
208 * @brief Prepare a SQL statement 225 * @brief Prepare a SQL statement
209 * 226 *
210 * @param dbh handle to the database 227 * @param dbh handle to the database
211 * @param zSql SQL statement, UTF-8 encoded 228 * @param sql SQL statement, UTF-8 encoded
212 * @param ppStmt set to the prepared statement
213 * @return 0 on success 229 * @return 0 on success
214 */ 230 */
215static int 231static int
@@ -262,7 +278,7 @@ database_setup (struct Plugin *plugin)
262 plugin->fn = filename; 278 plugin->fn = filename;
263 279
264 /* Open database and precompile statements */ 280 /* Open database and precompile statements */
265 if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) 281 if (SQLITE_OK != sqlite3_open (plugin->fn, &plugin->dbh))
266 { 282 {
267 LOG (GNUNET_ERROR_TYPE_ERROR, 283 LOG (GNUNET_ERROR_TYPE_ERROR,
268 _("Unable to initialize SQLite: %s.\n"), 284 _("Unable to initialize SQLite: %s.\n"),
@@ -270,6 +286,10 @@ database_setup (struct Plugin *plugin)
270 return GNUNET_SYSERR; 286 return GNUNET_SYSERR;
271 } 287 }
272 288
289#if DEBUG_PSYCSTORE
290 sqlite3_trace (plugin->dbh, &sql_trace, NULL);
291#endif
292
273 sql_exec (plugin->dbh, "PRAGMA temp_store=MEMORY"); 293 sql_exec (plugin->dbh, "PRAGMA temp_store=MEMORY");
274 sql_exec (plugin->dbh, "PRAGMA synchronous=NORMAL"); 294 sql_exec (plugin->dbh, "PRAGMA synchronous=NORMAL");
275 sql_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF"); 295 sql_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF");
@@ -284,62 +304,62 @@ database_setup (struct Plugin *plugin)
284 /* Create tables */ 304 /* Create tables */
285 305
286 sql_exec (plugin->dbh, 306 sql_exec (plugin->dbh,
287 "CREATE TABLE IF NOT EXISTS channels (" 307 "CREATE TABLE IF NOT EXISTS channels (\n"
288 " id INTEGER PRIMARY KEY," 308 " id INTEGER PRIMARY KEY,\n"
289 " pub_key BLOB UNIQUE" 309 " pub_key BLOB UNIQUE\n"
290 ");"); 310 ");");
291 311
292 sql_exec (plugin->dbh, 312 sql_exec (plugin->dbh,
293 "CREATE TABLE IF NOT EXISTS slaves (" 313 "CREATE TABLE IF NOT EXISTS slaves (\n"
294 " id INTEGER PRIMARY KEY," 314 " id INTEGER PRIMARY KEY,\n"
295 " pub_key BLOB UNIQUE" 315 " pub_key BLOB UNIQUE\n"
296 ");"); 316 ");");
297 317
298 sql_exec (plugin->dbh, 318 sql_exec (plugin->dbh,
299 "CREATE TABLE IF NOT EXISTS membership (" 319 "CREATE TABLE IF NOT EXISTS membership (\n"
300 " channel_id INTEGER NOT NULL REFERENCES channels(id)," 320 " channel_id INTEGER NOT NULL REFERENCES channels(id),\n"
301 " slave_id INTEGER NOT NULL REFERENCES slaves(id)," 321 " slave_id INTEGER NOT NULL REFERENCES slaves(id),\n"
302 " did_join INTEGER NOT NULL," 322 " did_join INTEGER NOT NULL,\n"
303 " announced_at INTEGER NOT NULL," 323 " announced_at INTEGER NOT NULL,\n"
304 " effective_since INTEGER NOT NULL," 324 " effective_since INTEGER NOT NULL,\n"
305 " group_generation INTEGER NOT NULL" 325 " group_generation INTEGER NOT NULL\n"
306 ");"); 326 ");");
307 sql_exec (plugin->dbh, 327 sql_exec (plugin->dbh,
308 "CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id " 328 "CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id "
309 "ON membership (channel_id, slave_id);"); 329 "ON membership (channel_id, slave_id);");
310 330
311 sql_exec (plugin->dbh, 331 sql_exec (plugin->dbh,
312 "CREATE TABLE IF NOT EXISTS messages (" 332 "CREATE TABLE IF NOT EXISTS messages (\n"
313 " channel_id INTEGER NOT NULL," 333 " channel_id INTEGER NOT NULL REFERENCES channels(id),\n"
314 " hop_counter INTEGER NOT NULL," 334 " hop_counter INTEGER NOT NULL,\n"
315 " signature BLOB," 335 " signature BLOB,\n"
316 " purpose BLOB," 336 " purpose BLOB,\n"
317 " fragment_id INTEGER NOT NULL," 337 " fragment_id INTEGER NOT NULL,\n"
318 " fragment_offset INTEGER NOT NULL," 338 " fragment_offset INTEGER NOT NULL,\n"
319 " message_id INTEGER NOT NULL," 339 " message_id INTEGER NOT NULL,\n"
320 " group_generation INTEGER NOT NULL," 340 " group_generation INTEGER NOT NULL,\n"
321 " multicast_flags INTEGER NOT NULL," 341 " multicast_flags INTEGER NOT NULL,\n"
322 " psyc_flags INTEGER NOT NULL," 342 " psycstore_flags INTEGER NOT NULL,\n"
323 " data BLOB," 343 " data BLOB,\n"
324 " PRIMARY KEY (channel_id, fragment_id)," 344 " PRIMARY KEY (channel_id, fragment_id),\n"
325 " UNIQUE (channel_id, message_id, fragment_offset)" 345 " UNIQUE (channel_id, message_id, fragment_offset)\n"
326 ");"); 346 ");");
327 347
328 sql_exec (plugin->dbh, 348 sql_exec (plugin->dbh,
329 "CREATE TABLE IF NOT EXISTS state (" 349 "CREATE TABLE IF NOT EXISTS state (\n"
330 " channel_id INTEGER NOT NULL," 350 " channel_id INTEGER NOT NULL REFERENCES channels(id),\n"
331 " name TEXT NOT NULL," 351 " name TEXT NOT NULL,\n"
332 " value_current BLOB, " 352 " value_current BLOB,\n"
333 " value_signed BLOB, " 353 " value_signed BLOB,\n"
334 " PRIMARY KEY (channel_id, name)" 354 " PRIMARY KEY (channel_id, name)\n"
335 ");"); 355 ");");
336 356
337 sql_exec (plugin->dbh, 357 sql_exec (plugin->dbh,
338 "CREATE TABLE IF NOT EXISTS state_sync (" 358 "CREATE TABLE IF NOT EXISTS state_sync (\n"
339 " channel_id INTEGER NOT NULL," 359 " channel_id INTEGER NOT NULL REFERENCES channels(id),\n"
340 " name TEXT NOT NULL," 360 " name TEXT NOT NULL,\n"
341 " value BLOB, " 361 " value BLOB,\n"
342 " PRIMARY KEY (channel_id, name)" 362 " PRIMARY KEY (channel_id, name)\n"
343 ");"); 363 ");");
344 364
345 /* Prepare statements */ 365 /* Prepare statements */
@@ -353,132 +373,143 @@ database_setup (struct Plugin *plugin)
353 &plugin->insert_slave_key); 373 &plugin->insert_slave_key);
354 374
355 sql_prepare (plugin->dbh, 375 sql_prepare (plugin->dbh,
356 "INSERT INTO membership " 376 "INSERT INTO membership\n"
357 " (channel_id, slave_id, did_join, announced_at, " 377 " (channel_id, slave_id, did_join, announced_at,\n"
358 " effective_since, group_generation) " 378 " effective_since, group_generation)\n"
359 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), " 379 "VALUES ((SELECT id FROM channels WHERE pub_key = ?),\n"
360 " (SELECT id FROM slaves WHERE pub_key = ?), " 380 " (SELECT id FROM slaves WHERE pub_key = ?),\n"
361 " ?, ?, ?, ?);", 381 " ?, ?, ?, ?);",
362 &plugin->insert_membership); 382 &plugin->insert_membership);
363 383
364 sql_prepare (plugin->dbh, 384 sql_prepare (plugin->dbh,
365 "SELECT did_join FROM membership " 385 "SELECT did_join FROM membership\n"
366 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) " 386 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
367 " AND slave_id = ? AND effective_since <= ? " 387 " AND slave_id = (SELECT id FROM slaves WHERE pub_key = ?)\n"
388 " AND effective_since <= ? AND did_join = 1\n"
368 "ORDER BY announced_at DESC LIMIT 1;", 389 "ORDER BY announced_at DESC LIMIT 1;",
369 &plugin->select_membership); 390 &plugin->select_membership);
370 391
371 sql_prepare (plugin->dbh, 392 sql_prepare (plugin->dbh,
372 "INSERT INTO messages " 393 "INSERT INTO messages\n"
373 " (channel_id, hop_counter, signature, purpose, " 394 " (channel_id, hop_counter, signature, purpose,\n"
374 " fragment_id, fragment_offset, message_id, " 395 " fragment_id, fragment_offset, message_id,\n"
375 " group_generation, multicast_flags, psyc_flags, data) " 396 " group_generation, multicast_flags, psycstore_flags, data)\n"
376 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), " 397 "VALUES ((SELECT id FROM channels WHERE pub_key = ?),\n"
377 " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", 398 " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
378 &plugin->insert_fragment); 399 &plugin->insert_fragment);
379 400
380 sql_prepare (plugin->dbh, 401 sql_prepare (plugin->dbh,
381 "UPDATE messages " 402 "UPDATE messages\n"
382 "SET multicast_flags = multicast_flags | ?, " 403 "SET psycstore_flags = psycstore_flags | ?\n"
383 " psyc_flags = psyc_flags | ? " 404 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
384 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) " 405 " AND message_id = ? AND fragment_offset = 0;",
385 " AND message_id = ?;", 406 &plugin->update_message_flags);
386 &plugin->update_fragment_flags);
387 407
388 sql_prepare (plugin->dbh, 408 sql_prepare (plugin->dbh,
389 "SELECT hop_counter, signature, purpose, " 409 "SELECT hop_counter, signature, purpose, fragment_id,\n"
390 " fragment_offset, message_id, group_generation, " 410 " fragment_offset, message_id, group_generation,\n"
391 " multicast_flags, psyc_flags, data " 411 " multicast_flags, psycstore_flags, data\n"
392 "FROM messages " 412 "FROM messages\n"
393 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) " 413 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
394 " AND fragment_id = ?;", 414 " AND fragment_id = ?;",
395 &plugin->select_fragment); 415 &plugin->select_fragment);
396 416
397 sql_prepare (plugin->dbh, 417 sql_prepare (plugin->dbh,
398 "SELECT hop_counter, signature, purpose, " 418 "SELECT hop_counter, signature, purpose, fragment_id,\n"
399 " fragment_id, fragment_offset, group_generation, " 419 " fragment_offset, message_id, group_generation,\n"
400 " multicast_flags, psyc_flags, data " 420 " multicast_flags, psycstore_flags, data\n"
401 "FROM messages " 421 "FROM messages\n"
402 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) " 422 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
403 " AND message_id = ?;", 423 " AND message_id = ?;",
404 &plugin->select_message); 424 &plugin->select_message);
405 425
406 sql_prepare (plugin->dbh, 426 sql_prepare (plugin->dbh,
407 "SELECT hop_counter, signature, purpose, " 427 "SELECT hop_counter, signature, purpose, fragment_id,\n"
408 " fragment_id, message_id, group_generation, " 428 " fragment_offset, message_id, group_generation,\n"
409 " multicast_flags, psyc_flags, data " 429 " multicast_flags, psycstore_flags, data\n"
410 "FROM messages " 430 "FROM messages\n"
411 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) " 431 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
412 " AND message_id = ? AND fragment_offset = ?;", 432 " AND message_id = ? AND fragment_offset = ?;",
413 &plugin->select_message_fragment); 433 &plugin->select_message_fragment);
414 434
415 sql_prepare (plugin->dbh, 435 sql_prepare (plugin->dbh,
416 "SELECT max(fragment_id), max(message_id), max(group_generation) " 436 "SELECT fragment_id, message_id, group_generation\n"
417 "FROM messages " 437 "FROM messages\n"
418 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);", 438 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
419 &plugin->select_master_counters); 439 "ORDER BY fragment_id DESC LIMIT 1;",
440 &plugin->select_counters_master);
420 441
421 sql_prepare (plugin->dbh, 442 sql_prepare (plugin->dbh,
422 "SELECT max(message_id) " 443 "SELECT message_id\n"
423 "FROM messages " 444 "FROM messages\n"
424 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) " 445 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
425 " AND psyc_flags & ?;", 446 " AND psycstore_flags & ?\n"
426 &plugin->select_slave_counters); 447 "ORDER BY message_id DESC LIMIT 1",
448 &plugin->select_counters_slave);
427 449
428 sql_prepare (plugin->dbh, 450 sql_prepare (plugin->dbh,
429 "INSERT OR REPLACE INTO state (channel_id, name, value_current) " 451 "INSERT OR REPLACE INTO state\n"
430 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);", 452 " (channel_id, name, value_current, value_signed)\n"
453 "SELECT new.channel_id, new.name,\n"
454 " new.value_current, old.value_signed\n"
455 "FROM (SELECT (SELECT id FROM channels WHERE pub_key = ?)\n"
456 " AS channel_id,\n"
457 " ? AS name, ? AS value_current) AS new\n"
458 "LEFT JOIN (SELECT channel_id, name, value_signed\n"
459 " FROM state) AS old\n"
460 "ON new.channel_id = old.channel_id AND new.name = old.name;",
431 &plugin->insert_state_current); 461 &plugin->insert_state_current);
432 462
433 sql_prepare (plugin->dbh, 463 sql_prepare (plugin->dbh,
434 "UPDATE state " 464 "UPDATE state\n"
435 "SET value_current = ? " 465 "SET value_signed = value_current\n"
436 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) " 466 "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); 467 &plugin->update_state_signed);
445 468
446 sql_prepare (plugin->dbh, 469 sql_prepare (plugin->dbh,
447 "INSERT INTO state_sync (channel_id, name, value) " 470 "INSERT INTO state_sync (channel_id, name, value)\n"
448 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);", 471 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);",
449 &plugin->insert_state_sync); 472 &plugin->insert_state_sync);
450 473
451 sql_prepare (plugin->dbh, 474 sql_prepare (plugin->dbh,
452 "DELETE FROM state " 475 "DELETE FROM state\n"
453 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);", 476 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
454 &plugin->delete_state); 477 &plugin->delete_state);
455 478
456 sql_prepare (plugin->dbh, 479 sql_prepare (plugin->dbh,
457 "INSERT INTO state " 480 "INSERT INTO state\n"
458 " (channel_id, name, value_current, value_signed) " 481 " (channel_id, name, value_current, value_signed)\n"
459 "SELECT channel_id, name, value, value " 482 "SELECT channel_id, name, value, value\n"
460 "FROM state_sync " 483 "FROM state_sync\n"
461 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);", 484 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
462 &plugin->insert_state_from_sync); 485 &plugin->insert_state_from_sync);
463 486
464 sql_prepare (plugin->dbh, 487 sql_prepare (plugin->dbh,
465 "DELETE FROM state_sync " 488 "DELETE FROM state_sync\n"
466 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);", 489 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
467 &plugin->delete_state_sync); 490 &plugin->delete_state_sync);
468 491
469 sql_prepare (plugin->dbh, 492 sql_prepare (plugin->dbh,
470 "SELECT value_current " 493 "SELECT value_current\n"
471 "FROM state " 494 "FROM state\n"
472 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) " 495 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
473 " AND name = ?;", 496 " AND name = ?;",
474 &plugin->select_state_one); 497 &plugin->select_state_one);
475 498
476 sql_prepare (plugin->dbh, 499 sql_prepare (plugin->dbh,
477 "SELECT value_current " 500 "SELECT name, value_current\n"
478 "FROM state " 501 "FROM state\n"
479 "WHERE name LIKE ? OR name LIKE ?;", 502 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n"
503 " AND name = ? OR name LIKE ?;",
480 &plugin->select_state_prefix); 504 &plugin->select_state_prefix);
481 505
506 sql_prepare (plugin->dbh,
507 "SELECT name, value_signed\n"
508 "FROM state\n"
509 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)"
510 " AND value_signed IS NOT NULL;",
511 &plugin->select_state_signed);
512
482 return GNUNET_OK; 513 return GNUNET_OK;
483} 514}
484 515
@@ -509,8 +540,8 @@ database_shutdown (struct Plugin *plugin)
509 if (NULL != plugin->insert_fragment) 540 if (NULL != plugin->insert_fragment)
510 sqlite3_finalize (plugin->insert_fragment); 541 sqlite3_finalize (plugin->insert_fragment);
511 542
512 if (NULL != plugin->update_fragment_flags) 543 if (NULL != plugin->update_message_flags)
513 sqlite3_finalize (plugin->update_fragment_flags); 544 sqlite3_finalize (plugin->update_message_flags);
514 545
515 if (NULL != plugin->select_fragment) 546 if (NULL != plugin->select_fragment)
516 sqlite3_finalize (plugin->select_fragment); 547 sqlite3_finalize (plugin->select_fragment);
@@ -521,18 +552,15 @@ database_shutdown (struct Plugin *plugin)
521 if (NULL != plugin->select_message_fragment) 552 if (NULL != plugin->select_message_fragment)
522 sqlite3_finalize (plugin->select_message_fragment); 553 sqlite3_finalize (plugin->select_message_fragment);
523 554
524 if (NULL != plugin->select_master_counters) 555 if (NULL != plugin->select_counters_master)
525 sqlite3_finalize (plugin->select_master_counters); 556 sqlite3_finalize (plugin->select_counters_master);
526 557
527 if (NULL != plugin->select_slave_counters) 558 if (NULL != plugin->select_counters_slave)
528 sqlite3_finalize (plugin->select_slave_counters); 559 sqlite3_finalize (plugin->select_counters_slave);
529 560
530 if (NULL != plugin->insert_state_current) 561 if (NULL != plugin->insert_state_current)
531 sqlite3_finalize (plugin->insert_state_current); 562 sqlite3_finalize (plugin->insert_state_current);
532 563
533 if (NULL != plugin->update_state_current)
534 sqlite3_finalize (plugin->update_state_current);
535
536 if (NULL != plugin->update_state_signed) 564 if (NULL != plugin->update_state_signed)
537 sqlite3_finalize (plugin->update_state_signed); 565 sqlite3_finalize (plugin->update_state_signed);
538 566
@@ -579,6 +607,65 @@ database_shutdown (struct Plugin *plugin)
579} 607}
580 608
581 609
610static int
611channel_key_store (struct Plugin *plugin,
612 const struct GNUNET_CRYPTO_EccPublicKey *channel_key)
613{
614 sqlite3_stmt *stmt = plugin->insert_channel_key;
615
616 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
617 sizeof (*channel_key), SQLITE_STATIC))
618 {
619 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
620 "insert_channel_key (bind)");
621 }
622 else if (SQLITE_DONE != sqlite3_step (stmt))
623 {
624 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
625 "insert_channel_key (step)");
626 }
627
628 if (SQLITE_OK != sqlite3_reset (stmt))
629 {
630 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
631 "insert_channel_key (reset)");
632 return GNUNET_SYSERR;
633 }
634
635 return GNUNET_OK;
636}
637
638
639static int
640slave_key_store (struct Plugin *plugin,
641 const struct GNUNET_CRYPTO_EccPublicKey *slave_key)
642{
643 sqlite3_stmt *stmt = plugin->insert_slave_key;
644
645 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, slave_key,
646 sizeof (*slave_key), SQLITE_STATIC))
647 {
648 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
649 "insert_slave_key (bind)");
650 }
651 else if (SQLITE_DONE != sqlite3_step (stmt))
652 {
653 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
654 "insert_slave_key (step)");
655 }
656
657
658 if (SQLITE_OK != sqlite3_reset (stmt))
659 {
660 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
661 "insert_slave_key (reset)");
662 return GNUNET_SYSERR;
663 }
664
665 return GNUNET_OK;
666}
667
668
582/** 669/**
583 * Store join/leave events for a PSYC channel in order to be able to answer 670 * Store join/leave events for a PSYC channel in order to be able to answer
584 * membership test queries later. 671 * membership test queries later.
@@ -587,17 +674,56 @@ database_shutdown (struct Plugin *plugin)
587 * 674 *
588 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 675 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
589 */ 676 */
590int 677static int
591libgnunet_plugin_psycstore_sqlite_membership_store 678membership_store (void *cls,
592 (void *cls, 679 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
593 const struct GNUNET_HashCode *channel_key, 680 const struct GNUNET_CRYPTO_EccPublicKey *slave_key,
594 const struct GNUNET_HashCode *slave_key, 681 int did_join,
595 int did_join, 682 uint64_t announced_at,
596 uint64_t announced_at, 683 uint64_t effective_since,
597 uint64_t effective_since, 684 uint64_t group_generation)
598 uint64_t group_generation) { 685{
686 if (announced_at > INT64_MAX ||
687 effective_since > INT64_MAX ||
688 group_generation > INT64_MAX)
689 {
690 GNUNET_break (0);
691 return GNUNET_SYSERR;
692 }
693
694 struct Plugin *plugin = cls;
695 sqlite3_stmt *stmt = plugin->insert_membership;
599 696
697 if (GNUNET_OK != channel_key_store (plugin, channel_key) ||
698 GNUNET_OK != slave_key_store (plugin, slave_key))
699 return GNUNET_SYSERR;
600 700
701 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
702 sizeof (*channel_key), SQLITE_STATIC) ||
703 SQLITE_OK != sqlite3_bind_blob (stmt, 2, slave_key,
704 sizeof (*slave_key), SQLITE_STATIC) ||
705 SQLITE_OK != sqlite3_bind_int (stmt, 3, did_join) ||
706 SQLITE_OK != sqlite3_bind_int64 (stmt, 4, announced_at) ||
707 SQLITE_OK != sqlite3_bind_int64 (stmt, 5, effective_since) ||
708 SQLITE_OK != sqlite3_bind_int64 (stmt, 6, group_generation))
709 {
710 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
711 "insert_membership (bind)");
712 }
713 else if (SQLITE_DONE != sqlite3_step (stmt))
714 {
715 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
716 "insert_membership (step)");
717 }
718
719 if (SQLITE_OK != sqlite3_reset (stmt))
720 {
721 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
722 "insert_membership (reset)");
723 return GNUNET_SYSERR;
724 }
725
726 return GNUNET_OK;
601} 727}
602 728
603/** 729/**
@@ -608,14 +734,44 @@ libgnunet_plugin_psycstore_sqlite_membership_store
608 * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not, 734 * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not,
609 * #GNUNET_SYSERR if there was en error. 735 * #GNUNET_SYSERR if there was en error.
610 */ 736 */
611int 737static int
612libgnunet_plugin_psycstore_sqlite_membership_test 738membership_test (void *cls,
613 (void *cls, 739 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
614 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 740 const struct GNUNET_CRYPTO_EccPublicKey *slave_key,
615 const struct GNUNET_CRYPTO_EccPublicKey *slave_key, 741 uint64_t message_id)
616 uint64_t message_id, 742{
617 uint64_t group_generation) { 743 struct Plugin *plugin = cls;
744 sqlite3_stmt *stmt = plugin->select_membership;
745 int ret = GNUNET_SYSERR;
746
747 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
748 sizeof (*channel_key), SQLITE_STATIC) ||
749 SQLITE_OK != sqlite3_bind_blob (stmt, 2, slave_key,
750 sizeof (*slave_key), SQLITE_STATIC) ||
751 SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_id))
752 {
753 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
754 "select_membership (bind)");
755 }
756 else
757 {
758 switch (sqlite3_step (stmt))
759 {
760 case SQLITE_DONE:
761 ret = GNUNET_NO;
762 break;
763 case SQLITE_ROW:
764 ret = GNUNET_YES;
765 }
766 }
618 767
768 if (SQLITE_OK != sqlite3_reset (stmt))
769 {
770 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
771 "select_membership (reset)");
772 }
773
774 return ret;
619} 775}
620 776
621/** 777/**
@@ -625,30 +781,141 @@ libgnunet_plugin_psycstore_sqlite_membership_test
625 * 781 *
626 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 782 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
627 */ 783 */
628int 784static int
629libgnunet_plugin_psycstore_sqlite_fragment_store 785fragment_store (void *cls,
630 (void *cls, 786 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
631 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 787 const struct GNUNET_MULTICAST_MessageHeader *msg,
632 const struct GNUNET_MULTICAST_MessageHeader *message) { 788 uint32_t psycstore_flags)
789{
790 if (msg->fragment_id > INT64_MAX ||
791 msg->fragment_offset > INT64_MAX ||
792 msg->message_id > INT64_MAX ||
793 msg->group_generation > INT64_MAX)
794 {
795 GNUNET_break (0);
796 return GNUNET_SYSERR;
797 }
798
799 struct Plugin *plugin = cls;
800 sqlite3_stmt *stmt = plugin->insert_fragment;
801
802 if (GNUNET_OK != channel_key_store (plugin, channel_key))
803 return GNUNET_SYSERR;
804
805 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
806 sizeof (*channel_key), SQLITE_STATIC) ||
807 SQLITE_OK != sqlite3_bind_int64 (stmt, 2, msg->hop_counter ) ||
808 SQLITE_OK != sqlite3_bind_blob (stmt, 3, (const void *) &msg->signature,
809 sizeof (msg->signature), SQLITE_STATIC) ||
810 SQLITE_OK != sqlite3_bind_blob (stmt, 4, (const void *) &msg->purpose,
811 sizeof (msg->purpose), SQLITE_STATIC) ||
812 SQLITE_OK != sqlite3_bind_int64 (stmt, 5, msg->fragment_id) ||
813 SQLITE_OK != sqlite3_bind_int64 (stmt, 6, msg->fragment_offset) ||
814 SQLITE_OK != sqlite3_bind_int64 (stmt, 7, msg->message_id) ||
815 SQLITE_OK != sqlite3_bind_int64 (stmt, 8, msg->group_generation) ||
816 SQLITE_OK != sqlite3_bind_int64 (stmt, 9, msg->flags) ||
817 SQLITE_OK != sqlite3_bind_int64 (stmt, 10, psycstore_flags) ||
818 SQLITE_OK != sqlite3_bind_blob (stmt, 11, (const void *) &msg[1],
819 ntohs (msg->header.size) - sizeof (*msg),
820 SQLITE_STATIC))
821 {
822 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
823 "insert_fragment (bind)");
824 }
825 else if (SQLITE_DONE != sqlite3_step (stmt))
826 {
827 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
828 "insert_fragment (step)");
829 }
830
831 if (SQLITE_OK != sqlite3_reset (stmt))
832 {
833 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
834 "insert_fragment (reset)");
835 return GNUNET_SYSERR;
836 }
633 837
838 return GNUNET_OK;
634} 839}
635 840
636/** 841/**
637 * Set additional flags for a given message. 842 * Set additional flags for a given message.
638 * 843 *
844 * They are OR'd with any existing flags set.
845 *
846 * @param plugin Plugin handle.
847 * @param channel_key Public key of the channel.
639 * @param message_id ID of the message. 848 * @param message_id ID of the message.
640 * @param flags Flags to add. 849 * @param psycstore_flags OR'd GNUNET_PSYCSTORE_MessageFlags.
641 * 850 *
642 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 851 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
643 */ 852 */
644int 853static int
645libgnunet_plugin_psycstore_sqlite_fragment_add_flags 854message_add_flags (void *cls,
646 (void *cls, 855 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
647 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 856 uint64_t message_id,
648 uint64_t message_id, 857 uint64_t psycstore_flags)
649 uint64_t multicast_flags, 858{
650 uint64_t psyc_flags) { 859 struct Plugin *plugin = cls;
860 sqlite3_stmt *stmt = plugin->update_message_flags;
861 int ret = GNUNET_SYSERR;
862
863 if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, psycstore_flags) ||
864 SQLITE_OK != sqlite3_bind_blob (stmt, 2, channel_key,
865 sizeof (*channel_key), SQLITE_STATIC) ||
866 SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_id))
867 {
868 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
869 "update_message_flags (bind)");
870 }
871 else
872 {
873 switch (sqlite3_step (stmt))
874 {
875 case SQLITE_DONE:
876 ret = sqlite3_total_changes (plugin->dbh) > 0 ? GNUNET_OK : GNUNET_NO;
877 break;
878 default:
879 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
880 "update_message_flags (step)");
881 }
882 }
883
884 if (SQLITE_OK != sqlite3_reset (stmt))
885 {
886 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
887 "update_message_flags (reset)");
888 return GNUNET_SYSERR;
889 }
890
891 return ret;
892}
651 893
894static int
895fragment_row (sqlite3_stmt *stmt, GNUNET_PSYCSTORE_FragmentCallback cb,
896 void *cb_cls)
897{
898 int data_size = sqlite3_column_bytes (stmt, 9);
899 struct GNUNET_MULTICAST_MessageHeader *msg
900 = GNUNET_malloc (sizeof (*msg) + data_size);
901
902 msg->header.size = htons (sizeof (*msg) + data_size);
903 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
904 msg->hop_counter = (uint32_t) sqlite3_column_int64 (stmt, 0);
905 memcpy (&msg->signature,
906 sqlite3_column_blob (stmt, 1),
907 sqlite3_column_bytes (stmt, 1));
908 memcpy (&msg->purpose,
909 sqlite3_column_blob (stmt, 2),
910 sqlite3_column_bytes (stmt, 2));
911 msg->fragment_id = sqlite3_column_int64 (stmt, 3);
912 msg->fragment_offset = sqlite3_column_int64 (stmt, 4);
913 msg->message_id = sqlite3_column_int64 (stmt, 5);
914 msg->group_generation = sqlite3_column_int64 (stmt, 6);
915 msg->flags = sqlite3_column_int64 (stmt, 7);
916 memcpy (&msg[1], sqlite3_column_blob (stmt, 9), data_size);
917
918 return cb (cb_cls, (void *) msg, sqlite3_column_int64 (stmt, 8));
652} 919}
653 920
654/** 921/**
@@ -658,14 +925,49 @@ libgnunet_plugin_psycstore_sqlite_fragment_add_flags
658 * 925 *
659 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 926 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
660 */ 927 */
661int 928static int
662libgnunet_plugin_psycstore_sqlite_fragment_get 929fragment_get (void *cls,
663 (void *cls, 930 const struct
664 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 931 GNUNET_CRYPTO_EccPublicKey *channel_key,
665 uint64_t fragment_id, 932 uint64_t fragment_id,
666 GNUNET_PSYCSTORE_FragmentCallback cb, 933 GNUNET_PSYCSTORE_FragmentCallback cb,
667 void *cb_cls) { 934 void *cb_cls)
935{
936 struct Plugin *plugin = cls;
937 sqlite3_stmt *stmt = plugin->select_fragment;
938 int ret = GNUNET_SYSERR;
939
940 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
941 sizeof (*channel_key),
942 SQLITE_STATIC) ||
943 SQLITE_OK != sqlite3_bind_int64 (stmt, 2, fragment_id))
944 {
945 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
946 "select_fragment (bind)");
947 }
948 else
949 {
950 switch (sqlite3_step (stmt))
951 {
952 case SQLITE_DONE:
953 ret = GNUNET_NO;
954 break;
955 case SQLITE_ROW:
956 ret = fragment_row (stmt, cb, cb_cls);
957 break;
958 default:
959 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
960 "select_fragment (step)");
961 }
962 }
668 963
964 if (SQLITE_OK != sqlite3_reset (stmt))
965 {
966 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
967 "select_fragment (reset)");
968 }
969
970 return ret;
669} 971}
670 972
671/** 973/**
@@ -675,14 +977,57 @@ libgnunet_plugin_psycstore_sqlite_fragment_get
675 * 977 *
676 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 978 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
677 */ 979 */
678int 980static int
679libgnunet_plugin_psycstore_sqlite_message_get 981message_get (void *cls,
680 (void *cls, 982 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
681 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 983 uint64_t message_id,
682 uint64_t message_id, 984 GNUNET_PSYCSTORE_FragmentCallback cb,
683 GNUNET_PSYCSTORE_FragmentCallback cb, 985 void *cb_cls)
684 void *cb_cls) { 986{
987 struct Plugin *plugin = cls;
988 sqlite3_stmt *stmt = plugin->select_message;
989 int ret = GNUNET_SYSERR;
990
991 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
992 sizeof (*channel_key),
993 SQLITE_STATIC) ||
994 SQLITE_OK != sqlite3_bind_int64 (stmt, 2, message_id))
995 {
996 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
997 "select_message (bind)");
998 }
999 else
1000 {
1001 int sql_ret;
1002 do
1003 {
1004 sql_ret = sqlite3_step (stmt);
1005 switch (sql_ret)
1006 {
1007 case SQLITE_DONE:
1008 if (ret != GNUNET_OK)
1009 ret = GNUNET_NO;
1010 break;
1011 case SQLITE_ROW:
1012 ret = fragment_row (stmt, cb, cb_cls);
1013 if (ret != GNUNET_YES)
1014 sql_ret = SQLITE_DONE;
1015 break;
1016 default:
1017 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1018 "select_message (step)");
1019 }
1020 }
1021 while (sql_ret == SQLITE_ROW);
1022 }
685 1023
1024 if (SQLITE_OK != sqlite3_reset (stmt))
1025 {
1026 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1027 "select_message (reset)");
1028 }
1029
1030 return ret;
686} 1031}
687 1032
688/** 1033/**
@@ -693,16 +1038,51 @@ libgnunet_plugin_psycstore_sqlite_message_get
693 * 1038 *
694 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 1039 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
695 */ 1040 */
696int 1041static int
697libgnunet_plugin_psycstore_sqlite_message_get_fragment 1042message_get_fragment (void *cls,
698 (void *cls, 1043 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
699 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 1044 uint64_t message_id,
700 uint64_t message_id, 1045 uint64_t fragment_offset,
701 uint64_t fragment_offset, 1046 GNUNET_PSYCSTORE_FragmentCallback cb,
702 GNUNET_PSYCSTORE_FragmentCallback cb, 1047 void *cb_cls)
703 void *cb_cls)
704{ 1048{
1049 struct Plugin *plugin = cls;
1050 int ret = GNUNET_SYSERR;
1051
1052 sqlite3_stmt *stmt = plugin->select_message_fragment;
1053
1054 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1055 sizeof (*channel_key),
1056 SQLITE_STATIC) ||
1057 SQLITE_OK != sqlite3_bind_int64 (stmt, 2, message_id) ||
1058 SQLITE_OK != sqlite3_bind_int64 (stmt, 3, fragment_offset))
1059 {
1060 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1061 "select_message_fragment (bind)");
1062 }
1063 else
1064 {
1065 switch (sqlite3_step (stmt))
1066 {
1067 case SQLITE_DONE:
1068 ret = GNUNET_NO;
1069 break;
1070 case SQLITE_ROW:
1071 ret = fragment_row (stmt, cb, cb_cls);
1072 break;
1073 default:
1074 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1075 "select_message_fragment (step)");
1076 }
1077 }
705 1078
1079 if (SQLITE_OK != sqlite3_reset (stmt))
1080 {
1081 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1082 "select_message_fragment (reset)");
1083 }
1084
1085 return ret;
706} 1086}
707 1087
708/** 1088/**
@@ -712,15 +1092,50 @@ libgnunet_plugin_psycstore_sqlite_message_get_fragment
712 * 1092 *
713 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 1093 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
714 */ 1094 */
715int 1095static int
716libgnunet_plugin_psycstore_sqlite_counters_get_master 1096counters_get_master (void *cls,
717 (void *cls, 1097 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
718 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 1098 uint64_t *fragment_id,
719 uint64_t *fragment_id, 1099 uint64_t *message_id,
720 uint64_t *message_id, 1100 uint64_t *group_generation)
721 uint64_t *group_generation)
722{ 1101{
1102 struct Plugin *plugin = cls;
1103 sqlite3_stmt *stmt = plugin->select_counters_master;
1104 int ret = GNUNET_SYSERR;
1105
1106 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1107 sizeof (*channel_key),
1108 SQLITE_STATIC))
1109 {
1110 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1111 "select_counters_master (bind)");
1112 }
1113 else
1114 {
1115 switch (sqlite3_step (stmt))
1116 {
1117 case SQLITE_DONE:
1118 ret = GNUNET_NO;
1119 break;
1120 case SQLITE_ROW:
1121 *fragment_id = sqlite3_column_int64 (stmt, 0);
1122 *message_id = sqlite3_column_int64 (stmt, 1);
1123 *group_generation = sqlite3_column_int64 (stmt, 2);
1124 ret = GNUNET_OK;
1125 break;
1126 default:
1127 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1128 "select_counters_master (step)");
1129 }
1130 }
723 1131
1132 if (SQLITE_OK != sqlite3_reset (stmt))
1133 {
1134 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1135 "select_counters_master (reset)");
1136 }
1137
1138 return ret;
724} 1139}
725 1140
726/** 1141/**
@@ -730,12 +1145,48 @@ libgnunet_plugin_psycstore_sqlite_counters_get_master
730 * 1145 *
731 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 1146 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
732 */ 1147 */
733int 1148static int
734libgnunet_plugin_psycstore_sqlite_counters_get_slave 1149counters_get_slave (void *cls,
735 (void *cls, 1150 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
736 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 1151 uint64_t *max_state_msg_id)
737 uint64_t *max_state_msg_id) { 1152{
1153 struct Plugin *plugin = cls;
1154 sqlite3_stmt *stmt = plugin->select_counters_slave;
1155 int ret = GNUNET_SYSERR;
1156
1157 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1158 sizeof (*channel_key),
1159 SQLITE_STATIC) ||
1160 SQLITE_OK != sqlite3_bind_int64 (stmt, 2,
1161 GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED))
1162 {
1163 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1164 "select_counters_slave (bind)");
1165 }
1166 else
1167 {
1168 switch (sqlite3_step (stmt))
1169 {
1170 case SQLITE_DONE:
1171 ret = GNUNET_NO;
1172 break;
1173 case SQLITE_ROW:
1174 *max_state_msg_id = sqlite3_column_int64 (stmt, 0);
1175 ret = GNUNET_OK;
1176 break;
1177 default:
1178 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1179 "select_counters_slave (step)");
1180 }
1181 }
738 1182
1183 if (SQLITE_OK != sqlite3_reset (stmt))
1184 {
1185 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1186 "select_counters_slave (reset)");
1187 }
1188
1189 return ret;
739} 1190}
740 1191
741/** 1192/**
@@ -745,35 +1196,174 @@ libgnunet_plugin_psycstore_sqlite_counters_get_slave
745 * 1196 *
746 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 1197 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
747 */ 1198 */
748int 1199static int
749libgnunet_plugin_psycstore_sqlite_state_set 1200state_set (void *cls,
750 (struct GNUNET_PSYCSTORE_Handle *h, 1201 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
751 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 1202 const char *name, const void *value, size_t value_size)
752 const char *name, 1203{
753 size_t value_size, 1204 struct Plugin *plugin = cls;
754 const void *value) { 1205 int ret = GNUNET_SYSERR;
1206
1207 sqlite3_stmt *stmt = plugin->insert_state_current;
1208
1209 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1210 sizeof (*channel_key), SQLITE_STATIC) ||
1211 SQLITE_OK != sqlite3_bind_text (stmt, 2, name, -1, SQLITE_STATIC) ||
1212 SQLITE_OK != sqlite3_bind_blob (stmt, 3, value, value_size,
1213 SQLITE_STATIC))
1214 {
1215 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1216 "insert_state_current (bind)");
1217 }
1218 else
1219 {
1220 switch (sqlite3_step (stmt))
1221 {
1222 case SQLITE_DONE:
1223 ret = sqlite3_total_changes (plugin->dbh) > 0 ? GNUNET_OK : GNUNET_NO;
1224 break;
1225 default:
1226 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1227 "insert_state_current (step)");
1228 }
1229 }
1230
1231 if (SQLITE_OK != sqlite3_reset (stmt))
1232 {
1233 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1234 "insert_state_current (reset)");
1235 return GNUNET_SYSERR;
1236 }
1237
1238 return ret;
1239}
1240
1241
1242/**
1243 * Reset the state of a channel.
1244 *
1245 * @see GNUNET_PSYCSTORE_state_reset()
1246 *
1247 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1248 */
1249static int
1250state_reset (void *cls, const struct GNUNET_CRYPTO_EccPublicKey *channel_key)
1251{
1252 struct Plugin *plugin = cls;
1253 sqlite3_stmt *stmt = plugin->delete_state;
1254
1255 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1256 sizeof (*channel_key), SQLITE_STATIC))
1257 {
1258 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1259 "delete_state (bind)");
1260 }
1261 else if (SQLITE_DONE != sqlite3_step (stmt))
1262 {
1263 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1264 "delete_state (step)");
1265 }
1266
1267 if (SQLITE_OK != sqlite3_reset (stmt))
1268 {
1269 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1270 "delete_state (reset)");
1271 return GNUNET_SYSERR;
1272 }
1273
1274 return GNUNET_OK;
1275}
1276
1277
1278/**
1279 * Update signed values of state variables in the state store.
1280 *
1281 * @see GNUNET_PSYCSTORE_state_hash_update()
1282 *
1283 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1284 */
1285static int
1286state_update_signed (void *cls,
1287 const struct GNUNET_CRYPTO_EccPublicKey *channel_key)
1288{
1289 struct Plugin *plugin = cls;
1290 sqlite3_stmt *stmt = plugin->update_state_signed;
1291
1292 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1293 sizeof (*channel_key), SQLITE_STATIC))
1294 {
1295 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1296 "update_state_signed (bind)");
1297 }
1298 else if (SQLITE_DONE != sqlite3_step (stmt))
1299 {
1300 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1301 "update_state_signed (step)");
1302 }
1303
1304 if (SQLITE_OK != sqlite3_reset (stmt))
1305 {
1306 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1307 "update_state_signed (reset)");
1308 return GNUNET_SYSERR;
1309 }
755 1310
1311 return GNUNET_OK;
756} 1312}
757 1313
1314
758/** 1315/**
759 * Retrieve a state variable by name. 1316 * Retrieve a state variable by name.
760 * 1317 *
761 * @param name Name of the variable to retrieve. 1318 * @see GNUNET_PSYCSTORE_state_get()
762 * @param[out] value_size Size of value.
763 * @param[out] value Returned value.
764 * 1319 *
765 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 1320 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
766 */ 1321 */
767int 1322static int
768libgnunet_plugin_psycstore_sqlite_state_get 1323state_get (void *cls, const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
769 (struct GNUNET_PSYCSTORE_Handle *h, 1324 const char *name, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls)
770 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 1325{
771 const char *name, 1326 struct Plugin *plugin = cls;
772 GNUNET_PSYCSTORE_StateCallback cb, 1327 int ret = GNUNET_SYSERR;
773 void *cb_cls) { 1328
1329 sqlite3_stmt *stmt = plugin->select_state_one;
1330
1331 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1332 sizeof (*channel_key),
1333 SQLITE_STATIC) ||
1334 SQLITE_OK != sqlite3_bind_text (stmt, 2, name, -1, SQLITE_STATIC))
1335 {
1336 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1337 "select_state_one (bind)");
1338 }
1339 else
1340 {
1341 switch (sqlite3_step (stmt))
1342 {
1343 case SQLITE_DONE:
1344 ret = GNUNET_NO;
1345 break;
1346 case SQLITE_ROW:
1347 ret = cb (cb_cls, name, sqlite3_column_blob (stmt, 0),
1348 sqlite3_column_bytes (stmt, 0));
1349 break;
1350 default:
1351 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1352 "select_state_one (step)");
1353 }
1354 }
774 1355
1356 if (SQLITE_OK != sqlite3_reset (stmt))
1357 {
1358 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1359 "select_state_one (reset)");
1360 }
1361
1362
1363 return ret;
775} 1364}
776 1365
1366
777/** 1367/**
778 * Retrieve all state variables for a channel with the given prefix. 1368 * Retrieve all state variables for a channel with the given prefix.
779 * 1369 *
@@ -781,21 +1371,130 @@ libgnunet_plugin_psycstore_sqlite_state_get
781 * 1371 *
782 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 1372 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
783 */ 1373 */
784int 1374static int
785libgnunet_plugin_psycstore_sqlite_state_get_all 1375state_get_all (void *cls, const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
786 (struct GNUNET_PSYCSTORE_Handle *h, 1376 const char *name, GNUNET_PSYCSTORE_StateCallback cb,
787 const struct GNUNET_CRYPTO_EccPublicKey *channel_key, 1377 void *cb_cls)
788 const char *name, 1378{
789 GNUNET_PSYCSTORE_StateCallback cb, 1379 struct Plugin *plugin = cls;
790 void *cb_cls) { 1380 int ret = GNUNET_SYSERR;
1381
1382 sqlite3_stmt *stmt = plugin->select_state_prefix;
1383 size_t name_len = strlen (name);
1384 char *name_prefix = GNUNET_malloc (name_len + 2);
1385 memcpy (name_prefix, name, name_len);
1386 memcpy (name_prefix + name_len, "_%", 2);
1387
1388 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1389 sizeof (*channel_key), SQLITE_STATIC) ||
1390 SQLITE_OK != sqlite3_bind_text (stmt, 2, name, name_len, SQLITE_STATIC) ||
1391 SQLITE_OK != sqlite3_bind_text (stmt, 3, name_prefix, name_len + 2,
1392 SQLITE_STATIC))
1393 {
1394 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1395 "select_state_prefix (bind)");
1396 }
1397 else
1398 {
1399 int sql_ret;
1400 do
1401 {
1402 sql_ret = sqlite3_step (stmt);
1403 switch (sql_ret)
1404 {
1405 case SQLITE_DONE:
1406 if (ret != GNUNET_OK)
1407 ret = GNUNET_NO;
1408 break;
1409 case SQLITE_ROW:
1410 ret = cb (cb_cls, (const char *) sqlite3_column_text (stmt, 0),
1411 sqlite3_column_blob (stmt, 1),
1412 sqlite3_column_bytes (stmt, 1));
1413 if (ret != GNUNET_YES)
1414 sql_ret = SQLITE_DONE;
1415 break;
1416 default:
1417 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1418 "select_state_prefix (step)");
1419 }
1420 }
1421 while (sql_ret == SQLITE_ROW);
1422 }
1423
1424 if (SQLITE_OK != sqlite3_reset (stmt))
1425 {
1426 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1427 "select_state_prefix (reset)");
1428 }
791 1429
1430 return ret;
792} 1431}
793 1432
794 1433
795/** 1434/**
1435 * Retrieve all signed state variables for a channel.
1436 *
1437 * @see GNUNET_PSYCSTORE_state_get_signed()
1438 *
1439 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
1440 */
1441static int
1442state_get_signed (void *cls,
1443 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
1444 GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls)
1445{
1446 struct Plugin *plugin = cls;
1447 int ret = GNUNET_SYSERR;
1448
1449 sqlite3_stmt *stmt = plugin->select_state_signed;
1450
1451 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key,
1452 sizeof (*channel_key), SQLITE_STATIC))
1453 {
1454 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1455 "select_state_signed (bind)");
1456 }
1457 else
1458 {
1459 int sql_ret;
1460 do
1461 {
1462 sql_ret = sqlite3_step (stmt);
1463 switch (sql_ret)
1464 {
1465 case SQLITE_DONE:
1466 if (ret != GNUNET_OK)
1467 ret = GNUNET_NO;
1468 break;
1469 case SQLITE_ROW:
1470 ret = cb (cb_cls, (const char *) sqlite3_column_text (stmt, 0),
1471 sqlite3_column_blob (stmt, 1),
1472 sqlite3_column_bytes (stmt, 1));
1473 if (ret != GNUNET_YES)
1474 sql_ret = SQLITE_DONE;
1475 break;
1476 default:
1477 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1478 "select_state_signed (step)");
1479 }
1480 }
1481 while (sql_ret == SQLITE_ROW);
1482 }
1483
1484 if (SQLITE_OK != sqlite3_reset (stmt))
1485 {
1486 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1487 "select_state_signed (reset)");
1488 }
1489
1490 return ret;
1491}
1492
1493
1494/**
796 * Entry point for the plugin. 1495 * Entry point for the plugin.
797 * 1496 *
798 * @param cls the "struct GNUNET_PSYCSTORE_PluginEnvironment*" 1497 * @param cls The struct GNUNET_CONFIGURATION_Handle.
799 * @return NULL on error, otherwise the plugin context 1498 * @return NULL on error, otherwise the plugin context
800 */ 1499 */
801void * 1500void *
@@ -816,21 +1515,23 @@ libgnunet_plugin_psycstore_sqlite_init (void *cls)
816 } 1515 }
817 api = GNUNET_new (struct GNUNET_PSYCSTORE_PluginFunctions); 1516 api = GNUNET_new (struct GNUNET_PSYCSTORE_PluginFunctions);
818 api->cls = &plugin; 1517 api->cls = &plugin;
819 api->membership_store = &libgnunet_plugin_psycstore_sqlite_membership_store; 1518 api->membership_store = &membership_store;
820 api->membership_test = &libgnunet_plugin_psycstore_sqlite_membership_test; 1519 api->membership_test = &membership_test;
821 api->fragment_store = &libgnunet_plugin_psycstore_sqlite_fragment_store; 1520 api->fragment_store = &fragment_store;
822 api->fragment_add_flags = &libgnunet_plugin_psycstore_sqlite_fragment_add_flags; 1521 api->message_add_flags = &message_add_flags;
823 api->fragment_get = &libgnunet_plugin_psycstore_sqlite_fragment_get; 1522 api->fragment_get = &fragment_get;
824 api->message_get = &libgnunet_plugin_psycstore_sqlite_message_get; 1523 api->message_get = &message_get;
825 api->message_get_fragment = &libgnunet_plugin_psycstore_sqlite_message_get_fragment; 1524 api->message_get_fragment = &message_get_fragment;
826 api->counters_get_master = &libgnunet_plugin_psycstore_sqlite_counters_get_master; 1525 api->counters_get_master = &counters_get_master;
827 api->counters_get_slave = &libgnunet_plugin_psycstore_sqlite_counters_get_slave; 1526 api->counters_get_slave = &counters_get_slave;
828 api->state_set = &libgnunet_plugin_psycstore_sqlite_state_set; 1527 api->state_set = &state_set;
829 api->state_get = &libgnunet_plugin_psycstore_sqlite_state_get; 1528 api->state_reset = &state_reset;
830 api->state_get_all = &libgnunet_plugin_psycstore_sqlite_state_get_all; 1529 api->state_update_signed = &state_update_signed;
831 1530 api->state_get = &state_get;
832 LOG (GNUNET_ERROR_TYPE_INFO, 1531 api->state_get_all = &state_get_all;
833 _("Sqlite database running\n")); 1532 api->state_get_signed = &state_get_signed;
1533
1534 LOG (GNUNET_ERROR_TYPE_INFO, _("SQLite database running\n"));
834 return api; 1535 return api;
835} 1536}
836 1537
@@ -838,8 +1539,8 @@ libgnunet_plugin_psycstore_sqlite_init (void *cls)
838/** 1539/**
839 * Exit point from the plugin. 1540 * Exit point from the plugin.
840 * 1541 *
841 * @param cls the plugin context (as returned by "init") 1542 * @param cls The plugin context (as returned by "init")
842 * @return always NULL 1543 * @return Always NULL
843 */ 1544 */
844void * 1545void *
845libgnunet_plugin_psycstore_sqlite_done (void *cls) 1546libgnunet_plugin_psycstore_sqlite_done (void *cls)
@@ -850,8 +1551,7 @@ libgnunet_plugin_psycstore_sqlite_done (void *cls)
850 database_shutdown (plugin); 1551 database_shutdown (plugin);
851 plugin->cfg = NULL; 1552 plugin->cfg = NULL;
852 GNUNET_free (api); 1553 GNUNET_free (api);
853 LOG (GNUNET_ERROR_TYPE_DEBUG, 1554 LOG (GNUNET_ERROR_TYPE_DEBUG, "SQLite plugin is finished\n");
854 "sqlite plugin is finished\n");
855 return NULL; 1555 return NULL;
856} 1556}
857 1557
diff --git a/src/psycstore/psycstore.conf b/src/psycstore/psycstore.conf
index 5b8dfee68..3f86d7b45 100644
--- a/src/psycstore/psycstore.conf
+++ b/src/psycstore/psycstore.conf
@@ -2,7 +2,7 @@
2AUTOSTART = YES 2AUTOSTART = YES
3HOME = $SERVICEHOME 3HOME = $SERVICEHOME
4BINARY = gnunet-service-psycstore 4BINARY = gnunet-service-psycstore
5UNIXPATH = /tmp/gnunet-service-psycstore.unix 5UNIXPATH = /tmp/gnunet-service-psycstore.sock
6UNIX_MATCH_UID = NO 6UNIX_MATCH_UID = NO
7UNIX_MATCH_GID = YES 7UNIX_MATCH_GID = YES
8DATABASE = sqlite 8DATABASE = sqlite
diff --git a/src/psycstore/psycstore.h b/src/psycstore/psycstore.h
index f1a1c787a..2e3d66ec5 100644
--- a/src/psycstore/psycstore.h
+++ b/src/psycstore/psycstore.h
@@ -35,7 +35,7 @@ GNUNET_NETWORK_STRUCT_BEGIN
35/** 35/**
36 * Answer from service to client about last operation. 36 * Answer from service to client about last operation.
37 */ 37 */
38struct GNUNET_PSYCSTORE_ResultCodeMessage 38struct ResultCodeMessage
39{ 39{
40 /** 40 /**
41 * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE 41 * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE
@@ -52,6 +52,32 @@ struct GNUNET_PSYCSTORE_ResultCodeMessage
52 52
53}; 53};
54 54
55
56/**
57 * @see GNUNET_PSYCSTORE_membership_store()
58 */
59struct MembershipStoreMessage
60{
61 const struct GNUNET_CRYPTO_EccPublicKey *channel_key;
62 const struct GNUNET_CRYPTO_EccPublicKey *slave_key;
63 int did_join;
64 uint64_t announced_at;
65 uint64_t effective_since;
66 uint64_t group_generation;
67};
68
69
70/**
71 * @see GNUNET_PSYCSTORE_membership_test()
72 */
73struct MembershipTestMessage
74{
75 const struct GNUNET_CRYPTO_EccPublicKey *channel_key;
76 const struct GNUNET_CRYPTO_EccPublicKey *slave_key;
77 uint64_t message_id;
78 uint64_t group_generation;
79};
80
55GNUNET_NETWORK_STRUCT_END 81GNUNET_NETWORK_STRUCT_END
56 82
57#endif 83#endif
diff --git a/src/psycstore/psycstore_api.c b/src/psycstore/psycstore_api.c
index d8d5134b6..194dcc79e 100644
--- a/src/psycstore/psycstore_api.c
+++ b/src/psycstore/psycstore_api.c
@@ -187,7 +187,7 @@ message_handler (void *cls,
187{ 187{
188 struct GNUNET_PSYCSTORE_Handle *h = cls; 188 struct GNUNET_PSYCSTORE_Handle *h = cls;
189 struct GNUNET_PSYCSTORE_OperationHandle *op; 189 struct GNUNET_PSYCSTORE_OperationHandle *op;
190 const struct GNUNET_PSYCSTORE_ResultCodeMessage *rcm; 190 const struct ResultCodeMessage *rcm;
191 const char *str; 191 const char *str;
192 uint16_t size; 192 uint16_t size;
193 193
@@ -203,22 +203,22 @@ message_handler (void *cls,
203 switch (ntohs (msg->type)) 203 switch (ntohs (msg->type))
204 { 204 {
205 case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE: 205 case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE:
206 if (size < sizeof (struct GNUNET_PSYCSTORE_ResultCodeMessage)) 206 if (size < sizeof (struct ResultCodeMessage))
207 { 207 {
208 GNUNET_break (0); 208 GNUNET_break (0);
209 reschedule_connect (h); 209 reschedule_connect (h);
210 return; 210 return;
211 } 211 }
212 rcm = (const struct GNUNET_PSYCSTORE_ResultCodeMessage *) msg; 212 rcm = (const struct ResultCodeMessage *) msg;
213 str = (const char *) &rcm[1]; 213 str = (const char *) &rcm[1];
214 if ( (size > sizeof (struct GNUNET_PSYCSTORE_ResultCodeMessage)) && 214 if ( (size > sizeof (struct ResultCodeMessage)) &&
215 ('\0' != str[size - sizeof (struct GNUNET_PSYCSTORE_ResultCodeMessage) - 1]) ) 215 ('\0' != str[size - sizeof (struct ResultCodeMessage) - 1]) )
216 { 216 {
217 GNUNET_break (0); 217 GNUNET_break (0);
218 reschedule_connect (h); 218 reschedule_connect (h);
219 return; 219 return;
220 } 220 }
221 if (size == sizeof (struct GNUNET_PSYCSTORE_ResultCodeMessage)) 221 if (size == sizeof (struct ResultCodeMessage))
222 str = NULL; 222 str = NULL;
223 223
224 op = h->op_head; 224 op = h->op_head;
@@ -341,7 +341,6 @@ reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
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 transmit_next (h); 343 transmit_next (h);
344 GNUNET_assert (NULL != h->th);
345} 344}
346 345
347 346
@@ -399,7 +398,7 @@ GNUNET_PSYCSTORE_disconnect (struct GNUNET_PSYCSTORE_Handle *h)
399 * was already transmitted, the service may still choose to complete 398 * was already transmitted, the service may still choose to complete
400 * the operation. 399 * the operation.
401 * 400 *
402 * @param op operation to cancel 401 * @param op Operation to cancel.
403 */ 402 */
404void 403void
405GNUNET_PSYCSTORE_operation_cancel (struct GNUNET_PSYCSTORE_OperationHandle *op) 404GNUNET_PSYCSTORE_operation_cancel (struct GNUNET_PSYCSTORE_OperationHandle *op)
@@ -435,4 +434,33 @@ GNUNET_PSYCSTORE_operation_cancel (struct GNUNET_PSYCSTORE_OperationHandle *op)
435} 434}
436 435
437 436
437struct GNUNET_PSYCSTORE_OperationHandle *
438GNUNET_PSYCSTORE_membership_store (
439 struct GNUNET_PSYCSTORE_Handle *h,
440 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
441 const struct GNUNET_CRYPTO_EccPublicKey *slave_key,
442 int did_join,
443 uint64_t announced_at,
444 uint64_t effective_since,
445 uint64_t group_generation,
446 GNUNET_PSYCSTORE_ResultCallback rcb,
447 void *rcb_cls)
448{
449
450}
451
452
453struct GNUNET_PSYCSTORE_OperationHandle *
454GNUNET_PSYCSTORE_membership_test (
455 struct GNUNET_PSYCSTORE_Handle *h,
456 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
457 const struct GNUNET_CRYPTO_EccPublicKey *slave_key,
458 uint64_t message_id,
459 uint64_t group_generation,
460 GNUNET_PSYCSTORE_ResultCallback rcb,
461 void *rcb_cls)
462{
463
464}
465
438/* end of psycstore_api.c */ 466/* end of psycstore_api.c */
diff --git a/src/psycstore/test_plugin_psycstore.c b/src/psycstore/test_plugin_psycstore.c
new file mode 100644
index 000000000..52a306f07
--- /dev/null
+++ b/src/psycstore/test_plugin_psycstore.c
@@ -0,0 +1,375 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/*
21 * @file psycstore/test_plugin_psycstore.c
22 * @brief Test for the psycstore plugins
23 * @author Gabor X Toth
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib.h"
29#include "gnunet_psycstore_plugin.h"
30#include "gnunet_psycstore_service.h"
31#include "gnunet_multicast_service.h"
32
33#define DEBUG_PSYCSTORE GNUNET_EXTRA_LOGGING
34#if DEBUG_PSYCSTORE
35# define LOG_LEVEL "DEBUG"
36#else
37# define LOG_LEVEL "WARNING"
38#endif
39
40#define C2ARG(str) str, (sizeof (str) - 1)
41
42#define LOG(kind,...) GNUNET_log_from (kind, "test-plugin-psycstore", __VA_ARGS__)
43
44#define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__, __LINE__); goto FAILURE;} } while (0)
45
46static int ok;
47
48/**
49 * Name of plugin under test.
50 */
51static const char *plugin_name;
52
53static struct GNUNET_CRYPTO_EccPrivateKey *channel_key;
54static struct GNUNET_CRYPTO_EccPrivateKey *slave_key;
55
56static struct GNUNET_CRYPTO_EccPublicKey channel_pub_key;
57static struct GNUNET_CRYPTO_EccPublicKey slave_pub_key;
58
59/**
60 * Function called when the service shuts down. Unloads our psycstore
61 * plugin.
62 *
63 * @param api api to unload
64 */
65static void
66unload_plugin (struct GNUNET_PSYCSTORE_PluginFunctions *api)
67{
68 char *libname;
69
70 GNUNET_asprintf (&libname, "libgnunet_plugin_psycstore_%s", plugin_name);
71 GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api));
72 GNUNET_free (libname);
73}
74
75
76/**
77 * Load the psycstore plugin.
78 *
79 * @param cfg configuration to pass
80 * @return NULL on error
81 */
82static struct GNUNET_PSYCSTORE_PluginFunctions *
83load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg)
84{
85 struct GNUNET_PSYCSTORE_PluginFunctions *ret;
86 char *libname;
87
88 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' psycstore plugin\n"),
89 plugin_name);
90 GNUNET_asprintf (&libname, "libgnunet_plugin_psycstore_%s", plugin_name);
91 if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void*) cfg)))
92 {
93 FPRINTF (stderr, "Failed to load plugin `%s'!\n", plugin_name);
94 return NULL;
95 }
96 GNUNET_free (libname);
97 return ret;
98}
99
100
101struct FragmentClosure
102{
103 uint8_t n;
104 uint64_t flags[16];
105 struct GNUNET_MULTICAST_MessageHeader *msg[16];
106};
107
108static int
109fragment_cb (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg2,
110 enum GNUNET_PSYCSTORE_MessageFlags flags)
111{
112 struct FragmentClosure *fcls = cls;
113 struct GNUNET_MULTICAST_MessageHeader *msg1 = fcls->msg[fcls->n];
114 uint64_t flags1 = fcls->flags[fcls->n++];
115 int ret;
116
117 if (flags1 == flags && msg1->header.size == msg2->header.size
118 && 0 == memcmp (msg1, msg2, ntohs (msg1->header.size)))
119 {
120 LOG (GNUNET_ERROR_TYPE_DEBUG, "Fragment %llu matches\n",
121 msg1->fragment_id);
122 ret = GNUNET_YES;
123 }
124 else
125 {
126 LOG (GNUNET_ERROR_TYPE_ERROR, "Fragment %llu differs\n",
127 msg1->fragment_id);
128 ret = GNUNET_SYSERR;
129 }
130
131 GNUNET_free (msg2);
132 return ret;
133}
134
135
136struct StateClosure {
137 size_t n;
138 void *value[16];
139 size_t value_size[16];
140};
141
142static int
143state_cb (void *cls, const char *name, const void *value, size_t value_size)
144{
145 struct StateClosure *scls = cls;
146 const void *val = scls->value[scls->n];
147 size_t val_size = scls->value_size[scls->n++];
148
149 return value_size == val_size && 0 == memcmp (value, val, val_size)
150 ? GNUNET_YES
151 : GNUNET_SYSERR;
152}
153
154
155static void
156run (void *cls, char *const *args, const char *cfgfile,
157 const struct GNUNET_CONFIGURATION_Handle *cfg)
158{
159 struct GNUNET_PSYCSTORE_PluginFunctions *db;
160
161 ok = 1;
162 db = load_plugin (cfg);
163 if (NULL == db)
164 {
165 FPRINTF (stderr,
166 "%s",
167 "Failed to initialize PSYCstore. "
168 "Database likely not setup, skipping test.\n");
169 return;
170 }
171
172 /* Membership */
173
174 channel_key = GNUNET_CRYPTO_ecc_key_create ();
175 slave_key = GNUNET_CRYPTO_ecc_key_create ();
176
177 GNUNET_CRYPTO_ecc_key_get_public (channel_key, &channel_pub_key);
178 GNUNET_CRYPTO_ecc_key_get_public (slave_key, &slave_pub_key);
179
180 ASSERT (GNUNET_OK == db->membership_store(db->cls, &channel_pub_key,
181 &slave_pub_key, GNUNET_YES,
182 4, 2, 1));
183
184 ASSERT (GNUNET_YES == db->membership_test(db->cls, &channel_pub_key,
185 &slave_pub_key, 4));
186
187 ASSERT (GNUNET_YES == db->membership_test(db->cls, &channel_pub_key,
188 &slave_pub_key, 2));
189
190 ASSERT (GNUNET_NO == db->membership_test(db->cls, &channel_pub_key,
191 &slave_pub_key, 1));
192
193
194 /* Messages */
195
196 struct GNUNET_MULTICAST_MessageHeader *msg
197 = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
198 ASSERT (msg != NULL);
199
200 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
201 msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key));
202
203 msg->hop_counter = 9;
204 msg->fragment_id = INT64_MAX - 1;
205 msg->fragment_offset = 0;
206 msg->message_id = INT64_MAX - 2;
207 msg->group_generation = INT64_MAX - 3;
208 msg->flags = GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT;
209
210 memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key));
211
212 msg->purpose.size = htonl (ntohs (msg->header.size)
213 - sizeof (msg->header)
214 - sizeof (msg->hop_counter)
215 - sizeof (msg->signature));
216 msg->purpose.purpose = htonl (234);
217 GNUNET_CRYPTO_ecc_sign (slave_key, &msg->purpose, &msg->signature);
218
219 struct FragmentClosure fcls = { 0 };
220 fcls.n = 0;
221 fcls.msg[0] = msg;
222 fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE;
223
224 ASSERT (GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg,
225 fcls.flags[0]));
226
227 ASSERT (GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key,
228 msg->fragment_id,
229 fragment_cb, &fcls));
230 ASSERT (fcls.n == 1);
231
232 fcls.n = 0;
233
234 ASSERT (GNUNET_OK == db->message_get_fragment (db->cls, &channel_pub_key,
235 msg->message_id,
236 msg->fragment_offset,
237 fragment_cb, &fcls));
238 ASSERT (fcls.n == 1);
239
240 ASSERT (GNUNET_OK == db->message_add_flags (
241 db->cls, &channel_pub_key, msg->message_id,
242 GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED));
243
244 fcls.n = 0;
245 fcls.flags[0] |= GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED;
246
247 ASSERT (GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key,
248 msg->fragment_id,
249 fragment_cb, &fcls));
250 ASSERT (fcls.n == 1);
251
252 struct GNUNET_MULTICAST_MessageHeader *msg1
253 = GNUNET_malloc (sizeof (*msg1) + sizeof (channel_pub_key));
254
255 memcpy (msg1, msg, sizeof (*msg1) + sizeof (channel_pub_key));
256
257 msg1->fragment_id++;
258 msg1->fragment_offset += 32768;
259
260 fcls.n = 0;
261 fcls.msg[1] = msg1;
262 fcls.flags[1] = GNUNET_PSYCSTORE_MESSAGE_STATE_HASH;
263
264 ASSERT (GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg1,
265 fcls.flags[1]));
266
267 ASSERT (GNUNET_OK == db->message_get (db->cls, &channel_pub_key,
268 msg->message_id,
269 fragment_cb, &fcls));
270 ASSERT (fcls.n == 2);
271
272 uint64_t max_state_msg_id = 0;
273 ASSERT (GNUNET_OK == db->counters_get_slave (db->cls, &channel_pub_key,
274 &max_state_msg_id)
275 && max_state_msg_id == msg->message_id);
276
277 uint64_t fragment_id = 0, message_id = 0, group_generation = 0;
278 ASSERT (GNUNET_OK == db->counters_get_master (db->cls, &channel_pub_key,
279 &fragment_id, &message_id,
280 &group_generation)
281 && fragment_id == msg1->fragment_id
282 && message_id == msg1->message_id
283 && group_generation == msg1->group_generation);
284
285
286 /* State */
287
288 ASSERT (GNUNET_OK == db->state_set (db->cls, &channel_pub_key, "_foo",
289 C2ARG("one two three")));
290
291 ASSERT (GNUNET_OK == db->state_set (db->cls, &channel_pub_key, "_foo_bar",
292 slave_key,
293 sizeof (*slave_key)));
294
295 struct StateClosure scls = { 0 };
296 scls.n = 0;
297 scls.value[0] = "one two three";
298 scls.value_size[0] = strlen ("one two three");
299
300 ASSERT (GNUNET_OK == db->state_get (db->cls, &channel_pub_key, "_foo",
301 state_cb, &scls));
302 ASSERT (scls.n == 1);
303
304 scls.n = 0;
305 scls.value[1] = slave_key;
306 scls.value_size[1] = sizeof (*slave_key);
307
308 ASSERT (GNUNET_OK == db->state_get_all (db->cls, &channel_pub_key, "_foo",
309 state_cb, &scls));
310 ASSERT (scls.n == 2);
311
312 scls.n = 0;
313 ASSERT (GNUNET_NO == db->state_get_signed (db->cls, &channel_pub_key,
314 state_cb, &scls));
315 ASSERT (scls.n == 0);
316
317 ASSERT (GNUNET_OK == db->state_update_signed (db->cls, &channel_pub_key));
318
319 scls.n = 0;
320 ASSERT (GNUNET_YES == db->state_get_signed (db->cls, &channel_pub_key,
321 state_cb, &scls));
322 ASSERT (scls.n == 2);
323
324 ok = 0;
325
326FAILURE:
327
328 if (NULL != channel_key)
329 {
330 GNUNET_free (channel_key);
331 channel_key = NULL;
332 }
333 if (NULL != slave_key)
334 {
335 GNUNET_free (slave_key);
336 slave_key = NULL;
337 }
338
339 unload_plugin (db);
340}
341
342
343int
344main (int argc, char *argv[])
345{
346 char cfg_name[128];
347 char *const xargv[] = {
348 "test-plugin-psycstore",
349 "-c", cfg_name,
350 "-L", LOG_LEVEL,
351 NULL
352 };
353 struct GNUNET_GETOPT_CommandLineOption options[] = {
354 GNUNET_GETOPT_OPTION_END
355 };
356
357 GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-psycstore-sqlite");
358 GNUNET_log_setup ("test-plugin-psycstore", LOG_LEVEL, NULL);
359 plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
360 GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_plugin_psycstore_%s.conf",
361 plugin_name);
362 GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv,
363 "test-plugin-psycstore", "nohelp", options, &run, NULL);
364
365 if (ok != 0)
366 FPRINTF (stderr, "Missed some testcases: %d\n", ok);
367
368#if ! DEBUG_PSYCSTORE
369 GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-psycstore-sqlite");
370#endif
371
372 return ok;
373}
374
375/* end of test_plugin_psycstore.c */
diff --git a/src/psycstore/test_plugin_psycstore_sqlite.conf b/src/psycstore/test_plugin_psycstore_sqlite.conf
new file mode 100644
index 000000000..7cde6fa4c
--- /dev/null
+++ b/src/psycstore/test_plugin_psycstore_sqlite.conf
@@ -0,0 +1,2 @@
1[psycstore-sqlite]
2FILENAME = /tmp/gnunet-test-plugin-psycstore-sqlite/sqlite.db
diff --git a/src/psycstore/test_psycstore.c b/src/psycstore/test_psycstore.c
index 405d1622c..6b9e77180 100644
--- a/src/psycstore/test_psycstore.c
+++ b/src/psycstore/test_psycstore.c
@@ -48,13 +48,18 @@ static struct GNUNET_PSYCSTORE_Handle *h;
48/** 48/**
49 * Handle to PSYCstore operation. 49 * Handle to PSYCstore operation.
50 */ 50 */
51static struct GNUNET_PSYCSTORE_Operation *op; 51static struct GNUNET_PSYCSTORE_OperationHandle *op;
52 52
53/** 53/**
54 * Handle for task for timeout termination. 54 * Handle for task for timeout termination.
55 */ 55 */
56static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; 56static GNUNET_SCHEDULER_TaskIdentifier endbadly_task;
57 57
58static struct GNUNET_CRYPTO_EccPrivateKey *channel_key;
59static struct GNUNET_CRYPTO_EccPrivateKey *slave_key;
60
61static struct GNUNET_CRYPTO_EccPublicKey channel_pub_key;
62static struct GNUNET_CRYPTO_EccPublicKey slave_pub_key;
58 63
59/** 64/**
60 * Clean up all resources used. 65 * Clean up all resources used.
@@ -72,6 +77,16 @@ cleanup ()
72 GNUNET_PSYCSTORE_disconnect (h); 77 GNUNET_PSYCSTORE_disconnect (h);
73 h = NULL; 78 h = NULL;
74 } 79 }
80 if (NULL != channel_key)
81 {
82 GNUNET_free (channel_key);
83 channel_key = NULL;
84 }
85 if (NULL != slave_key)
86 {
87 GNUNET_free (slave_key);
88 slave_key = NULL;
89 }
75 GNUNET_SCHEDULER_shutdown (); 90 GNUNET_SCHEDULER_shutdown ();
76} 91}
77 92
@@ -119,6 +134,11 @@ end ()
119 &end_normally, NULL); 134 &end_normally, NULL);
120} 135}
121 136
137void
138membership_store_result (void *cls, int result, const char *err_msg)
139{
140
141}
122 142
123/** 143/**
124 * Main function of the test, run from scheduler. 144 * Main function of the test, run from scheduler.
@@ -136,6 +156,17 @@ run (void *cls,
136 &endbadly, NULL); 156 &endbadly, NULL);
137 h = GNUNET_PSYCSTORE_connect (cfg); 157 h = GNUNET_PSYCSTORE_connect (cfg);
138 GNUNET_assert (NULL != h); 158 GNUNET_assert (NULL != h);
159
160 channel_key = GNUNET_CRYPTO_ecc_key_create ();
161 slave_key = GNUNET_CRYPTO_ecc_key_create ();
162
163 GNUNET_CRYPTO_ecc_key_get_public (channel_key, &channel_pub_key);
164 GNUNET_CRYPTO_ecc_key_get_public (slave_key, &slave_pub_key);
165
166 op = GNUNET_PSYCSTORE_membership_store (h, &channel_pub_key, &slave_pub_key,
167 GNUNET_YES, 2, 2, 1,
168 &membership_store_result, NULL);
169
139 end (); 170 end ();
140} 171}
141 172
diff --git a/src/psycstore/test_psycstore.conf b/src/psycstore/test_psycstore.conf
index 1f6d279ab..ea3031524 100644
--- a/src/psycstore/test_psycstore.conf
+++ b/src/psycstore/test_psycstore.conf
@@ -3,4 +3,13 @@ DEFAULTSERVICES = psycstore
3UNIXPATH = /tmp/test-psycstore-service-arm.sock 3UNIXPATH = /tmp/test-psycstore-service-arm.sock
4 4
5[psycstore] 5[psycstore]
6DBFILE = /tmp/test-psycstore-service.sqlite 6AUTOSTART = YES
7HOME = $SERVICEHOME
8BINARY = gnunet-service-psycstore
9UNIXPATH = /tmp/test-gnunet-service-psycstore.sock
10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES
12DATABASE = sqlite
13
14[psycstore-sqlite]
15FILENAME = $SERVICEHOME/psycstore/sqlite_test.db