summaryrefslogtreecommitdiff
path: root/contrib/pg_visibility/pg_visibility.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2016-06-17 17:37:30 -0400
committerRobert Haas <rhaas@postgresql.org>2016-06-17 17:37:30 -0400
commit71d05a2c7b82379bb1013a0e338906349c54ed85 (patch)
tree53a862320e1b58955449b7238d6f725cf1d954b4 /contrib/pg_visibility/pg_visibility.c
parent54f5c5150fa05d7ad15f8406debd5a2b394885b5 (diff)
pg_visibility: Add pg_truncate_visibility_map function.
This requires some core changes as well so that we can properly WAL-log the truncation. Specifically, it changes the format of the XLOG_SMGR_TRUNCATE WAL record, so bump XLOG_PAGE_MAGIC. Patch by me, reviewed but not fully endorsed by Andres Freund.
Diffstat (limited to 'contrib/pg_visibility/pg_visibility.c')
-rw-r--r--contrib/pg_visibility/pg_visibility.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index abb92f388a3..70340666630 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -11,10 +11,12 @@
#include "access/htup_details.h"
#include "access/visibilitymap.h"
#include "catalog/pg_type.h"
+#include "catalog/storage_xlog.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/procarray.h"
+#include "storage/smgr.h"
#include "utils/rel.h"
PG_MODULE_MAGIC;
@@ -40,6 +42,7 @@ PG_FUNCTION_INFO_V1(pg_visibility_rel);
PG_FUNCTION_INFO_V1(pg_visibility_map_summary);
PG_FUNCTION_INFO_V1(pg_check_frozen);
PG_FUNCTION_INFO_V1(pg_check_visible);
+PG_FUNCTION_INFO_V1(pg_truncate_visibility_map);
static TupleDesc pg_visibility_tupdesc(bool include_blkno, bool include_pd);
static vbits *collect_visibility_data(Oid relid, bool include_pd);
@@ -336,6 +339,75 @@ pg_check_visible(PG_FUNCTION_ARGS)
}
/*
+ * Remove the visibility map fork for a relation. If there turn out to be
+ * any bugs in the visibility map code that require rebuilding the VM, this
+ * provides users with a way to do it that is cleaner than shutting down the
+ * server and removing files by hand.
+ *
+ * This is a cut-down version of RelationTruncate.
+ */
+Datum
+pg_truncate_visibility_map(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ Relation rel;
+
+ rel = relation_open(relid, AccessExclusiveLock);
+
+ if (rel->rd_rel->relkind != RELKIND_RELATION &&
+ rel->rd_rel->relkind != RELKIND_MATVIEW &&
+ rel->rd_rel->relkind != RELKIND_TOASTVALUE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a table, materialized view, or TOAST table",
+ RelationGetRelationName(rel))));
+
+ RelationOpenSmgr(rel);
+ rel->rd_smgr->smgr_vm_nblocks = InvalidBlockNumber;
+
+ visibilitymap_truncate(rel, 0);
+
+ if (RelationNeedsWAL(rel))
+ {
+ xl_smgr_truncate xlrec;
+
+ xlrec.blkno = 0;
+ xlrec.rnode = rel->rd_node;
+ xlrec.flags = SMGR_TRUNCATE_VM;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, sizeof(xlrec));
+
+ XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
+ }
+
+ /*
+ * Release the lock right away, not at commit time.
+ *
+ * It would be a problem to release the lock prior to commit if this
+ * truncate operation sends any transactional invalidation messages. Other
+ * backends would potentially be able to lock the relation without
+ * processing them in the window of time between when we release the lock
+ * here and when we sent the messages at our eventual commit. However,
+ * we're currently only sending a non-transactional smgr invalidation,
+ * which will have been posted to shared memory immediately from within
+ * visibilitymap_truncate. Therefore, there should be no race here.
+ *
+ * The reason why it's desirable to release the lock early here is because
+ * of the possibility that someone will need to use this to blow away many
+ * visibility map forks at once. If we can't release the lock until
+ * commit time, the transaction doing this will accumulate
+ * AccessExclusiveLocks on all of those relations at the same time, which
+ * is undesirable. However, if this turns out to be unsafe we may have no
+ * choice...
+ */
+ relation_close(rel, AccessExclusiveLock);
+
+ /* Nothing to return. */
+ PG_RETURN_VOID();
+}
+
+/*
* Helper function to construct whichever TupleDesc we need for a particular
* call.
*/