33#define PSQL_OUTPUT_BYTES (64 * 1024)
36#define PSQL_OUTPUT_LINES 250
51 db->prepared_check_patch =
false;
52 db->prepared_get_oid_by_name =
false;
68 if (
db->prepared_check_patch)
70 res = PQprepare (
db->conn,
71 "gnunet_pq_check_patch",
75 " WHERE patch_name = $1"
79 if (PGRES_COMMAND_OK !=
83 "Failed to run SQL logic to setup database versioning logic: %s/%s\n",
84 PQresultErrorMessage (
res),
85 PQerrorMessage (
db->conn));
91 db->prepared_check_patch =
true;
108 if (
db->prepared_get_oid_by_name)
110 res = PQprepare (
db->conn,
111 "gnunet_pq_get_oid_by_name",
112 "SELECT typname, oid"
114 " WHERE oid = to_regtype($1)",
117 if (PGRES_COMMAND_OK != PQresultStatus (
res))
120 "Failed to run SQL statement prepare OID lookups: %s/%s\n",
121 PQresultErrorMessage (
res),
122 PQerrorMessage (
db->conn));
128 db->prepared_get_oid_by_name =
true;
152 res = PQexec (
db->conn,
155 " FROM information_schema.schemata"
156 " WHERE schema_name='_v';");
157 est = PQresultStatus (
res);
158 if ( (PGRES_COMMAND_OK != est) &&
159 (PGRES_TUPLES_OK != est) )
162 "Failed to run statement to check versioning schema. Bad!\n");
166 if (0 == PQntuples (
res))
171 "_v schema not found\n");
193 const char *load_path,
194 unsigned int patch_number)
196 const char *load_path_suffix;
197 size_t slen = strlen (load_path) + 10;
198 char patch_name[slen];
206 load_path_suffix = strrchr (load_path,
208 if (NULL == load_path_suffix)
209 load_path_suffix = load_path;
237 "gnunet_pq_check_patch",
244 "Database version %s already applied by %s\n",
340 const char *load_suffix,
341 unsigned int patch_number)
343 size_t slen = strlen (load_suffix) + 10;
344 char patch_name[slen];
377 const char *load_suffix,
381 for (
unsigned int i = from; i<5; i++)
408 unsigned int lines = 0;
410 for (
size_t i =
size; i > 0; i--)
413 if ( (
'\n' == output[i - 1]) &&
424 "psql stderr truncated to the last %u lines and %u bytes; earlier output omitted\n",
431 if (
'\0' == output[i])
433 if (
'\n' != output[i])
459 bool truncated =
false;
460 bool capture_failed =
false;
461 bool child_exited =
false;
476 "Applying SQL file `%s' on database %s\n",
483 "pipe for psql stderr",
491 ready = (
struct pollfd) {
503 "Failed to configure psql stderr capture for SQL file `%s'\n",
531 size_t wanted =
sizeof (chunk);
546 while (0 > ioctl (ready.fd, FIONREAD, &queued))
551 "inspect queued psql stderr",
553 capture_failed =
true;
564 wanted =
GNUNET_MIN (wanted, (
size_t) queued);
575 if ( (EAGAIN == errno) || (EWOULDBLOCK == errno) )
581 if ( (0 > poll (&ready, 1, 100)) && (EINTR != errno) )
586 capture_failed =
true;
594 capture_failed =
true;
609 memcpy (output + used,
614 if (capture_failed && (! child_exited))
628 "Failed to execute SQL file `%s': psql terminated by signal %lu\n",
633 "Failed to execute SQL file `%s': psql exit code was %lu\n",
636 capture_failed =
true;
678 const char *load_suffix)
681 "Loading SQL resources from `%s'\n",
683 for (
unsigned int i = 1; i<10000; i++)
714 const char *load_suffix)
716 size_t slen = strlen (load_suffix) + 10;
717 char patch_name[slen];
720 "Loading SQL resources from `%s'\n",
722 for (
unsigned int i = 1; i<10000; i++)
759 "Gap in SQL patch sequence: `%s%04u' is missing, but `%s%04u' exists; refusing to apply patches out of order\n",
779 PQconsumeInput (
db->conn))
781 if (CONNECTION_BAD != PQstatus (
db->conn))
794 for (
unsigned int i = 0; i <
db->oids.num; i++)
797 if (
name ==
db->oids.table[i].name)
799 *
oid =
db->oids.table[i].oid;
820 "gnunet_pq_get_oid_by_name",
828 if (NULL ==
db->oids.table)
831 typeof(*
db->oids.table));
836 if (
db->oids.cap <=
db->oids.num)
841 db->oids.table[
db->oids.num].name =
name;
842 db->oids.table[
db->oids.num].oid = *
oid;
860 static const char *typnames[] = {
870 for (
size_t i = 0; i<
sizeof(typnames) /
sizeof(*typnames); i++)
879 "Couldn't retrieve OID for type %s\n",
895 db->conn = PQconnectdb (
db->config_str);
896 if ( (NULL ==
db->conn) ||
897 (CONNECTION_OK != PQstatus (
db->conn)) )
901 "Database connection to '%s' failed: %s\n",
904 ? PQerrorMessage (
db->conn)
905 :
"PQconnectdb returned NULL");
909 PQsetNoticeReceiver (
db->conn,
912 PQsetNoticeProcessor (
db->conn,
929 "Failed to retrieve OID information for array types!\n");
934 PQsocket (
db->conn));
953 "Failed to find SQL file to load database versioning logic\n");
959 "Failed to run SQL logic to setup database versioning logic\n");
996 db->config_str = conninfo;
1003 if (NULL ==
db->conn)
1022 if (NULL !=
db->poller_task)
1025 db->poller_task = NULL;
1032 PQfinish (
db->conn);
static int start
Set if we are to start default services (including ARM).
static int ret
Final status code.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static char * name
Name (label) of the records to list.
static char * res
Currently read line or NULL on EOF.
static uint32_t type
Type string converted to DNS type value.
static int status
The program status; 0 for success.
static struct GNUNET_FS_DirectoryBuilder * db
static void cleanup()
Cleanup task.
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.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint32(const char *name, uint32_t *u32)
uint32_t expected.
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...
void(* GNUNET_PQ_ReconnectCallback)(void *cls, struct GNUNET_PQ_Context *pq)
Function called each time we connect or reconnect to the database.
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().
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_PQ_RECONNECT_CALLBACK_CLOSURE
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.
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test_read(const char *fil)
Check that fil corresponds to a filename and the file has read permissions.
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
int GNUNET_DISK_internal_file_handle(const struct GNUNET_DISK_FileHandle *fh)
Retrieve OS file handle.
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
@ GNUNET_DISK_PF_BLOCKING_WRITE
Configure write end to block when writing if set.
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
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.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
#define GNUNET_log(kind,...)
#define GNUNET_log_from(kind, comp,...)
GNUNET_GenericReturnValue
Named constants for return values.
#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.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#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...
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
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.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
enum GNUNET_GenericReturnValue GNUNET_process_run_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command and start a process.
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.
#define GNUNET_process_set_options(proc,...)
Set the requested options for the process.
GNUNET_OS_ProcessStatusType
Process status types.
#define GNUNET_process_option_inherit_wpipe(wpipe, child_fd)
Have child process inherit a pipe for writing.
enum GNUNET_GenericReturnValue GNUNET_process_kill(struct GNUNET_Process *proc, int sig)
Sends a signal to the process.
struct GNUNET_Process * GNUNET_process_create(enum GNUNET_OS_InheritStdioFlags std_inheritance)
Create a process handle.
@ GNUNET_OS_INHERIT_STD_NONE
No standard streams should be inherited.
@ GNUNET_OS_PROCESS_SIGNALED
The process was killed by a signal.
@ GNUNET_OS_PROCESS_EXITED
The process exited with a return code.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
static unsigned int size
Size of the "table".
shared internal data structures of libgnunetpq
void GNUNET_PQ_event_reconnect_(struct GNUNET_PQ_Context *db, int fd)
Internal API.
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.
#define PSQL_OUTPUT_LINES
Maximum number of retained stderr lines emitted on failure.
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 prepare_check_patch(struct GNUNET_PQ_Context *db)
Prepare the "gnunet_pq_check_patch" statement.
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.
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.
static void pq_notice_receiver_cb(void *arg, const PGresult *res)
Function called by libpq whenever it wants to log something.
static void reset_connection(struct GNUNET_PQ_Context *db)
Close connection to db and mark it as uninitialized.
static enum GNUNET_GenericReturnValue prepare_get_oid_by_name(struct GNUNET_PQ_Context *db)
Prepare the "gnunet_pq_get_oid_by_name" statement.
void GNUNET_PQ_reconnect_if_down(struct GNUNET_PQ_Context *db)
Reinitialize the database db if the connection is down.
void GNUNET_PQ_disconnect(struct GNUNET_PQ_Context *db)
Disconnect from the database, destroying the prepared statements and releasing other associated resou...
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)
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 void log_psql_output(char *output, size_t size, bool truncated)
Log the last lines of captured psql stderr through the component logger.
#define PSQL_OUTPUT_BYTES
Maximum stderr tail retained from one psql invocation.
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.
static void pq_notice_processor_cb(void *arg, const char *message)
Function called by libpq whenever it wants to log something.
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.
enum GNUNET_GenericReturnValue GNUNET_PQ_exec_sql(struct GNUNET_PQ_Context *db, const char *buf)
Execute SQL statements from buf against 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 enum GNUNET_GenericReturnValue load_initial_oids(struct GNUNET_PQ_Context *db)
Load the initial set of OIDs for the supported array-datatypes.
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_suf...
Handle used to access files (and pipes).
Handle used to manage a pipe.
Handle to Postgres database.
GNUNET_PQ_ReconnectCallback rc
Function to call whenever we needed to reconnect conn.
char * load_path
Path to load SQL files from.
GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE * rc_cls
Closure for rc.
Description of a DB query parameter.
Description of a DB result cell.