aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_sqlite.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/plugin_namestore_sqlite.c')
-rw-r--r--src/namestore/plugin_namestore_sqlite.c285
1 files changed, 95 insertions, 190 deletions
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c
index f62be1e18..6960e5d12 100644
--- a/src/namestore/plugin_namestore_sqlite.c
+++ b/src/namestore/plugin_namestore_sqlite.c
@@ -2,20 +2,18 @@
2 * This file is part of GNUnet 2 * This file is part of GNUnet
3 * Copyright (C) 2009-2017 GNUnet e.V. 3 * Copyright (C) 2009-2017 GNUnet e.V.
4 * 4 *
5 * GNUnet is free software; you can redistribute it and/or modify 5 * GNUnet is free software: you can redistribute it and/or modify it
6 * it under the terms of the GNU General Public License as published 6 * under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation; either version 3, or (at your 7 * by the Free Software Foundation, either version 3 of the License,
8 * option) any later version. 8 * or (at your option) any later version.
9 * 9 *
10 * GNUnet is distributed in the hope that it will be useful, but 10 * GNUnet is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details. 13 * Affero General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU Affero General Public License
16 * along with GNUnet; see the file COPYING. If not, write to the 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */ 17 */
20 18
21/** 19/**
@@ -106,72 +104,6 @@ struct Plugin
106 104
107 105
108/** 106/**
109 * @brief Prepare a SQL statement
110 *
111 * @param dbh handle to the database
112 * @param zSql SQL statement, UTF-8 encoded
113 * @param ppStmt set to the prepared statement
114 * @return 0 on success
115 */
116static int
117sq_prepare (sqlite3 *dbh,
118 const char *zSql,
119 sqlite3_stmt **ppStmt)
120{
121 char *dummy;
122 int result;
123
124 result =
125 sqlite3_prepare_v2 (dbh,
126 zSql,
127 strlen (zSql),
128 ppStmt,
129 (const char **) &dummy);
130 LOG (GNUNET_ERROR_TYPE_DEBUG,
131 "Prepared `%s' / %p: %d\n",
132 zSql,
133 *ppStmt,
134 result);
135 return result;
136}
137
138
139/**
140 * Create our database indices.
141 *
142 * @param dbh handle to the database
143 */
144static void
145create_indices (sqlite3 * dbh)
146{
147 /* create indices */
148 if ( (SQLITE_OK !=
149 sqlite3_exec (dbh,
150 "CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
151 "ON ns098records (zone_private_key,pkey)",
152 NULL, NULL, NULL)) ||
153 (SQLITE_OK !=
154 sqlite3_exec (dbh,
155 "CREATE INDEX IF NOT EXISTS ir_pkey_iter "
156 "ON ns098records (zone_private_key,uid)",
157 NULL, NULL, NULL)) )
158 LOG (GNUNET_ERROR_TYPE_ERROR,
159 "Failed to create indices: %s\n",
160 sqlite3_errmsg (dbh));
161}
162
163
164#if 0
165#define CHECK(a) GNUNET_break(a)
166#define ENULL NULL
167#else
168#define ENULL &e
169#define ENULL_DEFINED 1
170#define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
171#endif
172
173
174/**
175 * Initialize the database connections and associated 107 * Initialize the database connections and associated
176 * data structures (create tables and indices 108 * data structures (create tables and indices
177 * as needed as well). 109 * as needed as well).
@@ -182,17 +114,66 @@ create_indices (sqlite3 * dbh)
182static int 114static int
183database_setup (struct Plugin *plugin) 115database_setup (struct Plugin *plugin)
184{ 116{
185 sqlite3_stmt *stmt; 117 char *sqlite_filename;
186 char *afsdir; 118 struct GNUNET_SQ_ExecuteStatement es[] = {
187#if ENULL_DEFINED 119 GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
188 char *e; 120 GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
189#endif 121 GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
122 GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
123 GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
124 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=EXCLUSIVE"),
125 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
126 GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
127 " uid INTEGER PRIMARY KEY,"
128 " zone_private_key BLOB NOT NULL,"
129 " pkey BLOB,"
130 " rvalue INT8 NOT NULL,"
131 " record_count INT NOT NULL,"
132 " record_data BLOB NOT NULL,"
133 " label TEXT NOT NULL"
134 ")"),
135 GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
136 "ON ns098records (zone_private_key,pkey)"),
137 GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
138 "ON ns098records (zone_private_key,uid)"),
139 GNUNET_SQ_EXECUTE_STATEMENT_END
140 };
141 struct GNUNET_SQ_PrepareStatement ps[] = {
142 GNUNET_SQ_make_prepare ("INSERT INTO ns098records "
143 "(zone_private_key,pkey,rvalue,record_count,record_data,label)"
144 " VALUES (?, ?, ?, ?, ?, ?)",
145 &plugin->store_records),
146 GNUNET_SQ_make_prepare ("DELETE FROM ns098records "
147 "WHERE zone_private_key=? AND label=?",
148 &plugin->delete_records),
149 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
150 " FROM ns098records"
151 " WHERE zone_private_key=? AND pkey=?",
152 &plugin->zone_to_name),
153 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
154 " FROM ns098records"
155 " WHERE zone_private_key=? AND _rowid_ >= ?"
156 " ORDER BY _rowid_ ASC"
157 " LIMIT ?",
158 &plugin->iterate_zone),
159 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label,zone_private_key"
160 " FROM ns098records"
161 " WHERE _rowid_ >= ?"
162 " ORDER BY _rowid_ ASC"
163 " LIMIT ?",
164 &plugin->iterate_all_zones),
165 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label,zone_private_key"
166 " FROM ns098records"
167 " WHERE zone_private_key=? AND label=?",
168 &plugin->lookup_label),
169 GNUNET_SQ_PREPARE_END
170 };
190 171
191 if (GNUNET_OK != 172 if (GNUNET_OK !=
192 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, 173 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
193 "namestore-sqlite", 174 "namestore-sqlite",
194 "FILENAME", 175 "FILENAME",
195 &afsdir)) 176 &sqlite_filename))
196 { 177 {
197 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 178 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
198 "namestore-sqlite", 179 "namestore-sqlite",
@@ -200,132 +181,51 @@ database_setup (struct Plugin *plugin)
200 return GNUNET_SYSERR; 181 return GNUNET_SYSERR;
201 } 182 }
202 if (GNUNET_OK != 183 if (GNUNET_OK !=
203 GNUNET_DISK_file_test (afsdir)) 184 GNUNET_DISK_file_test (sqlite_filename))
204 { 185 {
205 if (GNUNET_OK != 186 if (GNUNET_OK !=
206 GNUNET_DISK_directory_create_for_file (afsdir)) 187 GNUNET_DISK_directory_create_for_file (sqlite_filename))
207 { 188 {
208 GNUNET_break (0); 189 GNUNET_break (0);
209 GNUNET_free (afsdir); 190 GNUNET_free (sqlite_filename);
210 return GNUNET_SYSERR; 191 return GNUNET_SYSERR;
211 } 192 }
212 } 193 }
213 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ 194 /* sqlite_filename should be UTF-8-encoded. If it isn't, it's a bug */
214 plugin->fn = afsdir; 195 plugin->fn = sqlite_filename;
215 196
216 /* Open database and precompile statements */ 197 /* Open database and precompile statements */
217 if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) 198 if (SQLITE_OK !=
199 sqlite3_open (plugin->fn,
200 &plugin->dbh))
218 { 201 {
219 LOG (GNUNET_ERROR_TYPE_ERROR, 202 LOG (GNUNET_ERROR_TYPE_ERROR,
220 _("Unable to initialize SQLite: %s.\n"), 203 _("Unable to initialize SQLite: %s.\n"),
221 sqlite3_errmsg (plugin->dbh)); 204 sqlite3_errmsg (plugin->dbh));
222 return GNUNET_SYSERR; 205 return GNUNET_SYSERR;
223 } 206 }
224 CHECK (SQLITE_OK == 207 GNUNET_break (SQLITE_OK ==
225 sqlite3_exec (plugin->dbh, 208 sqlite3_busy_timeout (plugin->dbh,
226 "PRAGMA temp_store=MEMORY", NULL, NULL, 209 BUSY_TIMEOUT_MS));
227 ENULL)); 210 if (GNUNET_OK !=
228 CHECK (SQLITE_OK == 211 GNUNET_SQ_exec_statements (plugin->dbh,
229 sqlite3_exec (plugin->dbh, 212 es))
230 "PRAGMA synchronous=NORMAL", NULL, NULL,
231 ENULL));
232 CHECK (SQLITE_OK ==
233 sqlite3_exec (plugin->dbh,
234 "PRAGMA legacy_file_format=OFF", NULL, NULL,
235 ENULL));
236 CHECK (SQLITE_OK ==
237 sqlite3_exec (plugin->dbh,
238 "PRAGMA auto_vacuum=INCREMENTAL", NULL,
239 NULL, ENULL));
240 CHECK (SQLITE_OK ==
241 sqlite3_exec (plugin->dbh,
242 "PRAGMA encoding=\"UTF-8\"", NULL,
243 NULL, ENULL));
244 CHECK (SQLITE_OK ==
245 sqlite3_exec (plugin->dbh,
246 "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
247 ENULL));
248 CHECK (SQLITE_OK ==
249 sqlite3_exec (plugin->dbh,
250 "PRAGMA page_size=4092", NULL, NULL,
251 ENULL));
252
253 CHECK (SQLITE_OK ==
254 sqlite3_busy_timeout (plugin->dbh,
255 BUSY_TIMEOUT_MS));
256
257
258 /* Create table */
259 CHECK (SQLITE_OK ==
260 sq_prepare (plugin->dbh,
261 "SELECT 1 FROM sqlite_master WHERE tbl_name = 'ns098records'",
262 &stmt));
263 if ( (sqlite3_step (stmt) == SQLITE_DONE) &&
264 (SQLITE_OK !=
265 sqlite3_exec (plugin->dbh,
266 "CREATE TABLE ns098records ("
267 " uid INTEGER PRIMARY KEY,"
268 " zone_private_key BLOB NOT NULL,"
269 " pkey BLOB,"
270 " rvalue INT8 NOT NULL,"
271 " record_count INT NOT NULL,"
272 " record_data BLOB NOT NULL,"
273 " label TEXT NOT NULL"
274 ")",
275 NULL, NULL, NULL)) )
276 { 213 {
277 LOG_SQLITE (plugin, 214 GNUNET_break (0);
278 GNUNET_ERROR_TYPE_ERROR, 215 LOG (GNUNET_ERROR_TYPE_ERROR,
279 "sqlite3_exec"); 216 _("Failed to setup database at `%s'\n"),
280 sqlite3_finalize (stmt); 217 plugin->fn);
281 return GNUNET_SYSERR; 218 return GNUNET_SYSERR;
282 } 219 }
283 sqlite3_finalize (stmt); 220
284 221 if (GNUNET_OK !=
285 create_indices (plugin->dbh); 222 GNUNET_SQ_prepare (plugin->dbh,
286 223 ps))
287 if ( (SQLITE_OK !=
288 sq_prepare (plugin->dbh,
289 "INSERT INTO ns098records (zone_private_key, pkey, rvalue, record_count, record_data, label)"
290 " VALUES (?, ?, ?, ?, ?, ?)",
291 &plugin->store_records)) ||
292 (SQLITE_OK !=
293 sq_prepare (plugin->dbh,
294 "DELETE FROM ns098records WHERE zone_private_key=? AND label=?",
295 &plugin->delete_records)) ||
296 (SQLITE_OK !=
297 sq_prepare (plugin->dbh,
298 "SELECT uid,record_count,record_data,label"
299 " FROM ns098records"
300 " WHERE zone_private_key=? AND pkey=?",
301 &plugin->zone_to_name)) ||
302 (SQLITE_OK !=
303 sq_prepare (plugin->dbh,
304 "SELECT uid,record_count,record_data,label"
305 " FROM ns098records"
306 " WHERE zone_private_key=? AND _rowid_ >= ?"
307 " ORDER BY _rowid_ ASC"
308 " LIMIT ?",
309 &plugin->iterate_zone)) ||
310 (SQLITE_OK !=
311 sq_prepare (plugin->dbh,
312 "SELECT uid,record_count,record_data,label,zone_private_key"
313 " FROM ns098records"
314 " WHERE _rowid_ >= ?"
315 " ORDER BY _rowid_ ASC"
316 " LIMIT ?",
317 &plugin->iterate_all_zones)) ||
318 (SQLITE_OK !=
319 sq_prepare (plugin->dbh,
320 "SELECT uid,record_count,record_data,label,zone_private_key"
321 " FROM ns098records"
322 " WHERE zone_private_key=? AND label=?",
323 &plugin->lookup_label))
324 )
325 { 224 {
326 LOG_SQLITE (plugin, 225 GNUNET_break (0);
327 GNUNET_ERROR_TYPE_ERROR, 226 LOG (GNUNET_ERROR_TYPE_ERROR,
328 "precompiling"); 227 _("Failed to setup database at `%s'\n"),
228 plugin->fn);
329 return GNUNET_SYSERR; 229 return GNUNET_SYSERR;
330 } 230 }
331 return GNUNET_OK; 231 return GNUNET_OK;
@@ -411,7 +311,7 @@ namestore_sqlite_store_records (void *cls,
411 int n; 311 int n;
412 struct GNUNET_CRYPTO_EcdsaPublicKey pkey; 312 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
413 uint64_t rvalue; 313 uint64_t rvalue;
414 size_t data_size; 314 ssize_t data_size;
415 315
416 memset (&pkey, 316 memset (&pkey,
417 0, 317 0,
@@ -430,6 +330,11 @@ namestore_sqlite_store_records (void *cls,
430 UINT64_MAX); 330 UINT64_MAX);
431 data_size = GNUNET_GNSRECORD_records_get_size (rd_count, 331 data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
432 rd); 332 rd);
333 if (data_size < 0)
334 {
335 GNUNET_break (0);
336 return GNUNET_SYSERR;
337 }
433 if (data_size > 64 * 65536) 338 if (data_size > 64 * 65536)
434 { 339 {
435 GNUNET_break (0); 340 GNUNET_break (0);
@@ -450,7 +355,7 @@ namestore_sqlite_store_records (void *cls,
450 data_size, 355 data_size,
451 data); 356 data);
452 if ( (ret < 0) || 357 if ( (ret < 0) ||
453 (data_size != (size_t) ret) ) 358 (data_size != ret) )
454 { 359 {
455 GNUNET_break (0); 360 GNUNET_break (0);
456 return GNUNET_SYSERR; 361 return GNUNET_SYSERR;