diff --git a/Makefile b/Makefile index 77a28c0..84ffa85 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -short_ver = 1.1.11 -last_ver = 1.1.10 +short_ver = 1.1.12 +last_ver = 1.1.11 long_ver = $(shell git describe --long 2>/dev/null || echo $(short_ver)-0-unknown-g`git describe --always`) generated = aiven_extras.control \ sql/aiven_extras--$(short_ver).sql \ @@ -11,7 +11,7 @@ RPM_MINOR_VERSION_SUFFIX ?= # Extension packaging EXTENSION = aiven_extras MODULE_big = aiven_extras -OBJS = src/standby_slots.o +OBJS = src/aiven_extras.o PG_CONFIG ?= pg_config DATA = $(filter-out $(generated),$(wildcard sql/*--*.sql)) DATA_built = $(generated) diff --git a/sql/aiven_extras--1.1.10--1.1.11.sql b/sql/aiven_extras--1.1.10--1.1.11.sql new file mode 100644 index 0000000..e2f08fc --- /dev/null +++ b/sql/aiven_extras--1.1.10--1.1.11.sql @@ -0,0 +1 @@ +-- NOOP diff --git a/sql/aiven_extras.sql b/sql/aiven_extras.sql index f346b87..e4449f4 100644 --- a/sql/aiven_extras.sql +++ b/sql/aiven_extras.sql @@ -580,3 +580,9 @@ CREATE FUNCTION aiven_extras.pg_create_logical_replication_slot_on_standby( OUT slot_name name, OUT lsn pg_lsn) AS 'MODULE_PATHNAME', 'standby_slot_create' LANGUAGE C; + +DROP FUNCTION IF EXISTS aiven_extras.aiven_truncate_freespace_map(regclass); +CREATE FUNCTION aiven_extras.truncate_freespace_map(regclass) +RETURNS void +AS 'MODULE_PATHNAME', 'aiven_truncate_freespace_map' +LANGUAGE C; diff --git a/src/standby_slots.c b/src/aiven_extras.c similarity index 69% rename from src/standby_slots.c rename to src/aiven_extras.c index f056948..630ec53 100644 --- a/src/standby_slots.c +++ b/src/aiven_extras.c @@ -2,19 +2,28 @@ #include "fmgr.h" #include "funcapi.h" #include "miscadmin.h" +#include "storage/freespace.h" +#include "storage/smgr.h" +#if PG_VERSION_NUM >= 160000 +#include "access/relation.h" +#endif +#include "access/xloginsert.h" #include "access/xlogreader.h" #include "access/xlogutils.h" #include "replication/logical.h" +#include "catalog/storage_xlog.h" #include "replication/slot.h" #include "replication/walreceiver.h" #if PG_VERSION_NUM >= 120000 && PG_VERSION_NUM < 130000 #include "replication/logicalfuncs.h" #endif #include "utils/pg_lsn.h" +#include "utils/rel.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(standby_slot_create); +PG_FUNCTION_INFO_V1(aiven_truncate_freespace_map); Datum standby_slot_create(PG_FUNCTION_ARGS) { @@ -120,3 +129,63 @@ standby_slot_create(PG_FUNCTION_ARGS) ReplicationSlotRelease(); PG_RETURN_DATUM(result); } + + + +#if PG_VERSION_NUM >= 160000 +Datum +aiven_truncate_freespace_map(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + Relation rel; + ForkNumber fork; + BlockNumber block; + + rel = relation_open(relid, AccessExclusiveLock); + + /* Only some relkinds have a freespacemap map */ + if (!RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind)) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("relation \"%s\" is of wrong relation kind", + RelationGetRelationName(rel)), + errdetail_relkind_not_supported(rel->rd_rel->relkind))); + + + /* Forcibly reset cached file size */ + RelationGetSmgr(rel)->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber; + + /* Just pretend we're going to wipeout the whole rel */ + block = FreeSpaceMapPrepareTruncateRel(rel, 0); + + if (BlockNumberIsValid(block)) + { + fork = FSM_FORKNUM; + smgrtruncate(RelationGetSmgr(rel), &fork, 1, &block); + } + + if (RelationNeedsWAL(rel)) + { + xl_smgr_truncate xlrec; + + xlrec.blkno = 0; + xlrec.rlocator = rel->rd_locator; + xlrec.flags = SMGR_TRUNCATE_FSM; + + XLogBeginInsert(); + XLogRegisterData((char *) &xlrec, sizeof(xlrec)); + + XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE); + } + + relation_close(rel, AccessExclusiveLock); + + PG_RETURN_VOID(); +} +#else +Datum +aiven_truncate_freespace_map(PG_FUNCTION_ARGS) +{ + elog(ERROR, "aiven_truncate_freespace_map is not supported on this version."); +} +#endif