diff options
Diffstat (limited to 'src/pq')
-rw-r--r-- | src/pq/pq.h | 5 | ||||
-rw-r--r-- | src/pq/pq_connect.c | 158 | ||||
-rw-r--r-- | src/pq/pq_exec.c | 2 |
3 files changed, 108 insertions, 57 deletions
diff --git a/src/pq/pq.h b/src/pq/pq.h index d10931d99..354d85a9f 100644 --- a/src/pq/pq.h +++ b/src/pq/pq.h | |||
@@ -73,6 +73,11 @@ struct GNUNET_PQ_Context | |||
73 | * File descriptor wrapper for @e event_task. | 73 | * File descriptor wrapper for @e event_task. |
74 | */ | 74 | */ |
75 | struct GNUNET_NETWORK_Handle *rfd; | 75 | struct GNUNET_NETWORK_Handle *rfd; |
76 | |||
77 | /** | ||
78 | * Flags controlling the connection. | ||
79 | */ | ||
80 | enum GNUNET_PQ_Options flags; | ||
76 | }; | 81 | }; |
77 | 82 | ||
78 | 83 | ||
diff --git a/src/pq/pq_connect.c b/src/pq/pq_connect.c index a2dce3fb0..a63d5f14e 100644 --- a/src/pq/pq_connect.c +++ b/src/pq/pq_connect.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | Copyright (C) 2017, 2019, 2020 GNUnet e.V. | 3 | Copyright (C) 2017, 2019, 2020, 2021 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | under the terms of the GNU Affero General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
@@ -70,6 +70,21 @@ GNUNET_PQ_connect (const char *config_str, | |||
70 | const struct GNUNET_PQ_ExecuteStatement *es, | 70 | const struct GNUNET_PQ_ExecuteStatement *es, |
71 | const struct GNUNET_PQ_PreparedStatement *ps) | 71 | const struct GNUNET_PQ_PreparedStatement *ps) |
72 | { | 72 | { |
73 | return GNUNET_PQ_connect2 (config_str, | ||
74 | load_path, | ||
75 | es, | ||
76 | ps, | ||
77 | GNUNET_PQ_FLAG_NONE); | ||
78 | } | ||
79 | |||
80 | |||
81 | struct GNUNET_PQ_Context * | ||
82 | GNUNET_PQ_connect2 (const char *config_str, | ||
83 | const char *load_path, | ||
84 | const struct GNUNET_PQ_ExecuteStatement *es, | ||
85 | const struct GNUNET_PQ_PreparedStatement *ps, | ||
86 | enum GNUNET_PQ_Options flags) | ||
87 | { | ||
73 | struct GNUNET_PQ_Context *db; | 88 | struct GNUNET_PQ_Context *db; |
74 | unsigned int elen = 0; | 89 | unsigned int elen = 0; |
75 | unsigned int plen = 0; | 90 | unsigned int plen = 0; |
@@ -82,6 +97,7 @@ GNUNET_PQ_connect (const char *config_str, | |||
82 | plen++; | 97 | plen++; |
83 | 98 | ||
84 | db = GNUNET_new (struct GNUNET_PQ_Context); | 99 | db = GNUNET_new (struct GNUNET_PQ_Context); |
100 | db->flags = flags; | ||
85 | db->config_str = GNUNET_strdup (config_str); | 101 | db->config_str = GNUNET_strdup (config_str); |
86 | if (NULL != load_path) | 102 | if (NULL != load_path) |
87 | db->load_path = GNUNET_strdup (load_path); | 103 | db->load_path = GNUNET_strdup (load_path); |
@@ -200,68 +216,72 @@ GNUNET_PQ_run_sql (struct GNUNET_PQ_Context *db, | |||
200 | load_path); | 216 | load_path); |
201 | for (unsigned int i = 1; i<10000; i++) | 217 | for (unsigned int i = 1; i<10000; i++) |
202 | { | 218 | { |
219 | char patch_name[slen]; | ||
220 | char buf[slen]; | ||
203 | enum GNUNET_DB_QueryStatus qs; | 221 | enum GNUNET_DB_QueryStatus qs; |
204 | { | 222 | |
205 | char buf[slen]; | 223 | /* First, check patch actually exists */ |
206 | 224 | GNUNET_snprintf (buf, | |
207 | /* First, check patch actually exists */ | 225 | sizeof (buf), |
208 | GNUNET_snprintf (buf, | 226 | "%s%04u.sql", |
209 | sizeof (buf), | 227 | load_path, |
210 | "%s%04u.sql", | 228 | i); |
211 | load_path, | 229 | if (GNUNET_YES != |
212 | i); | 230 | GNUNET_DISK_file_test (buf)) |
213 | if (GNUNET_YES != | 231 | return GNUNET_OK; /* We are done */ |
214 | GNUNET_DISK_file_test (buf)) | ||
215 | return GNUNET_OK; /* We are done */ | ||
216 | } | ||
217 | 232 | ||
218 | /* Second, check with DB versioning schema if this patch was already applied, | 233 | /* Second, check with DB versioning schema if this patch was already applied, |
219 | if so, skip it. */ | 234 | if so, skip it. */ |
235 | GNUNET_snprintf (patch_name, | ||
236 | sizeof (patch_name), | ||
237 | "%s%04u", | ||
238 | load_path_suffix, | ||
239 | i); | ||
220 | { | 240 | { |
221 | char patch_name[slen]; | 241 | char *applied_by; |
222 | 242 | struct GNUNET_PQ_QueryParam params[] = { | |
223 | GNUNET_snprintf (patch_name, | 243 | GNUNET_PQ_query_param_string (patch_name), |
224 | sizeof (patch_name), | 244 | GNUNET_PQ_query_param_end |
225 | "%s%04u", | 245 | }; |
226 | load_path_suffix, | 246 | struct GNUNET_PQ_ResultSpec rs[] = { |
227 | i); | 247 | GNUNET_PQ_result_spec_string ("applied_by", |
248 | &applied_by), | ||
249 | GNUNET_PQ_result_spec_end | ||
250 | }; | ||
251 | |||
252 | qs = GNUNET_PQ_eval_prepared_singleton_select (db, | ||
253 | "gnunet_pq_check_patch", | ||
254 | params, | ||
255 | rs); | ||
256 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) | ||
257 | { | ||
258 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
259 | "Database version %s already applied by %s, skipping\n", | ||
260 | patch_name, | ||
261 | applied_by); | ||
262 | GNUNET_PQ_cleanup_result (rs); | ||
263 | } | ||
264 | if (GNUNET_DB_STATUS_HARD_ERROR == qs) | ||
228 | { | 265 | { |
229 | char *applied_by; | 266 | GNUNET_break (0); |
230 | struct GNUNET_PQ_QueryParam params[] = { | 267 | return GNUNET_SYSERR; |
231 | GNUNET_PQ_query_param_string (patch_name), | ||
232 | GNUNET_PQ_query_param_end | ||
233 | }; | ||
234 | struct GNUNET_PQ_ResultSpec rs[] = { | ||
235 | GNUNET_PQ_result_spec_string ("applied_by", | ||
236 | &applied_by), | ||
237 | GNUNET_PQ_result_spec_end | ||
238 | }; | ||
239 | |||
240 | qs = GNUNET_PQ_eval_prepared_singleton_select (db, | ||
241 | "gnunet_pq_check_patch", | ||
242 | params, | ||
243 | rs); | ||
244 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) | ||
245 | { | ||
246 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
247 | "Database version %s already applied by %s, skipping\n", | ||
248 | patch_name, | ||
249 | applied_by); | ||
250 | GNUNET_PQ_cleanup_result (rs); | ||
251 | } | ||
252 | if (GNUNET_DB_STATUS_HARD_ERROR == qs) | ||
253 | { | ||
254 | GNUNET_break (0); | ||
255 | return GNUNET_SYSERR; | ||
256 | } | ||
257 | } | 268 | } |
258 | } | 269 | } |
259 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) | 270 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) |
260 | continue; /* patch already applied, skip it */ | 271 | continue; /* patch already applied, skip it */ |
261 | 272 | ||
262 | /* patch not yet applied, run it! */ | 273 | if (0 != (GNUNET_PQ_FLAG_CHECK_CURRENT & db->flags)) |
263 | { | 274 | { |
264 | int ret; | 275 | /* We are only checking, found unapplied patch, bad! */ |
276 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
277 | "Database outdated, patch %s missing. Aborting!\n", | ||
278 | patch_name); | ||
279 | return GNUNET_SYSERR; | ||
280 | } | ||
281 | else | ||
282 | { | ||
283 | /* patch not yet applied, run it! */ | ||
284 | enum GNUNET_GenericReturnValue ret; | ||
265 | 285 | ||
266 | ret = apply_patch (db, | 286 | ret = apply_patch (db, |
267 | load_path, | 287 | load_path, |
@@ -334,9 +354,17 @@ GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db) | |||
334 | NULL); | 354 | NULL); |
335 | if (PGRES_COMMAND_OK != PQresultStatus (res)) | 355 | if (PGRES_COMMAND_OK != PQresultStatus (res)) |
336 | { | 356 | { |
337 | int ret; | 357 | enum GNUNET_GenericReturnValue ret; |
338 | 358 | ||
339 | PQclear (res); | 359 | PQclear (res); |
360 | if (0 != (db->flags & GNUNET_PQ_FLAG_DROP)) | ||
361 | { | ||
362 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
363 | "Failed to prepare statement to check patch level. Likely versioning schema does not exist yet. Not attempting drop!\n"); | ||
364 | PQfinish (db->conn); | ||
365 | db->conn = NULL; | ||
366 | return; | ||
367 | } | ||
340 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 368 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
341 | "Failed to prepare statement to check patch level. Likely versioning schema does not exist yet, loading patch level 0000!\n"); | 369 | "Failed to prepare statement to check patch level. Likely versioning schema does not exist yet, loading patch level 0000!\n"); |
342 | ret = apply_patch (db, | 370 | ret = apply_patch (db, |
@@ -424,6 +452,23 @@ GNUNET_PQ_connect_with_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
424 | const struct GNUNET_PQ_ExecuteStatement *es, | 452 | const struct GNUNET_PQ_ExecuteStatement *es, |
425 | const struct GNUNET_PQ_PreparedStatement *ps) | 453 | const struct GNUNET_PQ_PreparedStatement *ps) |
426 | { | 454 | { |
455 | return GNUNET_PQ_connect_with_cfg2 (cfg, | ||
456 | section, | ||
457 | load_path_suffix, | ||
458 | es, | ||
459 | ps, | ||
460 | GNUNET_PQ_FLAG_NONE); | ||
461 | } | ||
462 | |||
463 | |||
464 | struct GNUNET_PQ_Context * | ||
465 | GNUNET_PQ_connect_with_cfg2 (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
466 | const char *section, | ||
467 | const char *load_path_suffix, | ||
468 | const struct GNUNET_PQ_ExecuteStatement *es, | ||
469 | const struct GNUNET_PQ_PreparedStatement *ps, | ||
470 | enum GNUNET_PQ_Options flags) | ||
471 | { | ||
427 | struct GNUNET_PQ_Context *db; | 472 | struct GNUNET_PQ_Context *db; |
428 | char *conninfo; | 473 | char *conninfo; |
429 | char *load_path; | 474 | char *load_path; |
@@ -447,10 +492,11 @@ GNUNET_PQ_connect_with_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
447 | "%s%s", | 492 | "%s%s", |
448 | sp, | 493 | sp, |
449 | load_path_suffix); | 494 | load_path_suffix); |
450 | db = GNUNET_PQ_connect (conninfo == NULL ? "" : conninfo, | 495 | db = GNUNET_PQ_connect2 (conninfo == NULL ? "" : conninfo, |
451 | load_path, | 496 | load_path, |
452 | es, | 497 | es, |
453 | ps); | 498 | ps, |
499 | flags); | ||
454 | GNUNET_free (load_path); | 500 | GNUNET_free (load_path); |
455 | GNUNET_free (sp); | 501 | GNUNET_free (sp); |
456 | GNUNET_free (conninfo); | 502 | GNUNET_free (conninfo); |
diff --git a/src/pq/pq_exec.c b/src/pq/pq_exec.c index fd4feae53..464fff4b4 100644 --- a/src/pq/pq_exec.c +++ b/src/pq/pq_exec.c | |||
@@ -72,7 +72,7 @@ GNUNET_PQ_make_try_execute (const char *sql) | |||
72 | * @return #GNUNET_OK on success (modulo statements where errors can be ignored) | 72 | * @return #GNUNET_OK on success (modulo statements where errors can be ignored) |
73 | * #GNUNET_SYSERR on error | 73 | * #GNUNET_SYSERR on error |
74 | */ | 74 | */ |
75 | int | 75 | enum GNUNET_GenericReturnValue |
76 | GNUNET_PQ_exec_statements (struct GNUNET_PQ_Context *db, | 76 | GNUNET_PQ_exec_statements (struct GNUNET_PQ_Context *db, |
77 | const struct GNUNET_PQ_ExecuteStatement *es) | 77 | const struct GNUNET_PQ_ExecuteStatement *es) |
78 | { | 78 | { |