diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/replication/logical/snapbuild.c | 99 | ||||
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 6 | ||||
-rw-r--r-- | src/include/replication/snapbuild.h | 4 | ||||
-rw-r--r-- | src/include/replication/snapbuild_internal.h | 3 |
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 */ |