aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-09-13 11:05:07 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-09-13 11:11:45 -0400
commit0a20ff54f5e66158930d5328f89f087d4e9ab400 (patch)
tree061094ad7638e0d0be3fe007f29ed31710a75cec /src/backend/access/transam/xlog.c
parent257eb57b50f7c65467bfc2f4d579622fa13f3370 (diff)
downloadpostgresql-0a20ff54f5e66158930d5328f89f087d4e9ab400.tar.gz
postgresql-0a20ff54f5e66158930d5328f89f087d4e9ab400.zip
Split up guc.c for better build speed and ease of maintenance.
guc.c has grown to be one of our largest .c files, making it a bottleneck for compilation. It's also acquired a bunch of knowledge that'd be better kept elsewhere, because of our not very good habit of putting variable-specific check hooks here. Hence, split it up along these lines: * guc.c itself retains just the core GUC housekeeping mechanisms. * New file guc_funcs.c contains the SET/SHOW interfaces and some SQL-accessible functions for GUC manipulation. * New file guc_tables.c contains the data arrays that define the built-in GUC variables, along with some already-exported constant tables. * GUC check/assign/show hook functions are moved to the variable's home module, whenever that's clearly identifiable. A few hard- to-classify hooks ended up in commands/variable.c, which was already a home for miscellaneous GUC hook functions. To avoid cluttering a lot more header files with #include "guc.h", I also invented a new header file utils/guc_hooks.h and put all the GUC hook functions' declarations there, regardless of their originating module. That allowed removal of #include "guc.h" from some existing headers. The fallout from that (hopefully all caught here) demonstrates clearly why such inclusions are best minimized: there are a lot of files that, for example, were getting array.h at two or more levels of remove, despite not having any connection at all to GUCs in themselves. There is some very minor code beautification here, such as renaming a couple of inconsistently-named hook functions and improving some comments. But mostly this just moves code from point A to point B and deals with the ensuing needs for #include adjustments and exporting a few functions that previously weren't exported. Patch by me, per a suggestion from Andres Freund; thanks also to Michael Paquier for the idea to invent guc_funcs.c. Discussion: https://postgr.es/m/587607.1662836699@sss.pgh.pa.us
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c176
1 files changed, 175 insertions, 1 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 7a710e6490d..81d339d57d7 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -97,7 +97,8 @@
#include "storage/smgr.h"
#include "storage/spin.h"
#include "storage/sync.h"
-#include "utils/guc.h"
+#include "utils/guc_hooks.h"
+#include "utils/guc_tables.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/relmapper.h"
@@ -105,6 +106,7 @@
#include "utils/snapmgr.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
+#include "utils/varlena.h"
extern uint32 bootstrap_data_checksum_version;
@@ -161,6 +163,12 @@ static double CheckPointDistanceEstimate = 0;
static double PrevCheckPointDistance = 0;
/*
+ * Track whether there were any deferred checks for custom resource managers
+ * specified in wal_consistency_checking.
+ */
+static bool check_wal_consistency_checking_deferred = false;
+
+/*
* GUC support
*/
const struct config_enum_entry sync_method_options[] = {
@@ -4305,6 +4313,172 @@ check_wal_buffers(int *newval, void **extra, GucSource source)
}
/*
+ * GUC check_hook for wal_consistency_checking
+ */
+bool
+check_wal_consistency_checking(char **newval, void **extra, GucSource source)
+{
+ char *rawstring;
+ List *elemlist;
+ ListCell *l;
+ bool newwalconsistency[RM_MAX_ID + 1];
+
+ /* Initialize the array */
+ MemSet(newwalconsistency, 0, (RM_MAX_ID + 1) * sizeof(bool));
+
+ /* Need a modifiable copy of string */
+ rawstring = pstrdup(*newval);
+
+ /* Parse string into list of identifiers */
+ if (!SplitIdentifierString(rawstring, ',', &elemlist))
+ {
+ /* syntax error in list */
+ GUC_check_errdetail("List syntax is invalid.");
+ pfree(rawstring);
+ list_free(elemlist);
+ return false;
+ }
+
+ foreach(l, elemlist)
+ {
+ char *tok = (char *) lfirst(l);
+ int rmid;
+
+ /* Check for 'all'. */
+ if (pg_strcasecmp(tok, "all") == 0)
+ {
+ for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
+ if (RmgrIdExists(rmid) && GetRmgr(rmid).rm_mask != NULL)
+ newwalconsistency[rmid] = true;
+ }
+ else
+ {
+ /* Check if the token matches any known resource manager. */
+ bool found = false;
+
+ for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
+ {
+ if (RmgrIdExists(rmid) && GetRmgr(rmid).rm_mask != NULL &&
+ pg_strcasecmp(tok, GetRmgr(rmid).rm_name) == 0)
+ {
+ newwalconsistency[rmid] = true;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ /*
+ * During startup, it might be a not-yet-loaded custom
+ * resource manager. Defer checking until
+ * InitializeWalConsistencyChecking().
+ */
+ if (!process_shared_preload_libraries_done)
+ {
+ check_wal_consistency_checking_deferred = true;
+ }
+ else
+ {
+ GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
+ pfree(rawstring);
+ list_free(elemlist);
+ return false;
+ }
+ }
+ }
+ }
+
+ pfree(rawstring);
+ list_free(elemlist);
+
+ /* assign new value */
+ *extra = guc_malloc(ERROR, (RM_MAX_ID + 1) * sizeof(bool));
+ memcpy(*extra, newwalconsistency, (RM_MAX_ID + 1) * sizeof(bool));
+ return true;
+}
+
+/*
+ * GUC assign_hook for wal_consistency_checking
+ */
+void
+assign_wal_consistency_checking(const char *newval, void *extra)
+{
+ /*
+ * If some checks were deferred, it's possible that the checks will fail
+ * later during InitializeWalConsistencyChecking(). But in that case, the
+ * postmaster will exit anyway, so it's safe to proceed with the
+ * assignment.
+ *
+ * Any built-in resource managers specified are assigned immediately,
+ * which affects WAL created before shared_preload_libraries are
+ * processed. Any custom resource managers specified won't be assigned
+ * until after shared_preload_libraries are processed, but that's OK
+ * because WAL for a custom resource manager can't be written before the
+ * module is loaded anyway.
+ */
+ wal_consistency_checking = extra;
+}
+
+/*
+ * InitializeWalConsistencyChecking: run after loading custom resource managers
+ *
+ * If any unknown resource managers were specified in the
+ * wal_consistency_checking GUC, processing was deferred. Now that
+ * shared_preload_libraries have been loaded, process wal_consistency_checking
+ * again.
+ */
+void
+InitializeWalConsistencyChecking(void)
+{
+ Assert(process_shared_preload_libraries_done);
+
+ if (check_wal_consistency_checking_deferred)
+ {
+ struct config_generic *guc;
+
+ guc = find_option("wal_consistency_checking", false, false, ERROR);
+
+ check_wal_consistency_checking_deferred = false;
+
+ set_config_option_ext("wal_consistency_checking",
+ wal_consistency_checking_string,
+ guc->scontext, guc->source, guc->srole,
+ GUC_ACTION_SET, true, ERROR, false);
+
+ /* checking should not be deferred again */
+ Assert(!check_wal_consistency_checking_deferred);
+ }
+}
+
+/*
+ * GUC show_hook for archive_command
+ */
+const char *
+show_archive_command(void)
+{
+ if (XLogArchivingActive())
+ return XLogArchiveCommand;
+ else
+ return "(disabled)";
+}
+
+/*
+ * GUC show_hook for in_hot_standby
+ */
+const char *
+show_in_hot_standby(void)
+{
+ /*
+ * We display the actual state based on shared memory, so that this GUC
+ * reports up-to-date state if examined intra-query. The underlying
+ * variable (in_hot_standby_guc) changes only when we transmit a new value
+ * to the client.
+ */
+ return RecoveryInProgress() ? "on" : "off";
+}
+
+
+/*
* Read the control file, set respective GUCs.
*
* This is to be called during startup, including a crash recovery cycle,