aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/replication/logical/snapbuild.c99
-rw-r--r--src/backend/utils/adt/arrayfuncs.c6
-rw-r--r--src/include/replication/snapbuild.h4
-rw-r--r--src/include/replication/snapbuild_internal.h3
4 files changed, 73 insertions, 39 deletions
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index b9df8c0a024..a6a4da32668 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1684,34 +1684,31 @@ out:
}
/*
- * Restore a snapshot into 'builder' if previously one has been stored at the
- * location indicated by 'lsn'. Returns true if successful, false otherwise.
+ * Restore the logical snapshot file contents to 'ondisk'.
+ *
+ * 'context' is the memory context where the catalog modifying/committed xid
+ * will live.
+ * If 'missing_ok' is true, will not throw an error if the file is not found.
*/
-static bool
-SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
+bool
+SnapBuildRestoreSnapshot(SnapBuildOnDisk *ondisk, const char *path,
+ MemoryContext context, bool missing_ok)
{
- SnapBuildOnDisk ondisk;
int fd;
- char path[MAXPGPATH];
- Size sz;
pg_crc32c checksum;
-
- /* no point in loading a snapshot if we're already there */
- if (builder->state == SNAPBUILD_CONSISTENT)
- return false;
-
- sprintf(path, "%s/%X-%X.snap",
- PG_LOGICAL_SNAPSHOTS_DIR,
- LSN_FORMAT_ARGS(lsn));
+ Size sz;
fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
- if (fd < 0 && errno == ENOENT)
- return false;
- else if (fd < 0)
+ if (fd < 0)
+ {
+ if (missing_ok && errno == ENOENT)
+ return false;
+
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", path)));
+ }
/* ----
* Make sure the snapshot had been stored safely to disk, that's normally
@@ -1724,47 +1721,46 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
fsync_fname(path, false);
fsync_fname(PG_LOGICAL_SNAPSHOTS_DIR, true);
-
/* read statically sized portion of snapshot */
- SnapBuildRestoreContents(fd, (char *) &ondisk, SnapBuildOnDiskConstantSize, path);
+ SnapBuildRestoreContents(fd, (char *) ondisk, SnapBuildOnDiskConstantSize, path);
- if (ondisk.magic != SNAPBUILD_MAGIC)
+ if (ondisk->magic != SNAPBUILD_MAGIC)
ereport(ERROR,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("snapbuild state file \"%s\" has wrong magic number: %u instead of %u",
- path, ondisk.magic, SNAPBUILD_MAGIC)));
+ path, ondisk->magic, SNAPBUILD_MAGIC)));
- if (ondisk.version != SNAPBUILD_VERSION)
+ if (ondisk->version != SNAPBUILD_VERSION)
ereport(ERROR,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("snapbuild state file \"%s\" has unsupported version: %u instead of %u",
- path, ondisk.version, SNAPBUILD_VERSION)));
+ path, ondisk->version, SNAPBUILD_VERSION)));
INIT_CRC32C(checksum);
COMP_CRC32C(checksum,
- ((char *) &ondisk) + SnapBuildOnDiskNotChecksummedSize,
+ ((char *) ondisk) + SnapBuildOnDiskNotChecksummedSize,
SnapBuildOnDiskConstantSize - SnapBuildOnDiskNotChecksummedSize);
/* read SnapBuild */
- SnapBuildRestoreContents(fd, (char *) &ondisk.builder, sizeof(SnapBuild), path);
- COMP_CRC32C(checksum, &ondisk.builder, sizeof(SnapBuild));
+ SnapBuildRestoreContents(fd, (char *) &ondisk->builder, sizeof(SnapBuild), path);
+ COMP_CRC32C(checksum, &ondisk->builder, sizeof(SnapBuild));
/* restore committed xacts information */
- if (ondisk.builder.committed.xcnt > 0)
+ if (ondisk->builder.committed.xcnt > 0)
{
- sz = sizeof(TransactionId) * ondisk.builder.committed.xcnt;
- ondisk.builder.committed.xip = MemoryContextAllocZero(builder->context, sz);
- SnapBuildRestoreContents(fd, (char *) ondisk.builder.committed.xip, sz, path);
- COMP_CRC32C(checksum, ondisk.builder.committed.xip, sz);
+ sz = sizeof(TransactionId) * ondisk->builder.committed.xcnt;
+ ondisk->builder.committed.xip = MemoryContextAllocZero(context, sz);
+ SnapBuildRestoreContents(fd, (char *) ondisk->builder.committed.xip, sz, path);
+ COMP_CRC32C(checksum, ondisk->builder.committed.xip, sz);
}
/* restore catalog modifying xacts information */
- if (ondisk.builder.catchange.xcnt > 0)
+ if (ondisk->builder.catchange.xcnt > 0)
{
- sz = sizeof(TransactionId) * ondisk.builder.catchange.xcnt;
- ondisk.builder.catchange.xip = MemoryContextAllocZero(builder->context, sz);
- SnapBuildRestoreContents(fd, (char *) ondisk.builder.catchange.xip, sz, path);
- COMP_CRC32C(checksum, ondisk.builder.catchange.xip, sz);
+ sz = sizeof(TransactionId) * ondisk->builder.catchange.xcnt;
+ ondisk->builder.catchange.xip = MemoryContextAllocZero(context, sz);
+ SnapBuildRestoreContents(fd, (char *) ondisk->builder.catchange.xip, sz, path);
+ COMP_CRC32C(checksum, ondisk->builder.catchange.xip, sz);
}
if (CloseTransientFile(fd) != 0)
@@ -1775,11 +1771,36 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
FIN_CRC32C(checksum);
/* verify checksum of what we've read */
- if (!EQ_CRC32C(checksum, ondisk.checksum))
+ if (!EQ_CRC32C(checksum, ondisk->checksum))
ereport(ERROR,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("checksum mismatch for snapbuild state file \"%s\": is %u, should be %u",
- path, checksum, ondisk.checksum)));
+ path, checksum, ondisk->checksum)));
+
+ return true;
+}
+
+/*
+ * Restore a snapshot into 'builder' if previously one has been stored at the
+ * location indicated by 'lsn'. Returns true if successful, false otherwise.
+ */
+static bool
+SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
+{
+ SnapBuildOnDisk ondisk;
+ char path[MAXPGPATH];
+
+ /* no point in loading a snapshot if we're already there */
+ if (builder->state == SNAPBUILD_CONSISTENT)
+ return false;
+
+ sprintf(path, "%s/%X-%X.snap",
+ PG_LOGICAL_SNAPSHOTS_DIR,
+ LSN_FORMAT_ARGS(lsn));
+
+ /* validate and restore the snapshot to 'ondisk' */
+ if (!SnapBuildRestoreSnapshot(&ondisk, path, builder->context, true))
+ return false;
/*
* ok, we now have a sensible snapshot here, figure out if it has more
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 1640d838852..a715e7e0b8e 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -3453,6 +3453,12 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
elmalign = TYPALIGN_SHORT;
break;
+ case XIDOID:
+ elmlen = sizeof(TransactionId);
+ elmbyval = true;
+ elmalign = TYPALIGN_INT;
+ break;
+
default:
elog(ERROR, "type %u not supported by construct_array_builtin()", elmtype);
/* keep compiler quiet */
diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h
index dbb4bc2f4b2..3c1454df993 100644
--- a/src/include/replication/snapbuild.h
+++ b/src/include/replication/snapbuild.h
@@ -15,6 +15,10 @@
#include "access/xlogdefs.h"
#include "utils/snapmgr.h"
+/*
+ * Please keep get_snapbuild_state_desc() (located in the pg_logicalinspect
+ * module) updated if a change needs to be made to SnapBuildState.
+ */
typedef enum
{
/*
diff --git a/src/include/replication/snapbuild_internal.h b/src/include/replication/snapbuild_internal.h
index 5df2ae4423d..1e295c75076 100644
--- a/src/include/replication/snapbuild_internal.h
+++ b/src/include/replication/snapbuild_internal.h
@@ -193,4 +193,7 @@ typedef struct SnapBuildOnDisk
/* variable amount of TransactionIds follows */
} SnapBuildOnDisk;
+extern bool SnapBuildRestoreSnapshot(SnapBuildOnDisk *ondisk, const char *path,
+ MemoryContext context, bool missing_ok);
+
#endif /* SNAPBUILD_INTERNAL_H */