GNUnet  0.11.x
pq_connect.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2017, 2019 GNUnet e.V.
4 
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
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
25 #include "platform.h"
26 #include "pq.h"
27 
28 
37 static void
39  const PGresult *res)
40 {
41  /* do nothing, intentionally */
42  (void) arg;
43  (void) res;
44 }
45 
46 
54 static void
56  const char *message)
57 {
58  (void) arg;
60  "pq",
61  "%s",
62  message);
63 }
64 
65 
88 struct GNUNET_PQ_Context *
90  const char *load_path,
91  const struct GNUNET_PQ_ExecuteStatement *es,
92  const struct GNUNET_PQ_PreparedStatement *ps)
93 {
94  struct GNUNET_PQ_Context *db;
95  unsigned int elen = 0;
96  unsigned int plen = 0;
97 
98  if (NULL != es)
99  while (NULL != es[elen].sql)
100  elen++;
101  if (NULL != ps)
102  while (NULL != ps[plen].name)
103  plen++;
104 
105  db = GNUNET_new (struct GNUNET_PQ_Context);
106  db->config_str = GNUNET_strdup (config_str);
107  if (NULL != load_path)
108  db->load_path = GNUNET_strdup (load_path);
109  if (0 != elen)
110  {
111  db->es = GNUNET_new_array (elen + 1,
113  memcpy (db->es,
114  es,
115  elen * sizeof (struct GNUNET_PQ_ExecuteStatement));
116  }
117  if (0 != plen)
118  {
119  db->ps = GNUNET_new_array (plen + 1,
121  memcpy (db->ps,
122  ps,
123  plen * sizeof (struct GNUNET_PQ_PreparedStatement));
124  }
125  GNUNET_PQ_reconnect (db);
126  if (NULL == db->conn)
127  {
129  GNUNET_free (db->config_str);
130  GNUNET_free (db);
131  return NULL;
132  }
133  return db;
134 }
135 
136 
142 void
144 {
145  if (CONNECTION_BAD != PQstatus (db->conn))
146  return;
147  GNUNET_PQ_reconnect (db);
148 }
149 
150 
156 void
158 {
159  if (NULL != db->conn)
160  PQfinish (db->conn);
161  db->conn = PQconnectdb (db->config_str);
162  if ((NULL == db->conn) ||
163  (CONNECTION_OK != PQstatus (db->conn)))
164  {
166  "pq",
167  "Database connection to '%s' failed: %s\n",
168  db->config_str,
169  (NULL != db->conn) ?
170  PQerrorMessage (db->conn)
171  : "PQconnectdb returned NULL");
172  if (NULL != db->conn)
173  {
174  PQfinish (db->conn);
175  db->conn = NULL;
176  }
177  return;
178  }
179  PQsetNoticeReceiver (db->conn,
181  db);
182  PQsetNoticeProcessor (db->conn,
184  db);
185  if (NULL != db->load_path)
186  {
187  size_t slen = strlen (db->load_path) + 10;
188 
189  for (unsigned int i = 0; i<10000; i++)
190  {
191  char buf[slen];
192  struct GNUNET_OS_Process *psql;
194  unsigned long code;
195 
196  GNUNET_snprintf (buf,
197  sizeof (buf),
198  "%s%04u.sql",
199  db->load_path,
200  i);
201  if (GNUNET_YES !=
202  GNUNET_DISK_file_test (buf))
203  break; /* We are done */
206  NULL,
207  NULL,
208  NULL,
209  "psql",
210  "psql",
211  db->config_str,
212  "-f",
213  buf,
214  "-q",
215  NULL);
216  if (NULL == psql)
217  {
219  "exec",
220  "psql");
221  PQfinish (db->conn);
222  db->conn = NULL;
223  return;
224  }
227  &type,
228  &code));
230  if ( (GNUNET_OS_PROCESS_EXITED != type) ||
231  (0 != code) )
232  {
234  "Could not run PSQL on file %s: %d",
235  buf,
236  (int) code);
237  PQfinish (db->conn);
238  db->conn = NULL;
239  return;
240  }
241  }
242  }
243  if ( (NULL != db->es) &&
244  (GNUNET_OK !=
246  db->es)) )
247  {
248  PQfinish (db->conn);
249  db->conn = NULL;
250  return;
251  }
252  if ( (NULL != db->ps) &&
253  (GNUNET_OK !=
255  db->ps)) )
256  {
257  PQfinish (db->conn);
258  db->conn = NULL;
259  return;
260  }
261 }
262 
263 
281 struct GNUNET_PQ_Context *
283  const char *section,
284  const struct GNUNET_PQ_ExecuteStatement *es,
285  const struct GNUNET_PQ_PreparedStatement *ps)
286 {
287  struct GNUNET_PQ_Context *db;
288  char *conninfo;
289  char *load_path;
290 
291  if (GNUNET_OK !=
293  section,
294  "CONFIG",
295  &conninfo))
296  conninfo = NULL;
297  if (GNUNET_OK !=
299  section,
300  "SQL_PATH",
301  &load_path))
302  load_path = NULL;
303  db = GNUNET_PQ_connect (conninfo == NULL ? "" : conninfo,
304  load_path,
305  es,
306  ps);
307  GNUNET_free_non_null (load_path);
308  GNUNET_free_non_null (conninfo);
309  return db;
310 }
311 
312 
319 void
321 {
322  GNUNET_free_non_null (db->es);
323  GNUNET_free_non_null (db->ps);
326  PQfinish (db->conn);
327  GNUNET_free (db);
328 }
329 
330 
331 /* end of pq/pq_connect.c */
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:544
void GNUNET_PQ_disconnect(struct GNUNET_PQ_Context *db)
Disconnect from the database, destroying the prepared statements and releasing other associated resou...
Definition: pq_connect.c:320
void GNUNET_PQ_reconnect(struct GNUNET_PQ_Context *db)
Reinitialize the database db.
Definition: pq_connect.c:157
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
struct GNUNET_PQ_PreparedStatement * ps
Prepared statements.
Definition: pq.h:49
void GNUNET_OS_process_destroy(struct GNUNET_OS_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition: os_priority.c:287
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
char * load_path
Path to load SQL files from.
Definition: pq.h:59
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Information needed to run a list of SQL statements using GNUNET_PQ_exec_statements().
struct GNUNET_OS_Process * GNUNET_OS_start_process(int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename,...)
Start a process.
Definition: os_priority.c:687
Information needed to prepare a list of SQL statements using GNUNET_PQ_prepare_statements().
struct GNUNET_PQ_ExecuteStatement * es
Statements to execute upon connection.
Definition: pq.h:44
int GNUNET_PQ_prepare_statements(struct GNUNET_PQ_Context *db, const struct GNUNET_PQ_PreparedStatement *ps)
Request creation of prepared statements ps from Postgres.
Definition: pq_prepare.c:62
#define GNUNET_NO
Definition: gnunet_common.h:86
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:83
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static char * section
Name of the section.
Definition: gnunet-config.c:33
PGconn * conn
Actual connection.
Definition: pq.h:39
struct GNUNET_PQ_Context * GNUNET_PQ_connect(const char *config_str, const char *load_path, const struct GNUNET_PQ_ExecuteStatement *es, const struct GNUNET_PQ_PreparedStatement *ps)
Create a connection to the Postgres database using config_str for the configuration.
Definition: pq_connect.c:89
shared internal data structures of libgnunetpq
int GNUNET_PQ_exec_statements(struct GNUNET_PQ_Context *db, const struct GNUNET_PQ_ExecuteStatement *es)
Request execution of an array of statements es from Postgres.
Definition: pq_exec.c:76
char * config_str
Configuration to use to connect to the DB.
Definition: pq.h:54
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
No standard streams should be inherited.
Definition: gnunet_os_lib.h:73
GNUNET_OS_ProcessStatusType
Process status types.
int GNUNET_OS_process_wait_status(struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Retrieve the status of a process, waiting on it if dead.
Definition: os_priority.c:981
static char buf[2048]
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
The process exited with a return code.
static int res
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
struct GNUNET_PQ_Context * GNUNET_PQ_connect_with_cfg(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const struct GNUNET_PQ_ExecuteStatement *es, const struct GNUNET_PQ_PreparedStatement *ps)
Connect to a postgres database using the configuration option "CONFIG" in section.
Definition: pq_connect.c:282
static struct GNUNET_FS_DirectoryBuilder * db
Definition: gnunet-search.c:41
void GNUNET_PQ_reconnect_if_down(struct GNUNET_PQ_Context *db)
Reinitialize the database db if the connection is down.
Definition: pq_connect.c:143
configuration data
Definition: configuration.c:84
const char * name
#define GNUNET_log(kind,...)
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
static void pq_notice_receiver_cb(void *arg, const PGresult *res)
Function called by libpq whenever it wants to log something.
Definition: pq_connect.c:38
#define GNUNET_YES
Definition: gnunet_common.h:85
static void pq_notice_processor_cb(void *arg, const char *message)
Function called by libpq whenever it wants to log something.
Definition: pq_connect.c:55
#define GNUNET_log_from(kind, comp,...)
Handle to Postgres database.
Definition: pq.h:34
#define GNUNET_free(ptr)
Wrapper around free.