aboutsummaryrefslogtreecommitdiff
path: root/src/pq/pq_connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pq/pq_connect.c')
-rw-r--r--src/pq/pq_connect.c158
1 files changed, 102 insertions, 56 deletions
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
81struct GNUNET_PQ_Context *
82GNUNET_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
464struct GNUNET_PQ_Context *
465GNUNET_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);