GNUnet 0.28.1-dev.4-7-gcbd8837da
 
Loading...
Searching...
No Matches
pq_connect.c File Reference

functions to connect to libpq (PostGres) More...

#include "platform.h"
#include "pq.h"
#include <pthread.h>
Include dependency graph for pq_connect.c:

Go to the source code of this file.

Functions

static void reset_connection (struct GNUNET_PQ_Context *db)
 Close connection to db and mark it as uninitialized.
 
static enum GNUNET_GenericReturnValue prepare_check_patch (struct GNUNET_PQ_Context *db)
 Prepare the "gnunet_pq_check_patch" statement.
 
static enum GNUNET_GenericReturnValue prepare_get_oid_by_name (struct GNUNET_PQ_Context *db)
 Prepare the "gnunet_pq_get_oid_by_name" statement.
 
static enum GNUNET_GenericReturnValue check_versioning_ok (struct GNUNET_PQ_Context *db)
 Check if the "_v" versioning schema exists (and cache the result in db).
 
static enum GNUNET_GenericReturnValue check_patch_applied (struct GNUNET_PQ_Context *db, const char *load_path, unsigned int patch_number)
 Check if the patch with patch_number from the given load_path was already applied on the db.
 
static void pq_notice_receiver_cb (void *arg, const PGresult *res)
 Function called by libpq whenever it wants to log something.
 
static void pq_notice_processor_cb (void *arg, const char *message)
 Function called by libpq whenever it wants to log something.
 
static char * get_sql_file_name (const struct GNUNET_PQ_Context *db, const char *infix)
 Construct the name of the SQL file with the given filename infix in the load path of db.
 
static enum GNUNET_GenericReturnValue patch_file_exists (const struct GNUNET_PQ_Context *db, const char *load_suffix, unsigned int patch_number)
 Check if the SQL file for the patch with the given patch_number exists in the load path of db.
 
static bool find_next_patch (const struct GNUNET_PQ_Context *db, const char *load_suffix, unsigned int from, unsigned int *found)
 Find the lowest patch number of at least from for which an SQL file exists in the load path of db.
 
enum GNUNET_GenericReturnValue GNUNET_PQ_exec_sql (struct GNUNET_PQ_Context *db, const char *buf)
 Execute SQL statements from buf against db.
 
enum GNUNET_GenericReturnValue GNUNET_PQ_check_current (struct GNUNET_PQ_Context *db, const char *load_suffix)
 Check if the database is current with respect to database migrations using prefix.
 
enum GNUNET_GenericReturnValue GNUNET_PQ_run_sql (struct GNUNET_PQ_Context *db, const char *load_suffix)
 Within the db context, run all the SQL files in the load path where the name starts with the load_suffix and ends with consecutive numbers from "[0000-9999].sql".
 
void GNUNET_PQ_reconnect_if_down (struct GNUNET_PQ_Context *db)
 Reinitialize the database db if the connection is down.
 
enum GNUNET_GenericReturnValue GNUNET_PQ_get_oid_by_name (struct GNUNET_PQ_Context *db, const char *name, Oid *oid)
 Returns the oid for a given datatype by name.
 
static enum GNUNET_GenericReturnValue load_initial_oids (struct GNUNET_PQ_Context *db)
 Load the initial set of OIDs for the supported array-datatypes.
 
void GNUNET_PQ_reconnect_ (struct GNUNET_PQ_Context *db)
 Reinitialize the database db.
 
enum GNUNET_GenericReturnValue GNUNET_PQ_load_versioning (struct GNUNET_PQ_Context *db)
 Setup database versioning.
 
struct GNUNET_PQ_ContextGNUNET_PQ_init (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_PQ_ReconnectCallback rc, GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE *rc_cls)
 
void GNUNET_PQ_disconnect (struct GNUNET_PQ_Context *db)
 Disconnect from the database, destroying the prepared statements and releasing other associated resources.
 

Detailed Description

functions to connect to libpq (PostGres)

Author
Christian Grothoff
Özgür Kesim

Definition in file pq_connect.c.

Function Documentation

◆ reset_connection()

static void reset_connection ( struct GNUNET_PQ_Context db)
static

Close connection to db and mark it as uninitialized.

Parameters
[in,out]dbconnection to close

Definition at line 37 of file pq_connect.c.

38{
39 if (NULL == db->conn)
40 return;
41 PQfinish (db->conn);
42 db->conn = NULL;
43 db->prepared_check_patch = false;
44 db->prepared_get_oid_by_name = false;
45}
static struct GNUNET_FS_DirectoryBuilder * db

References db.

Referenced by GNUNET_PQ_reconnect_(), prepare_check_patch(), and prepare_get_oid_by_name().

Here is the caller graph for this function:

◆ prepare_check_patch()

static enum GNUNET_GenericReturnValue prepare_check_patch ( struct GNUNET_PQ_Context db)
static

Prepare the "gnunet_pq_check_patch" statement.

Parameters
[in,out]dbdatabase to prepare statement for
Returns
GNUNET_OK on success, GNUNET_SYSERR on failure

Definition at line 56 of file pq_connect.c.

57{
58 PGresult *res;
59
60 if (db->prepared_check_patch)
61 return GNUNET_OK;
62 res = PQprepare (db->conn,
63 "gnunet_pq_check_patch",
64 "SELECT"
65 " applied_by"
66 " FROM _v.patches"
67 " WHERE patch_name = $1"
68 " LIMIT 1",
69 1,
70 NULL);
71 if (PGRES_COMMAND_OK !=
72 PQresultStatus (res))
73 {
75 "Failed to run SQL logic to setup database versioning logic: %s/%s\n",
76 PQresultErrorMessage (res),
77 PQerrorMessage (db->conn));
78 PQclear (res);
80 return GNUNET_SYSERR;
81 }
82 PQclear (res);
83 db->prepared_check_patch = true;
84 return GNUNET_OK;
85}
static char * res
Currently read line or NULL on EOF.
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_SYSERR
@ GNUNET_ERROR_TYPE_ERROR
static void reset_connection(struct GNUNET_PQ_Context *db)
Close connection to db and mark it as uninitialized.
Definition pq_connect.c:37

References db, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_SYSERR, res, and reset_connection().

Referenced by check_patch_applied().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ prepare_get_oid_by_name()

static enum GNUNET_GenericReturnValue prepare_get_oid_by_name ( struct GNUNET_PQ_Context db)
static

Prepare the "gnunet_pq_get_oid_by_name" statement.

Parameters
[in,out]dbdatabase to prepare statement for
Returns
GNUNET_OK on success, GNUNET_SYSERR on failure

Definition at line 96 of file pq_connect.c.

97{
98 PGresult *res;
99
100 if (db->prepared_get_oid_by_name)
101 return GNUNET_OK;
102 res = PQprepare (db->conn,
103 "gnunet_pq_get_oid_by_name",
104 "SELECT typname, oid"
105 " FROM pg_type"
106 " WHERE oid = to_regtype($1)",
107 1,
108 NULL);
109 if (PGRES_COMMAND_OK != PQresultStatus (res))
110 {
112 "Failed to run SQL statement prepare OID lookups: %s/%s\n",
113 PQresultErrorMessage (res),
114 PQerrorMessage (db->conn));
115 PQclear (res);
117 return GNUNET_SYSERR;
118 }
119 PQclear (res);
120 db->prepared_get_oid_by_name = true;
121 return GNUNET_OK;
122}

References db, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_SYSERR, res, and reset_connection().

Referenced by GNUNET_PQ_reconnect_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_versioning_ok()

static enum GNUNET_GenericReturnValue check_versioning_ok ( struct GNUNET_PQ_Context db)
static

Check if the "_v" versioning schema exists (and cache the result in db).

Parameters
[in,out]dbconnection to check
Returns
GNUNET_OK if versioning is OK GNUNET_NO if it is not loaded GNUNET_SYSERR if we encountered an error

Definition at line 135 of file pq_connect.c.

136{
137 PGresult *res;
138 ExecStatusType est;
139
140 if (GNUNET_OK == db->versioning_ok)
141 return GNUNET_OK;
142 if (GNUNET_NO == db->versioning_ok)
143 return GNUNET_NO;
144 res = PQexec (db->conn,
145 "SELECT"
146 " schema_name"
147 " FROM information_schema.schemata"
148 " WHERE schema_name='_v';");
149 est = PQresultStatus (res);
150 if ( (PGRES_COMMAND_OK != est) &&
151 (PGRES_TUPLES_OK != est) )
152 {
154 "Failed to run statement to check versioning schema. Bad!\n");
155 PQclear (res);
156 return GNUNET_SYSERR;
157 }
158 if (0 == PQntuples (res))
159 {
160 PQclear (res);
161 db->versioning_ok = GNUNET_NO;
163 "_v schema not found\n");
164 return GNUNET_NO;
165 }
166 PQclear (res);
167 db->versioning_ok = GNUNET_OK;
168 return GNUNET_OK;
169}
@ GNUNET_NO
@ GNUNET_ERROR_TYPE_WARNING

References db, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, and res.

Referenced by check_patch_applied(), and GNUNET_PQ_load_versioning().

Here is the caller graph for this function:

◆ check_patch_applied()

static enum GNUNET_GenericReturnValue check_patch_applied ( struct GNUNET_PQ_Context db,
const char *  load_path,
unsigned int  patch_number 
)
static

Check if the patch with patch_number from the given load_path was already applied on the db.

Parameters
[in]dbdatabase to check
load_pathfile system path to database setup files
patch_numbernumber of the patch to check
Returns
GNUNET_OK if patch is applied GNUNET_NO if patch is not applied GNUNET_SYSERR on internal error (DB failure)

Definition at line 184 of file pq_connect.c.

187{
188 const char *load_path_suffix;
189 size_t slen = strlen (load_path) + 10;
190 char patch_name[slen];
191
192 if (GNUNET_SYSERR ==
194 {
195 GNUNET_break (0);
196 return GNUNET_SYSERR; /* no versioning, cannot check */
197 }
198 load_path_suffix = strrchr (load_path,
199 '/');
200 if (NULL == load_path_suffix)
201 load_path_suffix = load_path;
202 else
203 load_path_suffix++; /* skip '/' */
204 GNUNET_snprintf (patch_name,
205 sizeof (patch_name),
206 "%s%04u",
207 load_path_suffix,
208 patch_number);
209 {
210 struct GNUNET_PQ_QueryParam params[] = {
211 GNUNET_PQ_query_param_string (patch_name),
213 };
214 char *applied_by;
215 struct GNUNET_PQ_ResultSpec rs[] = {
216 GNUNET_PQ_result_spec_string ("applied_by",
217 &applied_by),
219 };
220 enum GNUNET_DB_QueryStatus qs;
221
222 if (GNUNET_OK !=
224 {
225 GNUNET_break (0);
226 return GNUNET_SYSERR;
227 }
229 "gnunet_pq_check_patch",
230 params,
231 rs);
232 switch (qs)
233 {
236 "Database version %s already applied by %s\n",
237 patch_name,
238 applied_by);
240 return GNUNET_OK;
242 return GNUNET_NO;
244 GNUNET_break (0);
245 return GNUNET_SYSERR;
247 GNUNET_break (0);
248 return GNUNET_SYSERR;
249 }
250 GNUNET_assert (0);
251 return GNUNET_SYSERR;
252 }
253}
GNUNET_DB_QueryStatus
Status code returned from functions running database commands.
@ GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
The transaction succeeded, and yielded one result.
@ GNUNET_DB_STATUS_HARD_ERROR
A hard error occurred, retrying will not help.
@ GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
The transaction succeeded, but yielded zero results.
@ GNUNET_DB_STATUS_SOFT_ERROR
A soft error occurred, retrying the transaction may succeed.
enum GNUNET_DB_QueryStatus GNUNET_PQ_eval_prepared_singleton_select(struct GNUNET_PQ_Context *db, const char *statement_name, const struct GNUNET_PQ_QueryParam *params, struct GNUNET_PQ_ResultSpec *rs)
Execute a named prepared statement that is a SELECT statement which must return a single result in co...
Definition pq_eval.c:199
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_string(const char *name, char **dst)
0-terminated string expected.
#define GNUNET_PQ_query_param_end
End of query parameter specification.
void GNUNET_PQ_cleanup_result(struct GNUNET_PQ_ResultSpec *rs)
Free all memory that was allocated in rs during GNUNET_PQ_extract_result().
Definition pq.c:142
struct GNUNET_PQ_QueryParam GNUNET_PQ_query_param_string(const char *ptr)
Generate query parameter for a string.
#define GNUNET_PQ_result_spec_end
End of result parameter specification.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
static enum GNUNET_GenericReturnValue prepare_check_patch(struct GNUNET_PQ_Context *db)
Prepare the "gnunet_pq_check_patch" statement.
Definition pq_connect.c:56
static enum GNUNET_GenericReturnValue check_versioning_ok(struct GNUNET_PQ_Context *db)
Check if the "_v" versioning schema exists (and cache the result in db).
Definition pq_connect.c:135
Description of a DB query parameter.
Description of a DB result cell.

References check_versioning_ok(), db, GNUNET_assert, GNUNET_break, GNUNET_DB_STATUS_HARD_ERROR, GNUNET_DB_STATUS_SOFT_ERROR, GNUNET_DB_STATUS_SUCCESS_NO_RESULTS, GNUNET_DB_STATUS_SUCCESS_ONE_RESULT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_PQ_cleanup_result(), GNUNET_PQ_eval_prepared_singleton_select(), GNUNET_PQ_query_param_end, GNUNET_PQ_query_param_string(), GNUNET_PQ_result_spec_end, GNUNET_PQ_result_spec_string(), GNUNET_snprintf(), GNUNET_SYSERR, and prepare_check_patch().

Referenced by GNUNET_PQ_check_current(), and GNUNET_PQ_run_sql().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pq_notice_receiver_cb()

static void pq_notice_receiver_cb ( void *  arg,
const PGresult *  res 
)
static

Function called by libpq whenever it wants to log something.

We already log whenever we care, so this function does nothing and merely exists to silence the libpq logging.

Parameters
argthe SQL connection that was used
resinformation about some libpq event

Definition at line 265 of file pq_connect.c.

267{
268 /* do nothing, intentionally */
269 (void) arg;
270 (void) res;
271}

References res.

Referenced by GNUNET_PQ_reconnect_().

Here is the caller graph for this function:

◆ pq_notice_processor_cb()

static void pq_notice_processor_cb ( void *  arg,
const char *  message 
)
static

Function called by libpq whenever it wants to log something.

We log those using the GNUnet logger.

Parameters
argthe SQL connection that was used
messageinformation about some libpq event

Definition at line 282 of file pq_connect.c.

284{
285 (void) arg;
287 "pq",
288 "%s",
289 message);
290}
#define GNUNET_log_from(kind, comp,...)
@ GNUNET_ERROR_TYPE_INFO

References GNUNET_ERROR_TYPE_INFO, and GNUNET_log_from.

Referenced by GNUNET_PQ_reconnect_().

Here is the caller graph for this function:

◆ get_sql_file_name()

static char * get_sql_file_name ( const struct GNUNET_PQ_Context db,
const char *  infix 
)
static

Construct the name of the SQL file with the given filename infix in the load path of db.

This is the one place where the mapping from a filename infix to an actual file on disk is defined; all callers must use it, or they risk probing for files that are never loaded (and vice versa).

Parameters
dbdatabase context to get the load path from
infixfilename infix (!) identifying the SQL file
Returns
name of the SQL file, to be freed by the caller

Definition at line 305 of file pq_connect.c.

307{
308 char *fn;
309
310 GNUNET_asprintf (&fn,
311 "%s%s.sql",
312 db->load_path,
313 infix);
314 return fn;
315}
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.

References db, and GNUNET_asprintf().

Referenced by GNUNET_PQ_exec_sql(), and patch_file_exists().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ patch_file_exists()

static enum GNUNET_GenericReturnValue patch_file_exists ( const struct GNUNET_PQ_Context db,
const char *  load_suffix,
unsigned int  patch_number 
)
static

Check if the SQL file for the patch with the given patch_number exists in the load path of db.

Parameters
dbdatabase context to get the load path from
load_suffixsuffix to append to the load path, usually "subsystem-"
patch_numbernumber of the patch to look for
Returns
GNUNET_YES if the file exists and is readable, GNUNET_NO if it does not exist, GNUNET_SYSERR on error

Definition at line 331 of file pq_connect.c.

334{
335 size_t slen = strlen (load_suffix) + 10;
336 char patch_name[slen];
337 char *fn;
339
340 GNUNET_snprintf (patch_name,
341 sizeof (patch_name),
342 "%s%04u",
343 load_suffix,
344 patch_number);
345 fn = get_sql_file_name (db,
346 patch_name);
348 GNUNET_free (fn);
349 return ret;
350}
static int ret
Final status code.
Definition gnunet-arm.c:93
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test_read(const char *fil)
Check that fil corresponds to a filename and the file has read permissions.
Definition disk.c:565
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_free(ptr)
Wrapper around free.
static char * get_sql_file_name(const struct GNUNET_PQ_Context *db, const char *infix)
Construct the name of the SQL file with the given filename infix in the load path of db.
Definition pq_connect.c:305

References db, get_sql_file_name(), GNUNET_DISK_file_test_read(), GNUNET_free, GNUNET_snprintf(), and ret.

Referenced by find_next_patch().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_next_patch()

static bool find_next_patch ( const struct GNUNET_PQ_Context db,
const char *  load_suffix,
unsigned int  from,
unsigned int *  found 
)
static

Find the lowest patch number of at least from for which an SQL file exists in the load path of db.

Used to tell "we ran out of patches" apart from "there is a hole in the numbering": the latter must never be treated as the end of the sequence, as we would then silently ignore all patches beyond the hole.

Parameters
dbdatabase context to get the load path from
load_suffixsuffix to append to the load path, usually "subsystem-"
frompatch number to start searching at
[out]foundset to the number of the patch that was found
Returns
true if a patch with a number of at least from exists

Definition at line 368 of file pq_connect.c.

372{
373 for (unsigned int i = from; i<5; i++)
374 {
375 if (GNUNET_YES !=
377 load_suffix,
378 i))
379 continue;
380 *found = i;
381 return true;
382 }
383 return false;
384}
@ GNUNET_YES
static enum GNUNET_GenericReturnValue patch_file_exists(const struct GNUNET_PQ_Context *db, const char *load_suffix, unsigned int patch_number)
Check if the SQL file for the patch with the given patch_number exists in the load path of db.
Definition pq_connect.c:331

References db, GNUNET_YES, and patch_file_exists().

Referenced by GNUNET_PQ_check_current(), and GNUNET_PQ_run_sql().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_PQ_exec_sql()

enum GNUNET_GenericReturnValue GNUNET_PQ_exec_sql ( struct GNUNET_PQ_Context db,
const char *  buf 
)

Execute SQL statements from buf against db.

The given filename infix in buf is prefixed with the "load_path" and ".sql" is appended to construct the full filename.

Parameters
[in,out]dbdatabase context to use
buffilename infix (!) with the SQL code to run
Returns
GNUNET_OK on success GNUNET_NO if patch buf does not exist GNUNET_SYSERR on error

Definition at line 388 of file pq_connect.c.

390{
391 struct GNUNET_Process *psql;
393 unsigned long code;
394 char *fn;
395
396 fn = get_sql_file_name (db,
397 buf);
398 if (GNUNET_YES !=
400 {
401 GNUNET_free (fn);
402 return GNUNET_NO;
403 }
405 "Applying SQL file `%s' on database %s\n",
406 fn,
407 db->config_str);
409 if (GNUNET_OK !=
411 "psql",
412 "psql",
413 db->config_str,
414 "-f",
415 fn,
416 "-q",
417 "--set",
418 "ON_ERROR_STOP=1",
419 NULL))
420 {
422 "exec",
423 "psql");
425 GNUNET_free (fn);
426 return GNUNET_SYSERR;
427 }
430 true,
431 &type,
432 &code));
434 if ( (GNUNET_OS_PROCESS_EXITED != type) ||
435 (0 != code) )
436 {
438 "Could not run PSQL on file %s: psql exit code was %d\n",
439 fn,
440 (int) code);
441 GNUNET_free (fn);
442 return GNUNET_SYSERR;
443 }
444 GNUNET_free (fn);
445 return GNUNET_OK;
446}
static uint32_t type
Type string converted to DNS type value.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
enum GNUNET_GenericReturnValue GNUNET_process_run_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command and start a process.
Definition os_process.c:906
enum GNUNET_GenericReturnValue GNUNET_process_wait(struct GNUNET_Process *proc, bool blocking, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Wait for a process to terminate.
void GNUNET_process_destroy(struct GNUNET_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition os_process.c:363
GNUNET_OS_ProcessStatusType
Process status types.
struct GNUNET_Process * GNUNET_process_create(enum GNUNET_OS_InheritStdioFlags std_inheritance)
Create a process handle.
Definition os_process.c:465
@ GNUNET_OS_INHERIT_STD_NONE
No standard streams should be inherited.
@ GNUNET_OS_PROCESS_EXITED
The process exited with a return code.

References db, get_sql_file_name(), GNUNET_assert, GNUNET_DISK_file_test_read(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_strerror_file, GNUNET_NO, GNUNET_OK, GNUNET_OS_INHERIT_STD_NONE, GNUNET_OS_PROCESS_EXITED, GNUNET_process_create(), GNUNET_process_destroy(), GNUNET_process_run_command_va(), GNUNET_process_wait(), GNUNET_SYSERR, GNUNET_YES, and type.

Referenced by GNUNET_PQ_load_versioning(), GNUNET_PQ_run_sql(), libgnunet_plugin_datacache_postgres_done(), and namestore_postgres_drop_tables().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_PQ_check_current()

enum GNUNET_GenericReturnValue GNUNET_PQ_check_current ( struct GNUNET_PQ_Context db,
const char *  prefix 
)

Check if the database is current with respect to database migrations using prefix.

Parameters
[in,out]dbdatabase to check versioning for
prefixprefix to use to check migrations
Returns
GNUNET_OK on success GNUNET_NO if migrations are pending GNUNET_SYSERR on failure

Definition at line 450 of file pq_connect.c.

452{
454 "Loading SQL resources from `%s'\n",
455 load_suffix);
456 for (unsigned int i = 1; i<10000; i++)
457 {
459 unsigned int next;
460
462 load_suffix,
463 i);
464 if (GNUNET_SYSERR == ret)
465 {
466 GNUNET_break (0);
467 return GNUNET_SYSERR;
468 }
469 if (GNUNET_OK == ret)
470 continue; /* patch already applied, skip it */
471 /* patch not applied, check if it (or, in case the numbering
472 has a hole, any later patch) exists... */
473 if (find_next_patch (db,
474 load_suffix,
475 i,
476 &next))
477 return GNUNET_NO;
478 return GNUNET_OK;
479 }
480 GNUNET_break (0); /* 10k patches applied!? */
481 return GNUNET_OK;
482}
static enum GNUNET_GenericReturnValue check_patch_applied(struct GNUNET_PQ_Context *db, const char *load_path, unsigned int patch_number)
Check if the patch with patch_number from the given load_path was already applied on the db.
Definition pq_connect.c:184
static bool find_next_patch(const struct GNUNET_PQ_Context *db, const char *load_suffix, unsigned int from, unsigned int *found)
Find the lowest patch number of at least from for which an SQL file exists in the load path of db.
Definition pq_connect.c:368

References check_patch_applied(), db, find_next_patch(), GNUNET_break, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, and ret.

Here is the call graph for this function:

◆ GNUNET_PQ_run_sql()

enum GNUNET_GenericReturnValue GNUNET_PQ_run_sql ( struct GNUNET_PQ_Context db,
const char *  load_suffix 
)

Within the db context, run all the SQL files in the load path where the name starts with the load_suffix and ends with consecutive numbers from "[0000-9999].sql".

The numbering must have no gaps: if a patch file is missing but a higher-numbered one exists, this is an error, as we must not skip patches.

Parameters
dbdatabase context to use
load_suffixsuffix to append to the load path to find the XXXX.sql files, usually "subsystem-".
Returns
GNUNET_OK on success GNUNET_NO if no upgrade was needed GNUNET_SYSERR if the upgrade failed or the patch numbering has a gap

Definition at line 486 of file pq_connect.c.

488{
489 size_t slen = strlen (load_suffix) + 10;
490 char patch_name[slen];
491
493 "Loading SQL resources from `%s'\n",
494 load_suffix);
495 for (unsigned int i = 1; i<10000; i++)
496 {
498
500 load_suffix,
501 i);
502 if (GNUNET_SYSERR == ret)
503 {
504 GNUNET_break (0);
505 return GNUNET_SYSERR;
506 }
507 if (GNUNET_OK == ret)
508 continue; /* patch already applied, skip it */
509
510 GNUNET_snprintf (patch_name,
511 sizeof (patch_name),
512 "%s%04u",
513 load_suffix,
514 i);
516 patch_name);
517 if (GNUNET_NO == ret)
518 {
519 unsigned int next;
520
521 /* No such file. Before we conclude that we are done, make sure
522 this really is the end of the sequence and not a hole in the
523 numbering: applying the patches beyond the hole (or, worse,
524 silently not applying them) would leave the database in an
525 undefined state. */
526 if (find_next_patch (db,
527 load_suffix,
528 i + 1,
529 &next))
530 {
532 "Gap in SQL patch sequence: `%s%04u' is missing, but `%s%04u' exists; refusing to apply patches out of order\n",
533 load_suffix,
534 i,
535 load_suffix,
536 next);
537 return GNUNET_SYSERR;
538 }
539 break; /* no such file, we are done */
540 }
541 if (GNUNET_SYSERR == ret)
542 return GNUNET_SYSERR;
543 }
544 return GNUNET_OK;
545}
enum GNUNET_GenericReturnValue GNUNET_PQ_exec_sql(struct GNUNET_PQ_Context *db, const char *buf)
Execute SQL statements from buf against db.
Definition pq_connect.c:388

References check_patch_applied(), db, find_next_patch(), GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_PQ_exec_sql(), GNUNET_snprintf(), GNUNET_SYSERR, and ret.

Referenced by reconnect_cb(), reconnect_setup(), reconnect_setup(), and reconnect_setup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_PQ_reconnect_if_down()

void GNUNET_PQ_reconnect_if_down ( struct GNUNET_PQ_Context db)

Reinitialize the database db if the connection is down.

Parameters
[in,out]dbdatabase connection to reinitialize

Definition at line 549 of file pq_connect.c.

550{
551 if (1 ==
552 PQconsumeInput (db->conn))
553 return;
554 if (CONNECTION_BAD != PQstatus (db->conn))
555 return;
557}
void GNUNET_PQ_reconnect_(struct GNUNET_PQ_Context *db)
Reinitialize the database db.
Definition pq_connect.c:662

References db, and GNUNET_PQ_reconnect_().

Here is the call graph for this function:

◆ GNUNET_PQ_get_oid_by_name()

enum GNUNET_GenericReturnValue GNUNET_PQ_get_oid_by_name ( struct GNUNET_PQ_Context db,
const char *  name,
Oid *  oid 
)

Returns the oid for a given datatype by name.

Parameters
dbThe db-connection
nameThe name of the datatype
[out]oidThe OID of the datatype.
Returns
GNUNET_OK when the datatype was found, GNUNET_SYSERR otherwise

Definition at line 561 of file pq_connect.c.

565{
566 /* Check if the entry is in the cache already */
567 for (unsigned int i = 0; i < db->oids.num; i++)
568 {
569 /* Pointer comparison */
570 if (name == db->oids.table[i].name)
571 {
572 *oid = db->oids.table[i].oid;
573 return GNUNET_OK;
574 }
575 }
576
577 /* No entry found in cache, ask database */
578 {
579 enum GNUNET_DB_QueryStatus qs;
580 struct GNUNET_PQ_QueryParam params[] = {
583 };
584 struct GNUNET_PQ_ResultSpec spec[] = {
586 oid),
588 };
589
590 GNUNET_assert (NULL != db);
591
593 "gnunet_pq_get_oid_by_name",
594 params,
595 spec);
597 return GNUNET_SYSERR;
598 }
599
600 /* Add the entry to the cache */
601 if (NULL == db->oids.table)
602 {
603 db->oids.table = GNUNET_new_array (8,
604 typeof(*db->oids.table));
605 db->oids.cap = 8;
606 db->oids.num = 0;
607 }
608
609 if (db->oids.cap <= db->oids.num)
610 GNUNET_array_grow (db->oids.table,
611 db->oids.cap,
612 db->oids.cap + 8);
613
614 db->oids.table[db->oids.num].name = name;
615 db->oids.table[db->oids.num].oid = *oid;
616 db->oids.num++;
617
618 return GNUNET_OK;
619}
static char * name
Name (label) of the records to list.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint32(const char *name, uint32_t *u32)
uint32_t expected.
uint32_t oid
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.

References db, GNUNET_array_grow, GNUNET_assert, GNUNET_DB_STATUS_SUCCESS_ONE_RESULT, GNUNET_new_array, GNUNET_OK, GNUNET_PQ_eval_prepared_singleton_select(), GNUNET_PQ_query_param_end, GNUNET_PQ_query_param_string(), GNUNET_PQ_result_spec_end, GNUNET_PQ_result_spec_uint32(), GNUNET_SYSERR, name, and oid.

Referenced by GNUNET_PQ_query_param_array_abs_time(), GNUNET_PQ_query_param_array_bool(), GNUNET_PQ_query_param_array_bytes(), GNUNET_PQ_query_param_array_bytes_same_size(), GNUNET_PQ_query_param_array_int16(), GNUNET_PQ_query_param_array_ptrs_abs_time(), GNUNET_PQ_query_param_array_ptrs_bytes(), GNUNET_PQ_query_param_array_ptrs_bytes_same_size(), GNUNET_PQ_query_param_array_ptrs_rel_time(), GNUNET_PQ_query_param_array_ptrs_string(), GNUNET_PQ_query_param_array_ptrs_timestamp(), GNUNET_PQ_query_param_array_rel_time(), GNUNET_PQ_query_param_array_string(), GNUNET_PQ_query_param_array_timestamp(), GNUNET_PQ_query_param_array_uint16(), GNUNET_PQ_query_param_array_uint32(), GNUNET_PQ_query_param_array_uint64(), GNUNET_PQ_result_spec_array_abs_time(), GNUNET_PQ_result_spec_array_bool(), GNUNET_PQ_result_spec_array_fixed_size(), GNUNET_PQ_result_spec_array_int16(), GNUNET_PQ_result_spec_array_rel_time(), GNUNET_PQ_result_spec_array_string(), GNUNET_PQ_result_spec_array_timestamp(), GNUNET_PQ_result_spec_array_uint16(), GNUNET_PQ_result_spec_array_uint32(), GNUNET_PQ_result_spec_array_uint64(), GNUNET_PQ_result_spec_array_variable_size(), and load_initial_oids().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_initial_oids()

static enum GNUNET_GenericReturnValue load_initial_oids ( struct GNUNET_PQ_Context db)
static

Load the initial set of OIDs for the supported array-datatypes.

Parameters
dbThe database context
Returns
GNUNET_OK on success, GNUNET_SYSERR if any of the types couldn't be found

Definition at line 631 of file pq_connect.c.

632{
633 static const char *typnames[] = {
634 "bool",
635 "int2",
636 "int4",
637 "int8",
638 "bytea",
639 "varchar"
640 };
641 Oid oid;
642
643 for (size_t i = 0; i< sizeof(typnames) / sizeof(*typnames); i++)
644 {
645 if (GNUNET_OK !=
647 typnames[i],
648 &oid))
649 {
651 "pq",
652 "Couldn't retrieve OID for type %s\n",
653 typnames[i]);
654 return GNUNET_SYSERR;
655 }
656 }
657 return GNUNET_OK;
658}
enum GNUNET_GenericReturnValue GNUNET_PQ_get_oid_by_name(struct GNUNET_PQ_Context *db, const char *name, Oid *oid)
Returns the oid for a given datatype by name.
Definition pq_connect.c:561

References db, GNUNET_ERROR_TYPE_ERROR, GNUNET_log_from, GNUNET_OK, GNUNET_PQ_get_oid_by_name(), GNUNET_SYSERR, and oid.

Referenced by GNUNET_PQ_reconnect_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_PQ_reconnect_()

void GNUNET_PQ_reconnect_ ( struct GNUNET_PQ_Context db)

Reinitialize the database db.

Parameters
dbdatabase connection to reinitialize
Deprecated:

Definition at line 662 of file pq_connect.c.

663{
665 -1);
667 db->versioning_ok = GNUNET_SYSERR; /* new connection, new game */
668 db->conn = PQconnectdb (db->config_str);
669 if ( (NULL == db->conn) ||
670 (CONNECTION_OK != PQstatus (db->conn)) )
671 {
673 "pq",
674 "Database connection to '%s' failed: %s\n",
675 db->config_str,
676 (NULL != db->conn)
677 ? PQerrorMessage (db->conn)
678 : "PQconnectdb returned NULL");
680 return;
681 }
682 PQsetNoticeReceiver (db->conn,
684 db);
685 PQsetNoticeProcessor (db->conn,
687 db);
688 if (NULL != db->rc)
689 db->rc (db->rc_cls,
690 db);
691
692 /* Prepare statement for OID lookup by name */
693 if (GNUNET_OK !=
695 return;
696
697 /* Reset the OID-cache and retrieve the OIDs for the supported Array types */
698 db->oids.num = 0;
700 {
702 "Failed to retrieve OID information for array types!\n");
704 return;
705 }
707 PQsocket (db->conn));
708}
void GNUNET_PQ_event_reconnect_(struct GNUNET_PQ_Context *db, int fd)
Internal API.
Definition pq_event.c:434
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:265
static enum GNUNET_GenericReturnValue prepare_get_oid_by_name(struct GNUNET_PQ_Context *db)
Prepare the "gnunet_pq_get_oid_by_name" statement.
Definition pq_connect.c:96
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:282
static enum GNUNET_GenericReturnValue load_initial_oids(struct GNUNET_PQ_Context *db)
Load the initial set of OIDs for the supported array-datatypes.
Definition pq_connect.c:631

References db, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_log_from, GNUNET_OK, GNUNET_PQ_event_reconnect_(), GNUNET_SYSERR, load_initial_oids(), pq_notice_processor_cb(), pq_notice_receiver_cb(), prepare_get_oid_by_name(), and reset_connection().

Referenced by do_scheduler_notify(), GNUNET_PQ_eval_result(), GNUNET_PQ_event_do_poll(), GNUNET_PQ_exec_prepared(), GNUNET_PQ_init(), and GNUNET_PQ_reconnect_if_down().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_PQ_load_versioning()

enum GNUNET_GenericReturnValue GNUNET_PQ_load_versioning ( struct GNUNET_PQ_Context db)

Setup database versioning.

Parameters
[in,out]dbdatabase to load versioning for
Returns
GNUNET_OK on success GNUNET_NO if it was already loaded GNUNET_SYSERR on failure

Definition at line 712 of file pq_connect.c.

713{
715
717 if (GNUNET_SYSERR == ret)
718 return GNUNET_SYSERR;
719 if (GNUNET_YES == ret)
720 return GNUNET_NO; /* already setup */
722 "versioning");
723 if (GNUNET_NO == ret)
724 {
726 "Failed to find SQL file to load database versioning logic\n");
727 return GNUNET_SYSERR;
728 }
729 if (GNUNET_SYSERR == ret)
730 {
732 "Failed to run SQL logic to setup database versioning logic\n");
733 return GNUNET_SYSERR;
734 }
735 db->versioning_ok = GNUNET_YES;
736 return GNUNET_OK;
737}

References check_versioning_ok(), db, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_PQ_exec_sql(), GNUNET_SYSERR, GNUNET_YES, and ret.

Referenced by reconnect_setup(), and reconnect_setup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_PQ_init()

struct GNUNET_PQ_Context * GNUNET_PQ_init ( const struct GNUNET_CONFIGURATION_Handle cfg,
const char *  section,
GNUNET_PQ_ReconnectCallback  rc,
GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE rc_cls 
)

Definition at line 741 of file pq_connect.c.

745{
746 struct GNUNET_PQ_Context *db;
747 char *conninfo;
748 char *load_path;
749
750 if (GNUNET_OK !=
752 section,
753 "CONFIG",
754 &conninfo))
755 conninfo = GNUNET_strdup ("");
756 load_path = NULL;
757 if (GNUNET_OK !=
759 section,
760 "SQL_DIR",
761 &load_path))
762 {
764 section,
765 "SQL_DIR");
766 }
768 db->versioning_ok = GNUNET_SYSERR;
769 db->config_str = conninfo;
770 db->load_path = load_path;
771 db->rc = rc;
772 db->rc_cls = rc_cls;
773 db->channel_map = GNUNET_CONTAINER_multishortmap_create (16,
774 true);
776 if (NULL == db->conn)
777 {
779 GNUNET_free (db->config_str);
780 GNUNET_free (db);
781 return NULL;
782 }
783 return db;
784}
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition gnunet-arm.c:108
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue 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_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Handle to Postgres database.
Definition pq.h:36
GNUNET_PQ_ReconnectCallback rc
Function to call whenever we needed to reconnect conn.
Definition pq.h:45
char * load_path
Path to load SQL files from.
Definition pq.h:60
GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE * rc_cls
Closure for rc.
Definition pq.h:50

References cfg, db, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONTAINER_multishortmap_create(), GNUNET_CONTAINER_multishortmap_destroy(), GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log_config_missing(), GNUNET_new, GNUNET_OK, GNUNET_PQ_reconnect_(), GNUNET_strdup, GNUNET_SYSERR, GNUNET_PQ_Context::load_path, GNUNET_PQ_Context::rc, and GNUNET_PQ_Context::rc_cls.

Here is the call graph for this function:

◆ GNUNET_PQ_disconnect()

void GNUNET_PQ_disconnect ( struct GNUNET_PQ_Context db)

Disconnect from the database, destroying the prepared statements and releasing other associated resources.

Parameters
dbdatabase handle to disconnect (will be free'd)

Definition at line 788 of file pq_connect.c.

789{
790 if (NULL == db)
791 return;
792 GNUNET_assert (0 ==
795 if (NULL != db->poller_task)
796 {
797 GNUNET_SCHEDULER_cancel (db->poller_task);
798 db->poller_task = NULL;
799 }
800 GNUNET_free (db->load_path);
801 GNUNET_free (db->config_str);
802 GNUNET_free (db->oids.table);
803 db->oids.num = 0;
804 db->oids.cap = 0;
805 PQfinish (db->conn);
806 GNUNET_free (db);
807}
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986

References db, GNUNET_assert, GNUNET_CONTAINER_multishortmap_destroy(), GNUNET_CONTAINER_multishortmap_size(), GNUNET_free, and GNUNET_SCHEDULER_cancel().

Referenced by database_shutdown(), database_shutdown(), libgnunet_plugin_datacache_postgres_done(), libgnunet_plugin_datastore_postgres_done(), namestore_postgres_create_tables(), and namestore_postgres_drop_tables().

Here is the call graph for this function:
Here is the caller graph for this function: