]> granicus.if.org Git - postgresql/commitdiff
pageinspect: Add page_checksum function
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 17 Mar 2017 13:49:10 +0000 (09:49 -0400)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 17 Mar 2017 14:55:17 +0000 (10:55 -0400)
Author: Tomas Vondra <tomas.vondra@2ndquadrant.com>
Reviewed-by: Ashutosh Sharma <ashu.coek88@gmail.com>
contrib/pageinspect/expected/page.out
contrib/pageinspect/pageinspect--1.5--1.6.sql
contrib/pageinspect/rawpage.c
contrib/pageinspect/sql/page.sql
doc/src/sgml/pageinspect.sgml

index 08599af774d0157c78d2e5593ef87dc4dea5ea52..8e15947a8187326351b2684aae3b362e319660d2 100644 (file)
@@ -49,6 +49,12 @@ SELECT pagesize, version FROM page_header(get_raw_page('test1', 0));
      8192 |       4
 (1 row)
 
+SELECT page_checksum(get_raw_page('test1', 0), 0) IS NOT NULL AS silly_checksum_test;
+ silly_checksum_test 
+---------------------
+ t
+(1 row)
+
 SELECT tuple_data_split('test1'::regclass, t_data, t_infomask, t_infomask2, t_bits)
     FROM heap_page_items(get_raw_page('test1', 0));
        tuple_data_split        
index ac3956882c94c64c7aae36b8c75d9167234b1ac3..6ac2a8011d80a1af6e178029685adcdf634d3be2 100644 (file)
@@ -75,3 +75,11 @@ CREATE FUNCTION hash_metapage_info(IN page bytea,
     OUT mapp int8[])
 AS 'MODULE_PATHNAME', 'hash_metapage_info'
 LANGUAGE C STRICT PARALLEL SAFE;
+
+--
+-- page_checksum()
+--
+CREATE FUNCTION page_checksum(IN page bytea, IN blkno int4)
+RETURNS smallint
+AS 'MODULE_PATHNAME', 'page_checksum'
+LANGUAGE C STRICT PARALLEL SAFE;
index a5def917511cd5ce78dc2c92ad6ab0aeb3cdf298..631e435a939c2a56c30ea3d7ac28bd623e69c681 100644 (file)
@@ -24,6 +24,7 @@
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
+#include "storage/checksum.h"
 #include "utils/builtins.h"
 #include "utils/pg_lsn.h"
 #include "utils/rel.h"
@@ -280,3 +281,39 @@ page_header(PG_FUNCTION_ARGS)
 
        PG_RETURN_DATUM(result);
 }
+
+/*
+ * page_checksum
+ *
+ * Compute checksum of a raw page
+ */
+
+PG_FUNCTION_INFO_V1(page_checksum);
+
+Datum
+page_checksum(PG_FUNCTION_ARGS)
+{
+       bytea      *raw_page = PG_GETARG_BYTEA_P(0);
+       uint32          blkno = PG_GETARG_INT32(1);
+       int                     raw_page_size;
+       PageHeader      page;
+
+       if (!superuser())
+               ereport(ERROR,
+                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                                (errmsg("must be superuser to use raw page functions"))));
+
+       raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
+
+       /*
+        * Check that the supplied page is of the right size.
+        */
+       if (raw_page_size != BLCKSZ)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("incorrect size of input page (%d bytes)", raw_page_size)));
+
+       page = (PageHeader) VARDATA(raw_page);
+
+       PG_RETURN_INT16(pg_checksum_page((char *)page, blkno));
+}
index 53e9f8022d437772840a65bdd8d7237a597fb9b0..493ca9b211d38db0105dbca6a3f28361c382a224 100644 (file)
@@ -24,6 +24,8 @@ SELECT get_raw_page('test1', 0) = get_raw_page('test1', 'main', 0);
 
 SELECT pagesize, version FROM page_header(get_raw_page('test1', 0));
 
+SELECT page_checksum(get_raw_page('test1', 0), 0) IS NOT NULL AS silly_checksum_test;
+
 SELECT tuple_data_split('test1'::regclass, t_data, t_infomask, t_infomask2, t_bits)
     FROM heap_page_items(get_raw_page('test1', 0));
 
index 5e6712f9cdee7c4943a64157b97bdc9423c20df9..9f41bb21eb9f22006cff40d60913655423ecc6bb 100644 (file)
 test=# SELECT * FROM page_header(get_raw_page('pg_class', 0));
     lsn    | checksum | flags  | lower | upper | special | pagesize | version | prune_xid
 -----------+----------+--------+-------+-------+---------+----------+---------+-----------
- 0/24A1B50 |        1 |      1 |   232 |   368 |    8192 |     8192 |       4 |         0
+ 0/24A1B50 |        0 |      1 |   232 |   368 |    8192 |     8192 |       4 |         0
 </screen>
       The returned columns correspond to the fields in the
       <structname>PageHeaderData</> struct.
       See <filename>src/include/storage/bufpage.h</> for details.
-    </para>
+     </para>
+
+     <para>
+      The <structfield>checksum</structfield> field is the checksum stored in
+      the page, which might be incorrect if the page is somehow corrupted.  If
+      data checksums are not enabled for this instance, then the value stored
+      is meaningless.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>
+     <function>page_checksum(page bytea, blkno int4) returns smallint</function>
+     <indexterm>
+      <primary>page_checksum</primary>
+     </indexterm>
+    </term>
+
+    <listitem>
+     <para>
+      <function>page_checksum</function> computes the checksum for the page, as if
+      it was located at the given block.
+     </para>
+
+     <para>
+      A page image obtained with <function>get_raw_page</function> should be
+      passed as argument.  For example:
+<screen>
+test=# SELECT page_checksum(get_raw_page('pg_class', 0), 0);
+ page_checksum
+---------------
+         13443
+</screen>
+      Note that the checksum depends on the block number, so matching block
+      numbers should be passed (except when doing esoteric debugging).
+     </para>
+
+     <para>
+      The checksum computed with this function can be compared with
+      the <structfield>checksum</structfield> result field of the
+      function <function>page_header</function>.  If data checksums are
+      enabled for this instance, then the two values should be equal.
+     </para>
     </listitem>
    </varlistentry>