aboutsummaryrefslogtreecommitdiff
path: root/src/pq
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-01-17 02:26:21 +0100
committerChristian Grothoff <christian@grothoff.org>2020-01-17 02:26:21 +0100
commit4353432b97bdc03ce31f11dfd1ff3e30cf0106af (patch)
treef6d92c64b324e30065051259b73e23e12f4c533f /src/pq
parent1126181ab98fd7e9e6cca0786939020b161fcb94 (diff)
downloadgnunet-4353432b97bdc03ce31f11dfd1ff3e30cf0106af.tar.gz
gnunet-4353432b97bdc03ce31f11dfd1ff3e30cf0106af.zip
DB load API change
Diffstat (limited to 'src/pq')
-rw-r--r--src/pq/pq.h5
-rw-r--r--src/pq/pq_connect.c92
2 files changed, 87 insertions, 10 deletions
diff --git a/src/pq/pq.h b/src/pq/pq.h
index b30f4f0d4..91a890bcb 100644
--- a/src/pq/pq.h
+++ b/src/pq/pq.h
@@ -52,6 +52,11 @@ struct GNUNET_PQ_Context
52 * Configuration to use to connect to the DB. 52 * Configuration to use to connect to the DB.
53 */ 53 */
54 char *config_str; 54 char *config_str;
55
56 /**
57 * Path to load SQL files from.
58 */
59 char *load_path;
55}; 60};
56 61
57#endif 62#endif
diff --git a/src/pq/pq_connect.c b/src/pq/pq_connect.c
index 7d9a524b3..5ade12a3e 100644
--- a/src/pq/pq_connect.c
+++ b/src/pq/pq_connect.c
@@ -64,19 +64,22 @@ pq_notice_processor_cb (void *arg,
64 64
65 65
66/** 66/**
67 * Create a connection to the Postgres database using @a config_str 67 * Create a connection to the Postgres database using @a config_str for the
68 * for the configuration. Initialize logging via GNUnet's log 68 * configuration. Initialize logging via GNUnet's log routines and disable
69 * routines and disable Postgres's logger. Also ensures that the 69 * Postgres's logger. Also ensures that the statements in @a load_path and @a
70 * statements in @a es are executed whenever we (re)connect to the 70 * es are executed whenever we (re)connect to the database, and that the
71 * database, and that the prepared statements in @a ps are "ready". 71 * prepared statements in @a ps are "ready". If statements in @es fail that
72 * If statements in @es fail that were created with 72 * were created with #GNUNET_PQ_make_execute(), then the entire operation
73 * #GNUNET_PQ_make_execute(), then the entire operation fails. 73 * fails.
74 * 74 *
75 * The caller MUST ensure that @a es and @a ps remain allocated and 75 * In @a load_path, a list of "$XXXX.sql" files is expected where $XXXX
76 * initialized in memory until #GNUNET_PQ_disconnect() is called, 76 * must be a sequence of contiguous integer values starting at 0000.
77 * as they may be needed repeatedly and no copy will be made. 77 * These files are then loaded in sequence using "psql $config_str" before
78 * running statements from @e es. The directory is inspected again on
79 * reconnect.
78 * 80 *
79 * @param config_str configuration to use 81 * @param config_str configuration to use
82 * @param load_path path to directory with SQL transactions to run, can be NULL
80 * @param es #GNUNET_PQ_PREPARED_STATEMENT_END-terminated 83 * @param es #GNUNET_PQ_PREPARED_STATEMENT_END-terminated
81 * array of statements to execute upon EACH connection, can be NULL 84 * array of statements to execute upon EACH connection, can be NULL
82 * @param ps array of prepared statements to prepare, can be NULL 85 * @param ps array of prepared statements to prepare, can be NULL
@@ -84,6 +87,7 @@ pq_notice_processor_cb (void *arg,
84 */ 87 */
85struct GNUNET_PQ_Context * 88struct GNUNET_PQ_Context *
86GNUNET_PQ_connect (const char *config_str, 89GNUNET_PQ_connect (const char *config_str,
90 const char *load_path,
87 const struct GNUNET_PQ_ExecuteStatement *es, 91 const struct GNUNET_PQ_ExecuteStatement *es,
88 const struct GNUNET_PQ_PreparedStatement *ps) 92 const struct GNUNET_PQ_PreparedStatement *ps)
89{ 93{
@@ -100,6 +104,8 @@ GNUNET_PQ_connect (const char *config_str,
100 104
101 db = GNUNET_new (struct GNUNET_PQ_Context); 105 db = GNUNET_new (struct GNUNET_PQ_Context);
102 db->config_str = GNUNET_strdup (config_str); 106 db->config_str = GNUNET_strdup (config_str);
107 if (NULL != load_path)
108 db->load_path = GNUNET_strdup (load_path);
103 if (0 != elen) 109 if (0 != elen)
104 { 110 {
105 db->es = GNUNET_new_array (elen + 1, 111 db->es = GNUNET_new_array (elen + 1,
@@ -175,6 +181,62 @@ GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db)
175 PQsetNoticeProcessor (db->conn, 181 PQsetNoticeProcessor (db->conn,
176 &pq_notice_processor_cb, 182 &pq_notice_processor_cb,
177 db); 183 db);
184 if (NULL != db->load_path)
185 {
186 size_t slen = strlen (db->load_path) + 10;
187
188 for (unsigned int i = 0; i<10000; i++)
189 {
190 char buf[slen];
191 struct GNUNET_OS_Process *psql;
192 enum GNUNET_OS_ProcessStatusType type;
193 unsigned long code;
194
195 GNUNET_snprintf (buf,
196 sizeof (buf),
197 "%s/%u.sql",
198 db->load_path,
199 i);
200 if (GNUNET_YES !=
201 GNUNET_DISK_file_test (buf))
202 break; /* We are done */
203 psql = GNUNET_OS_start_process (GNUNET_NO,
204 GNUNET_OS_INHERIT_STD_ERR,
205 NULL,
206 NULL,
207 NULL,
208 "psql",
209 db->config_str,
210 "-f",
211 buf,
212 "-q",
213 NULL);
214 if (NULL == psql)
215 {
216 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
217 "exec",
218 "psql");
219 PQfinish (db->conn);
220 db->conn = NULL;
221 return;
222 }
223 GNUNET_assert (GNUNET_OK ==
224 GNUNET_OS_process_wait_status (psql,
225 &type,
226 &code));
227 GNUNET_OS_process_destroy (psql);
228 if ( (GNUNET_OS_PROCESS_EXITED != type) ||
229 (0 != code) )
230 {
231 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
232 "psql",
233 buf);
234 PQfinish (db->conn);
235 db->conn = NULL;
236 return;
237 }
238 }
239 }
178 if ( (NULL != db->es) && 240 if ( (NULL != db->es) &&
179 (GNUNET_OK != 241 (GNUNET_OK !=
180 GNUNET_PQ_exec_statements (db, 242 GNUNET_PQ_exec_statements (db,
@@ -221,6 +283,7 @@ GNUNET_PQ_connect_with_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
221{ 283{
222 struct GNUNET_PQ_Context *db; 284 struct GNUNET_PQ_Context *db;
223 char *conninfo; 285 char *conninfo;
286 char *load_path;
224 287
225 if (GNUNET_OK != 288 if (GNUNET_OK !=
226 GNUNET_CONFIGURATION_get_value_string (cfg, 289 GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -228,9 +291,17 @@ GNUNET_PQ_connect_with_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
228 "CONFIG", 291 "CONFIG",
229 &conninfo)) 292 &conninfo))
230 conninfo = NULL; 293 conninfo = NULL;
294 if (GNUNET_OK !=
295 GNUNET_CONFIGURATION_get_value_string (cfg,
296 section,
297 "SQL_PATH",
298 &load_path))
299 load_path = NULL;
231 db = GNUNET_PQ_connect (conninfo == NULL ? "" : conninfo, 300 db = GNUNET_PQ_connect (conninfo == NULL ? "" : conninfo,
301 load_path,
232 es, 302 es,
233 ps); 303 ps);
304 GNUNET_free_non_null (load_path);
234 GNUNET_free_non_null (conninfo); 305 GNUNET_free_non_null (conninfo);
235 return db; 306 return db;
236} 307}
@@ -247,6 +318,7 @@ GNUNET_PQ_disconnect (struct GNUNET_PQ_Context *db)
247{ 318{
248 GNUNET_free_non_null (db->es); 319 GNUNET_free_non_null (db->es);
249 GNUNET_free_non_null (db->ps); 320 GNUNET_free_non_null (db->ps);
321 GNUNET_free_non_null (db->load_path);
250 PQfinish (db->conn); 322 PQfinish (db->conn);
251 GNUNET_free (db); 323 GNUNET_free (db);
252} 324}