diff options
| author | Masahiko Sawada | 2024-10-15 00:22:02 +0000 |
|---|---|---|
| committer | Masahiko Sawada | 2024-10-15 00:22:02 +0000 |
| commit | 7cdfeee320e72162b62dddddee638e713c2b8680 (patch) | |
| tree | f96ad90afe907be7ec9191bc845f79628325bfc4 /src/backend | |
| parent | e2fd615ecc177493b9a961a640ec0dcc4a25755c (diff) | |
Add contrib/pg_logicalinspect.
This module provides SQL functions that allow to inspect logical
decoding components.
It currently allows to inspect the contents of serialized logical
snapshots of a running database cluster, which is useful for debugging
or educational purposes.
Author: Bertrand Drouvot
Reviewed-by: Amit Kapila, Shveta Malik, Peter Smith, Peter Eisentraut
Reviewed-by: David G. Johnston
Discussion: https://postgr.es/m/ZscuZ92uGh3wm4tW%40ip-10-97-1-34.eu-west-3.compute.internal
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/replication/logical/snapbuild.c | 99 | ||||
| -rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 6 |
2 files changed, 66 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 */ |
