Commit fef2bcdc authored by Peter Eisentraut's avatar Peter Eisentraut

pageinspect: Add page_checksum function

Author: Tomas Vondra <tomas.vondra@2ndquadrant.com>
Reviewed-by: default avatarAshutosh Sharma <ashu.coek88@gmail.com>
parent 64ae420b
...@@ -49,6 +49,12 @@ SELECT pagesize, version FROM page_header(get_raw_page('test1', 0)); ...@@ -49,6 +49,12 @@ SELECT pagesize, version FROM page_header(get_raw_page('test1', 0));
8192 | 4 8192 | 4
(1 row) (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) SELECT tuple_data_split('test1'::regclass, t_data, t_infomask, t_infomask2, t_bits)
FROM heap_page_items(get_raw_page('test1', 0)); FROM heap_page_items(get_raw_page('test1', 0));
tuple_data_split tuple_data_split
......
...@@ -75,3 +75,11 @@ CREATE FUNCTION hash_metapage_info(IN page bytea, ...@@ -75,3 +75,11 @@ CREATE FUNCTION hash_metapage_info(IN page bytea,
OUT mapp int8[]) OUT mapp int8[])
AS 'MODULE_PATHNAME', 'hash_metapage_info' AS 'MODULE_PATHNAME', 'hash_metapage_info'
LANGUAGE C STRICT PARALLEL SAFE; 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;
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "funcapi.h" #include "funcapi.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/checksum.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/pg_lsn.h" #include "utils/pg_lsn.h"
#include "utils/rel.h" #include "utils/rel.h"
...@@ -280,3 +281,39 @@ page_header(PG_FUNCTION_ARGS) ...@@ -280,3 +281,39 @@ page_header(PG_FUNCTION_ARGS)
PG_RETURN_DATUM(result); 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));
}
...@@ -24,6 +24,8 @@ SELECT get_raw_page('test1', 0) = get_raw_page('test1', 'main', 0); ...@@ -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 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) SELECT tuple_data_split('test1'::regclass, t_data, t_infomask, t_infomask2, t_bits)
FROM heap_page_items(get_raw_page('test1', 0)); FROM heap_page_items(get_raw_page('test1', 0));
......
...@@ -73,12 +73,55 @@ ...@@ -73,12 +73,55 @@
test=# SELECT * FROM page_header(get_raw_page('pg_class', 0)); test=# SELECT * FROM page_header(get_raw_page('pg_class', 0));
lsn | checksum | flags | lower | upper | special | pagesize | version | prune_xid 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> </screen>
The returned columns correspond to the fields in the The returned columns correspond to the fields in the
<structname>PageHeaderData</> struct. <structname>PageHeaderData</> struct.
See <filename>src/include/storage/bufpage.h</> for details. 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> </listitem>
</varlistentry> </varlistentry>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment