From 03482265b539bfd46ce684935c4b6697217dfe21 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Tue, 1 Mar 2016 20:55:43 -0500
Subject: [PATCH 2/2] pg_visibilitymap

---
 contrib/pg_visibilitymap/Makefile                  | 19 ++++++
 contrib/pg_visibilitymap/pg_visibilitymap--1.0.sql | 46 ++++++++++++++
 contrib/pg_visibilitymap/pg_visibilitymap.c        | 70 ++++++++++++++++++++++
 contrib/pg_visibilitymap/pg_visibilitymap.control  |  5 ++
 4 files changed, 140 insertions(+)
 create mode 100644 contrib/pg_visibilitymap/Makefile
 create mode 100644 contrib/pg_visibilitymap/pg_visibilitymap--1.0.sql
 create mode 100644 contrib/pg_visibilitymap/pg_visibilitymap.c
 create mode 100644 contrib/pg_visibilitymap/pg_visibilitymap.control

diff --git a/contrib/pg_visibilitymap/Makefile b/contrib/pg_visibilitymap/Makefile
new file mode 100644
index 0000000..76cf1fa
--- /dev/null
+++ b/contrib/pg_visibilitymap/Makefile
@@ -0,0 +1,19 @@
+# contrib/pg_visibilitymap/Makefile
+
+MODULE_big = pg_visibilitymap
+OBJS = pg_visibilitymap.o $(WIN32RES)
+
+EXTENSION = pg_visibilitymap
+DATA = pg_visibilitymap--1.0.sql
+PGFILEDESC = "pg_visibilitymap - monitoring of visibility map"
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/pg_visibilitymap
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/pg_visibilitymap/pg_visibilitymap--1.0.sql b/contrib/pg_visibilitymap/pg_visibilitymap--1.0.sql
new file mode 100644
index 0000000..4817b2c
--- /dev/null
+++ b/contrib/pg_visibilitymap/pg_visibilitymap--1.0.sql
@@ -0,0 +1,46 @@
+/* contrib/pg_visibilitymap/pg_visibilitymap--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pg_visibilitymap" to load this file. \quit
+
+-- Show visibility map information.
+CREATE FUNCTION pg_visibilitymap(regclass, bigint)
+RETURNS int4
+AS 'MODULE_PATHNAME', 'pg_visibilitymap'
+LANGUAGE C STRICT;
+
+-- Show page status information.
+CREATE FUNCTION pg_page_flags(regclass, bigint)
+RETURNS int4
+AS 'MODULE_PATHNAME', 'pg_page_flags'
+LANGUAGE C STRICT;
+
+-- pg_visibilitymap shows the visibility map bits for each block in a relation
+CREATE FUNCTION
+  pg_visibilitymap(rel regclass, blkno OUT bigint, mapbits OUT int4)
+RETURNS SETOF RECORD
+AS $$
+  SELECT blkno, pg_visibilitymap($1, blkno) AS mapbits
+  FROM generate_series(0, pg_relation_size($1) / current_setting('block_size')::bigint - 1) AS blkno;
+$$
+LANGUAGE SQL;
+
+-- pg_visibility shows the visibility map bits and page-level bits for each
+-- block in a relation.  this is more expensive than pg_visibilitymap since
+-- we must read all of the pages.
+CREATE FUNCTION
+  pg_visibility(rel regclass, blkno OUT bigint, mapbits OUT int4,
+                pagebits OUT int4)
+RETURNS SETOF RECORD
+AS $$
+  SELECT blkno, pg_visibilitymap($1, blkno) AS mapbits,
+      pg_page_flags($1, blkno) AS pagebits
+  FROM generate_series(0, pg_relation_size($1) / current_setting('block_size')::bigint - 1) AS blkno;
+$$
+LANGUAGE SQL;
+
+-- Don't want these to be available to public.
+REVOKE ALL ON FUNCTION pg_visibilitymap(regclass, bigint) FROM PUBLIC;
+REVOKE ALL ON FUNCTION pg_page_flags(regclass, bigint) FROM PUBLIC;
+REVOKE ALL ON FUNCTION pg_visibilitymap(regclass) FROM PUBLIC;
+REVOKE ALL ON FUNCTION pg_visibility(regclass) FROM PUBLIC;
diff --git a/contrib/pg_visibilitymap/pg_visibilitymap.c b/contrib/pg_visibilitymap/pg_visibilitymap.c
new file mode 100644
index 0000000..9ffc7e1
--- /dev/null
+++ b/contrib/pg_visibilitymap/pg_visibilitymap.c
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_visibilitymap.c
+ *	  display contents of a visibility map and page level bits
+ *
+ *	  contrib/pg_visibilitymap/pg_visibilitymap.c
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/visibilitymap.h"
+#include "funcapi.h"
+#include "storage/bufmgr.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(pg_visibilitymap);
+PG_FUNCTION_INFO_V1(pg_page_flags);
+
+Datum
+pg_visibilitymap(PG_FUNCTION_ARGS)
+{
+	Oid			relid = PG_GETARG_OID(0);
+	int64		blkno = PG_GETARG_INT64(1);
+	int32		mapbits;
+	Relation	rel;
+	Buffer		vmbuffer = InvalidBuffer;
+
+	rel = relation_open(relid, AccessShareLock);
+
+	if (blkno < 0 || blkno > MaxBlockNumber)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("invalid block number")));
+
+	mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
+	if (vmbuffer != InvalidBuffer)
+		ReleaseBuffer(vmbuffer);
+
+	relation_close(rel, AccessShareLock);
+	PG_RETURN_INT32(mapbits);
+}
+
+Datum
+pg_page_flags(PG_FUNCTION_ARGS)
+{
+	Oid			relid = PG_GETARG_OID(0);
+	int64		blkno = PG_GETARG_INT64(1);
+	int32		pagebits;
+	Relation	rel;
+	Buffer		buffer;
+	Page		page;
+
+	rel = relation_open(relid, AccessShareLock);
+
+	if (blkno < 0 || blkno > MaxBlockNumber)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("invalid block number")));
+
+	buffer = ReadBuffer(rel, blkno);
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	page = BufferGetPage(buffer);
+	pagebits = (int32) (((PageHeader) (page))->pd_flags);
+
+	UnlockReleaseBuffer(buffer);
+	relation_close(rel, AccessShareLock);
+	PG_RETURN_INT32(pagebits);
+}
diff --git a/contrib/pg_visibilitymap/pg_visibilitymap.control b/contrib/pg_visibilitymap/pg_visibilitymap.control
new file mode 100644
index 0000000..f1686eb
--- /dev/null
+++ b/contrib/pg_visibilitymap/pg_visibilitymap.control
@@ -0,0 +1,5 @@
+# pg_visibilitymap extension
+comment = 'examine the visibility map (VM)'
+default_version = '1.0'
+module_pathname = '$libdir/pg_visibilitymap'
+relocatable = true
-- 
2.5.4 (Apple Git-61)

