aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_sqlite.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-05-09 17:33:04 +0200
committerChristian Grothoff <christian@grothoff.org>2018-05-09 17:33:04 +0200
commit8bb475af99260f1d107dbc8908268ae93960aa83 (patch)
tree1a7a1fc03424df841a6f977b137482439b09bc9f /src/namestore/plugin_namestore_sqlite.c
parent1f80a11e90ee982bffaae4685e281f75ee1c225d (diff)
downloadgnunet-8bb475af99260f1d107dbc8908268ae93960aa83.tar.gz
gnunet-8bb475af99260f1d107dbc8908268ae93960aa83.zip
implement new functions in libgnunetsq, clean up sqlite namestore plugin, implement flow control in namestore API and tests
Diffstat (limited to 'src/namestore/plugin_namestore_sqlite.c')
-rw-r--r--src/namestore/plugin_namestore_sqlite.c260
1 files changed, 81 insertions, 179 deletions
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c
index f62be1e18..34e548613 100644
--- a/src/namestore/plugin_namestore_sqlite.c
+++ b/src/namestore/plugin_namestore_sqlite.c
@@ -106,72 +106,6 @@ struct Plugin
106 106
107 107
108/** 108/**
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 109 * Initialize the database connections and associated
176 * data structures (create tables and indices 110 * data structures (create tables and indices
177 * as needed as well). 111 * as needed as well).
@@ -182,17 +116,66 @@ create_indices (sqlite3 * dbh)
182static int 116static int
183database_setup (struct Plugin *plugin) 117database_setup (struct Plugin *plugin)
184{ 118{
185 sqlite3_stmt *stmt; 119 char *sqlite_filename;
186 char *afsdir; 120 struct GNUNET_SQ_ExecuteStatement es[] = {
187#if ENULL_DEFINED 121 GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
188 char *e; 122 GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
189#endif 123 GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
124 GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
125 GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
126 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=EXCLUSIVE"),
127 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
128 GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
129 " uid INTEGER PRIMARY KEY,"
130 " zone_private_key BLOB NOT NULL,"
131 " pkey BLOB,"
132 " rvalue INT8 NOT NULL,"
133 " record_count INT NOT NULL,"
134 " record_data BLOB NOT NULL,"
135 " label TEXT NOT NULL"
136 ")"),
137 GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
138 "ON ns098records (zone_private_key,pkey)"),
139 GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
140 "ON ns098records (zone_private_key,uid)"),
141 GNUNET_SQ_EXECUTE_STATEMENT_END
142 };
143 struct GNUNET_SQ_PrepareStatement ps[] = {
144 GNUNET_SQ_make_prepare ("INSERT INTO ns098records "
145 "(zone_private_key,pkey,rvalue,record_count,record_data,label)"
146 " VALUES (?, ?, ?, ?, ?, ?)",
147 &plugin->store_records),
148 GNUNET_SQ_make_prepare ("DELETE FROM ns098records "
149 "WHERE zone_private_key=? AND label=?",
150 &plugin->delete_records),
151 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
152 " FROM ns098records"
153 " WHERE zone_private_key=? AND pkey=?",
154 &plugin->zone_to_name),
155 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
156 " FROM ns098records"
157 " WHERE zone_private_key=? AND _rowid_ >= ?"
158 " ORDER BY _rowid_ ASC"
159 " LIMIT ?",
160 &plugin->iterate_zone),
161 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label,zone_private_key"
162 " FROM ns098records"
163 " WHERE _rowid_ >= ?"
164 " ORDER BY _rowid_ ASC"
165 " LIMIT ?",
166 &plugin->iterate_all_zones),
167 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label,zone_private_key"
168 " FROM ns098records"
169 " WHERE zone_private_key=? AND label=?",
170 &plugin->lookup_label),
171 GNUNET_SQ_PREPARE_END
172 };
190 173
191 if (GNUNET_OK != 174 if (GNUNET_OK !=
192 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, 175 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
193 "namestore-sqlite", 176 "namestore-sqlite",
194 "FILENAME", 177 "FILENAME",
195 &afsdir)) 178 &sqlite_filename))
196 { 179 {
197 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 180 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
198 "namestore-sqlite", 181 "namestore-sqlite",
@@ -200,132 +183,51 @@ database_setup (struct Plugin *plugin)
200 return GNUNET_SYSERR; 183 return GNUNET_SYSERR;
201 } 184 }
202 if (GNUNET_OK != 185 if (GNUNET_OK !=
203 GNUNET_DISK_file_test (afsdir)) 186 GNUNET_DISK_file_test (sqlite_filename))
204 { 187 {
205 if (GNUNET_OK != 188 if (GNUNET_OK !=
206 GNUNET_DISK_directory_create_for_file (afsdir)) 189 GNUNET_DISK_directory_create_for_file (sqlite_filename))
207 { 190 {
208 GNUNET_break (0); 191 GNUNET_break (0);
209 GNUNET_free (afsdir); 192 GNUNET_free (sqlite_filename);
210 return GNUNET_SYSERR; 193 return GNUNET_SYSERR;
211 } 194 }
212 } 195 }
213 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ 196 /* sqlite_filename should be UTF-8-encoded. If it isn't, it's a bug */
214 plugin->fn = afsdir; 197 plugin->fn = sqlite_filename;
215 198
216 /* Open database and precompile statements */ 199 /* Open database and precompile statements */
217 if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) 200 if (SQLITE_OK !=
201 sqlite3_open (plugin->fn,
202 &plugin->dbh))
218 { 203 {
219 LOG (GNUNET_ERROR_TYPE_ERROR, 204 LOG (GNUNET_ERROR_TYPE_ERROR,
220 _("Unable to initialize SQLite: %s.\n"), 205 _("Unable to initialize SQLite: %s.\n"),
221 sqlite3_errmsg (plugin->dbh)); 206 sqlite3_errmsg (plugin->dbh));
222 return GNUNET_SYSERR; 207 return GNUNET_SYSERR;
223 } 208 }
224 CHECK (SQLITE_OK == 209 GNUNET_break (SQLITE_OK ==
225 sqlite3_exec (plugin->dbh, 210 sqlite3_busy_timeout (plugin->dbh,
226 "PRAGMA temp_store=MEMORY", NULL, NULL, 211 BUSY_TIMEOUT_MS));
227 ENULL)); 212 if (GNUNET_OK !=
228 CHECK (SQLITE_OK == 213 GNUNET_SQ_exec_statements (plugin->dbh,
229 sqlite3_exec (plugin->dbh, 214 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 { 215 {
277 LOG_SQLITE (plugin, 216 GNUNET_break (0);
278 GNUNET_ERROR_TYPE_ERROR, 217 LOG (GNUNET_ERROR_TYPE_ERROR,
279 "sqlite3_exec"); 218 _("Failed to setup database at `%s'\n"),
280 sqlite3_finalize (stmt); 219 plugin->fn);
281 return GNUNET_SYSERR; 220 return GNUNET_SYSERR;
282 } 221 }
283 sqlite3_finalize (stmt); 222
284 223 if (GNUNET_OK !=
285 create_indices (plugin->dbh); 224 GNUNET_SQ_prepare (plugin->dbh,
286 225 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 { 226 {
326 LOG_SQLITE (plugin, 227 GNUNET_break (0);
327 GNUNET_ERROR_TYPE_ERROR, 228 LOG (GNUNET_ERROR_TYPE_ERROR,
328 "precompiling"); 229 _("Failed to setup database at `%s'\n"),
230 plugin->fn);
329 return GNUNET_SYSERR; 231 return GNUNET_SYSERR;
330 } 232 }
331 return GNUNET_OK; 233 return GNUNET_OK;