- not required anymore
[oweals/gnunet.git] / src / namestore / plugin_namestore_sqlite.c
1  /*
2   * This file is part of GNUnet
3   * (C) 2009, 2011, 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 /**
22  * @file namestore/plugin_namestore_sqlite.c
23  * @brief sqlite-based namestore backend
24  * @author Christian Grothoff
25  */
26
27 #include "platform.h"
28 #include "gnunet_namestore_plugin.h"
29 #include "gnunet_namestore_service.h"
30 #include <sqlite3.h>
31
32 /**
33  * After how many ms "busy" should a DB operation fail for good?
34  * A low value makes sure that we are more responsive to requests
35  * (especially PUTs).  A high value guarantees a higher success
36  * rate (SELECTs in iterate can take several seconds despite LIMIT=1).
37  *
38  * The default value of 1s should ensure that users do not experience
39  * huge latencies while at the same time allowing operations to succeed
40  * with reasonable probability.
41  */
42 #define BUSY_TIMEOUT_MS 1000
43
44
45 /**
46  * Log an error message at log-level 'level' that indicates
47  * a failure of the command 'cmd' on file 'filename'
48  * with the message given by strerror(errno).
49  */
50 #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "namestore-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
51
52 #define LOG(kind,...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__)
53
54
55 /**
56  * Context for all functions in this plugin.
57  */
58 struct Plugin
59 {
60
61   const struct GNUNET_CONFIGURATION_Handle *cfg;
62
63   /**
64    * Database filename.
65    */
66   char *fn;
67
68   /**
69    * Native SQLite database handle.
70    */
71   sqlite3 *dbh;
72
73   /**
74    * Precompiled SQL for put record
75    */
76   sqlite3_stmt *put_records;
77
78   /**
79    * Precompiled SQL for remove record
80    */
81   sqlite3_stmt *remove_records;
82
83   /**
84    * Precompiled SQL for iterate over all records.
85    */
86   sqlite3_stmt *iterate_all;
87
88   /**
89    * Precompiled SQL for iterate records with same name.
90    */
91   sqlite3_stmt *iterate_by_name;
92
93   /**
94    * Precompiled SQL for iterate records with same zone.
95    */
96   sqlite3_stmt *iterate_by_zone;
97
98   /**
99    * Precompiled SQL for iterate records with same name and zone.
100    */
101   sqlite3_stmt *iterate_records;
102
103   /**
104    * Precompiled SQL to get the name for a given zone-value.
105    */
106   sqlite3_stmt *zone_to_name;
107
108   /**
109    * Precompiled SQL for delete zone
110    */
111   sqlite3_stmt *delete_zone;
112
113 };
114
115
116 /**
117  * @brief Prepare a SQL statement
118  *
119  * @param dbh handle to the database
120  * @param zSql SQL statement, UTF-8 encoded
121  * @param ppStmt set to the prepared statement
122  * @return 0 on success
123  */
124 static int
125 sq_prepare (sqlite3 * dbh, const char *zSql, sqlite3_stmt ** ppStmt)
126 {
127   char *dummy;
128   int result;
129
130   result =
131       sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt,
132                           (const char **) &dummy);
133   LOG (GNUNET_ERROR_TYPE_DEBUG, 
134        "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result);
135   return result;
136 }
137
138
139 /**
140  * Create our database indices.
141  *
142  * @param dbh handle to the database
143  */
144 static void
145 create_indices (sqlite3 * dbh)
146 {
147   /* create indices */
148   if ( (SQLITE_OK !=
149         sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_name_rv ON ns091records (zone_hash,record_name_hash,rvalue)",
150                       NULL, NULL, NULL)) ||
151        (SQLITE_OK !=
152         sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_delegation ON ns091records (zone_hash,zone_delegation)",
153                       NULL, NULL, NULL)) ||
154        (SQLITE_OK !=
155         sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_rv ON ns091records (zone_hash,rvalue)",
156                       NULL, NULL, NULL)) ||
157        (SQLITE_OK !=
158         sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone ON ns091records (zone_hash)",
159                       NULL, NULL, NULL)) ||
160        (SQLITE_OK !=
161         sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_name_rv ON ns091records (record_name_hash,rvalue)",
162                       NULL, NULL, NULL)) ||
163        (SQLITE_OK !=
164         sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_rv ON ns091records (rvalue)",
165                       NULL, NULL, NULL)) )    
166     LOG (GNUNET_ERROR_TYPE_ERROR, 
167          "Failed to create indices: %s\n", sqlite3_errmsg (dbh));
168 }
169
170
171 #if 0
172 #define CHECK(a) GNUNET_break(a)
173 #define ENULL NULL
174 #else
175 #define ENULL &e
176 #define ENULL_DEFINED 1
177 #define CHECK(a) if (! a) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
178 #endif
179
180
181 /**
182  * Initialize the database connections and associated
183  * data structures (create tables and indices
184  * as needed as well).
185  *
186  * @param plugin the plugin context (state for this module)
187  * @return GNUNET_OK on success
188  */
189 static int
190 database_setup (struct Plugin *plugin)
191 {
192   sqlite3_stmt *stmt;
193   char *afsdir;
194 #if ENULL_DEFINED
195   char *e;
196 #endif
197
198   if (GNUNET_OK !=
199       GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "namestore-sqlite",
200                                                "FILENAME", &afsdir))
201     {
202     LOG (GNUNET_ERROR_TYPE_ERROR, 
203          _ ("Option `%s' in section `%s' missing in configuration!\n"),
204          "FILENAME", "namestore-sqlite");
205     return GNUNET_SYSERR;
206   }
207   if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
208   {
209     if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir))
210     {
211       GNUNET_break (0);
212       GNUNET_free (afsdir);
213       return GNUNET_SYSERR;
214     }
215   }
216 #ifdef ENABLE_NLS
217   plugin->fn =
218       GNUNET_STRINGS_to_utf8 (afsdir, strlen (afsdir), nl_langinfo (CODESET));
219 #else
220   plugin->fn = GNUNET_STRINGS_to_utf8 (afsdir, strlen (afsdir), "UTF-8");       /* good luck */
221 #endif
222   GNUNET_free (afsdir);
223
224   /* Open database and precompile statements */
225   if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
226   {
227     LOG (GNUNET_ERROR_TYPE_ERROR,
228          _("Unable to initialize SQLite: %s.\n"),
229          sqlite3_errmsg (plugin->dbh));
230     return GNUNET_SYSERR;
231   }
232   CHECK (SQLITE_OK ==
233          sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL,
234                        ENULL));
235   CHECK (SQLITE_OK ==
236          sqlite3_exec (plugin->dbh, "PRAGMA synchronous=NORMAL", NULL, NULL,
237                        ENULL));
238   CHECK (SQLITE_OK ==
239          sqlite3_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF", NULL, NULL,
240                        ENULL));
241   CHECK (SQLITE_OK ==
242          sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL,
243                        NULL, ENULL));
244   CHECK (SQLITE_OK ==
245          sqlite3_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\"", NULL,
246                        NULL, ENULL));
247   CHECK (SQLITE_OK ==
248          sqlite3_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
249                        ENULL));
250   CHECK (SQLITE_OK ==
251          sqlite3_exec (plugin->dbh, "PRAGMA count_changes=OFF", NULL, NULL,
252                        ENULL));
253   CHECK (SQLITE_OK ==
254          sqlite3_exec (plugin->dbh, "PRAGMA page_size=4092", NULL, NULL,
255                        ENULL));
256
257   CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS));
258
259
260   /* Create tables */
261   CHECK (SQLITE_OK ==
262          sq_prepare (plugin->dbh,
263                      "SELECT 1 FROM sqlite_master WHERE tbl_name = 'ns091records'",
264                      &stmt));
265   if ((sqlite3_step (stmt) == SQLITE_DONE) &&
266       (sqlite3_exec
267        (plugin->dbh,
268         "CREATE TABLE ns091records (" 
269         " zone_key BLOB NOT NULL DEFAULT ''," 
270         " zone_delegation BLOB NOT NULL DEFAULT ''," 
271         " zone_hash BLOB NOT NULL DEFAULT ''," 
272         " record_count INT NOT NULL DEFAULT 0,"
273         " record_data BLOB NOT NULL DEFAULT '',"
274         " block_expiration_time INT8 NOT NULL DEFAULT 0," 
275         " signature BLOB NOT NULL DEFAULT '',"
276         " record_name TEXT NOT NULL DEFAULT ''," 
277         " record_name_hash BLOB NOT NULL DEFAULT ''," 
278         " rvalue INT8 NOT NULL DEFAULT ''"
279         ")", 
280         NULL, NULL, NULL) != SQLITE_OK))
281   {
282     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec");
283     sqlite3_finalize (stmt);
284     return GNUNET_SYSERR;
285   }
286   sqlite3_finalize (stmt);
287
288   create_indices (plugin->dbh);
289
290 #define ALL "zone_key, record_name, record_count, record_data, block_expiration_time, signature"
291   if ((sq_prepare
292        (plugin->dbh,
293         "INSERT INTO ns091records (" ALL ", zone_delegation, zone_hash, record_name_hash, rvalue) VALUES "
294         "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
295         &plugin->put_records) != SQLITE_OK) ||
296       (sq_prepare
297        (plugin->dbh,
298         "DELETE FROM ns091records WHERE zone_hash=? AND record_name_hash=?",
299         &plugin->remove_records) != SQLITE_OK) ||
300       (sq_prepare
301        (plugin->dbh,
302         "SELECT " ALL
303         " FROM ns091records WHERE zone_hash=? AND record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?",
304         &plugin->iterate_records) != SQLITE_OK) ||
305       (sq_prepare
306        (plugin->dbh,
307         "SELECT " ALL
308         " FROM ns091records WHERE zone_hash=? ORDER BY rvalue  LIMIT 1 OFFSET ?",
309         &plugin->iterate_by_zone) != SQLITE_OK) ||
310       (sq_prepare
311        (plugin->dbh,
312         "SELECT " ALL 
313         " FROM ns091records WHERE record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?",
314         &plugin->iterate_by_name) != SQLITE_OK) ||
315       (sq_prepare
316         (plugin->dbh,
317         "SELECT " ALL
318         " FROM ns091records ORDER BY rvalue LIMIT 1 OFFSET ?",
319         &plugin->iterate_all) != SQLITE_OK) ||
320       (sq_prepare
321         (plugin->dbh,
322         "SELECT " ALL
323         " FROM ns091records WHERE zone_hash=? AND zone_delegation=?",
324         &plugin->zone_to_name) != SQLITE_OK) ||
325       (sq_prepare
326        (plugin->dbh,
327         "DELETE FROM ns091records WHERE zone_hash=?",
328         &plugin->delete_zone) != SQLITE_OK) )
329   {
330     LOG_SQLITE (plugin,GNUNET_ERROR_TYPE_ERROR, "precompiling");
331     return GNUNET_SYSERR;
332   }
333 #undef ALL
334   return GNUNET_OK;
335 }
336
337
338 /**
339  * Shutdown database connection and associate data
340  * structures.
341  * @param plugin the plugin context (state for this module)
342  */
343 static void
344 database_shutdown (struct Plugin *plugin)
345 {
346   int result;
347   sqlite3_stmt *stmt;
348
349   if (NULL != plugin->put_records)
350     sqlite3_finalize (plugin->put_records);
351   if (NULL != plugin->remove_records)
352     sqlite3_finalize (plugin->remove_records);
353   if (NULL != plugin->iterate_records)
354     sqlite3_finalize (plugin->iterate_records);
355   if (NULL != plugin->iterate_by_zone)
356     sqlite3_finalize (plugin->iterate_by_zone);
357   if (NULL != plugin->iterate_by_name)
358     sqlite3_finalize (plugin->iterate_by_name);
359   if (NULL != plugin->iterate_all)
360     sqlite3_finalize (plugin->iterate_all);
361   if (NULL != plugin->zone_to_name)
362     sqlite3_finalize (plugin->zone_to_name);
363   if (NULL != plugin->delete_zone)
364     sqlite3_finalize (plugin->delete_zone);
365   result = sqlite3_close (plugin->dbh);
366   if (result == SQLITE_BUSY)
367   {
368     LOG (GNUNET_ERROR_TYPE_WARNING,
369          _("Tried to close sqlite without finalizing all prepared statements.\n"));
370     stmt = sqlite3_next_stmt (plugin->dbh, NULL);
371     while (stmt != NULL)
372     {
373       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
374                        "Closing statement %p\n", stmt);
375       result = sqlite3_finalize (stmt);
376       if (result != SQLITE_OK)
377         GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite",
378                          "Failed to close statement %p: %d\n", stmt, result);
379       stmt = sqlite3_next_stmt (plugin->dbh, NULL);
380     }
381     result = sqlite3_close (plugin->dbh);
382   }
383   if (SQLITE_OK != result)
384     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
385
386   GNUNET_free_non_null (plugin->fn);
387 }
388
389
390 /**
391  * Removes any existing record in the given zone with the same name.
392  *
393  * @param cls closure (internal context for the plugin)
394  * @param zone hash of the public key of the zone
395  * @param name name to remove (at most 255 characters long)
396  * @return GNUNET_OK on success
397  */
398 static int 
399 namestore_sqlite_remove_records (void *cls, 
400                                  const GNUNET_HashCode *zone,
401                                  const char *name)
402 {
403   struct Plugin *plugin = cls;
404   GNUNET_HashCode nh;
405   size_t name_len;
406   int n;
407
408   name_len = strlen (name);
409   GNUNET_CRYPTO_hash (name, name_len, &nh);
410
411   if ((SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 1, zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) ||
412       (SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 2, &nh, sizeof (GNUNET_HashCode), SQLITE_STATIC)))
413   {
414     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
415                 "sqlite3_bind_XXXX");
416     if (SQLITE_OK != sqlite3_reset (plugin->remove_records))
417       LOG_SQLITE (plugin,
418                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
419                   "sqlite3_reset");
420     return GNUNET_SYSERR;
421   }
422   n = sqlite3_step (plugin->remove_records);
423   if (SQLITE_OK != sqlite3_reset (plugin->remove_records))
424     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
425                 "sqlite3_reset");
426   switch (n)
427   {
428   case SQLITE_DONE:
429     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Record removed\n");
430     return GNUNET_OK;
431   case SQLITE_BUSY:
432     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
433                 "sqlite3_step");
434     return GNUNET_NO;
435   default:
436     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
437                 "sqlite3_step");
438     return GNUNET_SYSERR;
439   }
440 }
441
442
443 /**
444  * Store a record in the datastore.  Removes any existing record in the
445  * same zone with the same name.
446  *
447  * @param cls closure (internal context for the plugin)
448  * @param zone_key public key of the zone
449  * @param expire when does the corresponding block in the DHT expire (until
450  *               when should we never do a DHT lookup for the same name again)?
451  * @param name name that is being mapped (at most 255 characters long)
452  * @param rd_count number of entries in 'rd' array
453  * @param rd array of records with data to store
454  * @param signature signature of the record block, NULL if signature is unavailable (i.e. 
455  *        because the user queried for a particular record type only)
456  * @return GNUNET_OK on success, else GNUNET_SYSERR
457  */
458 static int 
459 namestore_sqlite_put_records (void *cls, 
460                               const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
461                               struct GNUNET_TIME_Absolute expire,
462                               const char *name,
463                               unsigned int rd_count,
464                               const struct GNUNET_NAMESTORE_RecordData *rd,
465                               const struct GNUNET_CRYPTO_RsaSignature *signature)
466 {
467   struct Plugin *plugin = cls;
468   int n;
469   GNUNET_HashCode zone;
470   GNUNET_HashCode zone_delegation;
471   GNUNET_HashCode nh;
472   size_t name_len;
473   uint64_t rvalue;
474   size_t data_size;
475   unsigned int i;
476
477   GNUNET_CRYPTO_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
478   (void) namestore_sqlite_remove_records (plugin, &zone, name);
479   name_len = strlen (name);
480   GNUNET_CRYPTO_hash (name, name_len, &nh);
481   memset (&zone_delegation, 0, sizeof (zone_delegation));
482   for (i=0;i<rd_count;i++)
483     if (rd[i].record_type == GNUNET_NAMESTORE_TYPE_PKEY)
484     {
485       GNUNET_assert (sizeof (GNUNET_HashCode) == rd[i].data_size);
486       memcpy (&zone_delegation,
487               rd[i].data,
488               sizeof (GNUNET_HashCode));
489       break;
490     }
491   rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
492   data_size = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
493   if (data_size > 64 * 65536)
494   {
495     GNUNET_break (0);
496     return GNUNET_SYSERR;
497   }
498   {
499     char data[data_size];
500
501     if (data_size != GNUNET_NAMESTORE_records_serialize (rd_count, rd,
502                                                          data_size, data))
503     {
504       GNUNET_break (0);
505       return GNUNET_SYSERR;
506     }
507     if ((SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 1, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), SQLITE_STATIC)) ||
508         (SQLITE_OK != sqlite3_bind_text (plugin->put_records, 2, name, -1, SQLITE_STATIC)) ||
509         (SQLITE_OK != sqlite3_bind_int (plugin->put_records, 3, rd_count)) ||
510         (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 4, data, data_size, SQLITE_STATIC)) ||
511         (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 5, expire.abs_value)) ||
512         (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 6, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature), SQLITE_STATIC)) ||
513         (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 7, &zone_delegation, sizeof (GNUNET_HashCode), SQLITE_STATIC)) ||
514         (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 8, &zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) ||
515         (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 9, &nh, sizeof (GNUNET_HashCode), SQLITE_STATIC)) ||
516         (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 10, rvalue)) )
517     {
518       LOG_SQLITE (plugin, 
519                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
520                   "sqlite3_bind_XXXX");
521       if (SQLITE_OK != sqlite3_reset (plugin->put_records))
522         LOG_SQLITE (plugin, 
523                     GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
524                     "sqlite3_reset");
525       return GNUNET_SYSERR;
526       
527     }
528     n = sqlite3_step (plugin->put_records);
529     if (SQLITE_OK != sqlite3_reset (plugin->put_records))
530       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
531                   "sqlite3_reset");
532   }
533   switch (n)
534   {
535   case SQLITE_DONE:
536     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Record stored\n");
537     return GNUNET_OK;
538   case SQLITE_BUSY:
539     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
540                 "sqlite3_step");
541     return GNUNET_NO;
542   default:
543     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
544                 "sqlite3_step");
545     return GNUNET_SYSERR;  
546   }
547 }
548   
549   
550 /**
551  * Iterate over the results for a particular key and zone in the
552  * datastore.  Will return at most one result to the iterator.
553  *
554  * @param cls closure (internal context for the plugin)
555  * @param zone hash of public key of the zone, NULL to iterate over all zones
556  * @param name name as string, NULL to iterate over all records of the zone
557  * @param offset offset in the list of all matching records
558  * @param iter function to call with the result
559  * @param iter_cls closure for iter
560  * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error
561  */
562 static int 
563 namestore_sqlite_iterate_records (void *cls, 
564                                   const GNUNET_HashCode *zone,
565                                   const char *name,
566                                   uint64_t offset,
567                                   GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
568 {
569   struct Plugin *plugin = cls;
570   sqlite3_stmt *stmt;
571   GNUNET_HashCode name_hase;
572   unsigned int boff;
573   int ret;
574   int sret;
575
576   if (NULL == zone)
577     if (NULL == name)
578       stmt = plugin->iterate_all;
579     else
580     {
581       GNUNET_CRYPTO_hash (name, strlen(name), &name_hase);
582       stmt = plugin->iterate_by_name;
583     }
584   else
585     if (NULL == name)
586       stmt = plugin->iterate_by_zone;
587     else
588     {
589       GNUNET_CRYPTO_hash (name, strlen(name), &name_hase);
590       stmt = plugin->iterate_records;
591     }
592
593   boff = 0;
594   if ( (NULL != zone) &&
595        (SQLITE_OK != sqlite3_bind_blob (stmt, ++boff, 
596                                         zone, sizeof (GNUNET_HashCode), 
597                                         SQLITE_STATIC)) )
598   {
599     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
600                 "sqlite3_bind_XXXX");
601     if (SQLITE_OK != sqlite3_reset (stmt))
602       LOG_SQLITE (plugin,
603                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
604                   "sqlite3_reset");
605     return GNUNET_SYSERR;
606   }      
607   if ( (NULL != name) &&
608        (SQLITE_OK != sqlite3_bind_blob (stmt, ++boff, 
609                                         &name_hase, sizeof (GNUNET_HashCode),
610                                         SQLITE_STATIC)) )
611   {
612     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ITERATE NAME HASH: `%s'", GNUNET_h2s_full(&name_hase));
613     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
614                 "sqlite3_bind_XXXX");
615     if (SQLITE_OK != sqlite3_reset (stmt))
616       LOG_SQLITE (plugin,
617                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
618                   "sqlite3_reset");
619     return GNUNET_SYSERR;
620   }      
621
622   if (SQLITE_OK != sqlite3_bind_int64 (stmt, ++boff, 
623                                        offset)) 
624   {
625     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
626                 "sqlite3_bind_XXXX");
627     if (SQLITE_OK != sqlite3_reset (stmt))
628       LOG_SQLITE (plugin,
629                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
630                   "sqlite3_reset");
631     return GNUNET_SYSERR;
632   }
633   ret = GNUNET_NO;
634   if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
635   {
636     unsigned int record_count;
637     size_t data_size;
638     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
639     const struct GNUNET_CRYPTO_RsaSignature *sig;
640     struct GNUNET_TIME_Absolute expiration;
641     const char *data;
642     const char *name;
643       
644     ret = GNUNET_YES;
645     zone_key =  sqlite3_column_blob (stmt, 0);
646     name = (const char*) sqlite3_column_text (stmt, 1);
647     record_count = sqlite3_column_int (stmt, 2);
648     data_size = sqlite3_column_bytes (stmt, 3);
649     data = sqlite3_column_blob (stmt, 3);
650     expiration.abs_value = (uint64_t) sqlite3_column_int64 (stmt, 4);
651     sig = sqlite3_column_blob (stmt, 5);
652
653     if ( (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) != sqlite3_column_bytes (stmt, 0)) ||
654          (sizeof (struct GNUNET_CRYPTO_RsaSignature) != sqlite3_column_bytes (stmt, 5)) )
655     {
656       GNUNET_break (0);
657       ret = GNUNET_SYSERR;
658     }
659     else
660     {
661       struct GNUNET_NAMESTORE_RecordData rd[record_count];
662
663       if (GNUNET_OK !=
664           GNUNET_NAMESTORE_records_deserialize (data_size, data,
665                                                 record_count, rd))
666       {
667         GNUNET_break (0);
668         ret = GNUNET_SYSERR;
669         record_count = 0;
670       }
671       else
672       {
673         iter (iter_cls, zone_key, expiration, name, 
674               record_count, rd, sig);
675       }
676     }
677   }
678   else
679   {
680     if (SQLITE_DONE != sret)
681       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step");
682     iter (iter_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL);
683   }
684   if (SQLITE_OK != sqlite3_reset (stmt))
685     LOG_SQLITE (plugin,
686                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
687                 "sqlite3_reset");
688   return ret;
689 }
690
691
692 /**
693  * Look for an existing PKEY delegation record for a given public key.
694  * Returns at most one result to the iterator.
695  *
696  * @param cls closure (internal context for the plugin)
697  * @param zone hash of public key of the zone to look up in, never NULL
698  * @param value_zone hash of the public key of the target zone (value), never NULL
699  * @param iter function to call with the result
700  * @param iter_cls closure for iter
701  * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error
702  */
703 static int
704 namestore_sqlite_zone_to_name (void *cls, 
705                                const GNUNET_HashCode *zone,
706                                const GNUNET_HashCode *value_zone,
707                                GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
708 {
709   struct Plugin *plugin = cls;
710   sqlite3_stmt *stmt;
711   int ret;
712   int sret;
713
714   stmt = plugin->zone_to_name;
715   if ( (SQLITE_OK != sqlite3_bind_blob (stmt, 1, 
716                                         zone, sizeof (GNUNET_HashCode), 
717                                         SQLITE_STATIC)) ||
718        (SQLITE_OK != sqlite3_bind_blob (stmt, 2, 
719                                         value_zone, sizeof (GNUNET_HashCode), 
720                                         SQLITE_STATIC)) )
721   {
722     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
723                 "sqlite3_bind_XXXX");
724     if (SQLITE_OK != sqlite3_reset (stmt))
725       LOG_SQLITE (plugin,
726                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
727                   "sqlite3_reset");
728     return GNUNET_SYSERR;
729   }      
730   ret = GNUNET_NO;
731   if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
732   {
733     unsigned int record_count;
734     size_t data_size;
735     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
736     const struct GNUNET_CRYPTO_RsaSignature *sig;
737     struct GNUNET_TIME_Absolute expiration;
738     const char *data;
739     const char *name;
740       
741     ret = GNUNET_YES;
742     zone_key =  sqlite3_column_blob (stmt, 0);
743     name = (const char*) sqlite3_column_text (stmt, 1);
744     record_count = sqlite3_column_int (stmt, 2);
745     data_size = sqlite3_column_bytes (stmt, 3);
746     data = sqlite3_column_blob (stmt, 3);
747     expiration.abs_value = (uint64_t) sqlite3_column_int64 (stmt, 4);
748     sig = sqlite3_column_blob (stmt, 5);
749
750     if ( (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) != sqlite3_column_bytes (stmt, 0)) ||
751          (sizeof (struct GNUNET_CRYPTO_RsaSignature) != sqlite3_column_bytes (stmt, 5)) )
752     {
753       GNUNET_break (0);
754       ret = GNUNET_SYSERR;
755     }
756     else
757     {
758       struct GNUNET_NAMESTORE_RecordData rd[record_count];
759
760       if (GNUNET_OK !=
761           GNUNET_NAMESTORE_records_deserialize (data_size, data,
762                                                 record_count, rd))
763       {
764         GNUNET_break (0);
765         ret = GNUNET_SYSERR;
766         record_count = 0;
767       }
768       else
769       {
770         iter (iter_cls, zone_key, expiration, name, 
771               record_count, rd, sig);
772       }
773     }
774   }
775   else
776   {
777     if (SQLITE_DONE != sret)
778       LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step");
779     iter (iter_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL);
780   }
781   if (SQLITE_OK != sqlite3_reset (stmt))
782     LOG_SQLITE (plugin,
783                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
784                 "sqlite3_reset");
785   return ret;
786 }
787
788
789 /**
790  * Delete an entire zone (all records).  Not used in normal operation.
791  *
792  * @param cls closure (internal context for the plugin)
793  * @param zone zone to delete
794  */
795 static void 
796 namestore_sqlite_delete_zone (void *cls,
797                               const GNUNET_HashCode *zone)
798 {
799   struct Plugin *plugin = cls;
800   sqlite3_stmt *stmt = plugin->delete_zone;
801   int n;
802
803   if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, zone, sizeof (GNUNET_HashCode), SQLITE_STATIC))
804   {
805     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
806                 "sqlite3_bind_XXXX");
807     if (SQLITE_OK != sqlite3_reset (stmt))
808       LOG_SQLITE (plugin,
809                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
810                   "sqlite3_reset");
811     return;
812   }
813   n = sqlite3_step (stmt);
814   if (SQLITE_OK != sqlite3_reset (stmt))
815     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
816                 "sqlite3_reset");
817   switch (n)
818   {
819   case SQLITE_DONE:
820     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Values deleted\n");
821     break;
822   case SQLITE_BUSY:
823     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
824                 "sqlite3_step");
825     break;
826   default:
827     LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
828                 "sqlite3_step");
829     break;
830   }
831 }
832
833
834 /**
835  * Entry point for the plugin.
836  *
837  * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
838  * @return NULL on error, othrewise the plugin context
839  */
840 void *
841 libgnunet_plugin_namestore_sqlite_init (void *cls)
842 {
843   static struct Plugin plugin;
844   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
845   struct GNUNET_NAMESTORE_PluginFunctions *api;
846
847   if (NULL != plugin.cfg)
848     return NULL;                /* can only initialize once! */
849   memset (&plugin, 0, sizeof (struct Plugin));
850   plugin.cfg = cfg;  
851   if (GNUNET_OK != database_setup (&plugin))
852   {
853     database_shutdown (&plugin);
854     return NULL;
855   }
856   api = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_PluginFunctions));
857   api->cls = &plugin;
858   api->put_records = &namestore_sqlite_put_records;
859   api->remove_records = &namestore_sqlite_remove_records;
860   api->iterate_records = &namestore_sqlite_iterate_records;
861   api->zone_to_name = &namestore_sqlite_zone_to_name;
862   api->delete_zone = &namestore_sqlite_delete_zone;
863   LOG (GNUNET_ERROR_TYPE_INFO, 
864        _("Sqlite database running\n"));
865   return api;
866 }
867
868
869 /**
870  * Exit point from the plugin.
871  *
872  * @param cls the plugin context (as returned by "init")
873  * @return always NULL
874  */
875 void *
876 libgnunet_plugin_namestore_sqlite_done (void *cls)
877 {
878   struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
879   struct Plugin *plugin = api->cls;
880
881   LOG (GNUNET_ERROR_TYPE_DEBUG, 
882        "sqlite plugin is done\n");
883   database_shutdown (plugin);
884   plugin->cfg = NULL;
885   GNUNET_free (api);
886   LOG (GNUNET_ERROR_TYPE_DEBUG, 
887        "sqlite plugin is finished\n");
888   return NULL;
889 }
890
891 /* end of plugin_namestore_sqlite.c */