mirror of
https://github.com/postgres/postgres.git
synced 2025-07-20 05:03:10 +03:00
pageinspect: Add page_checksum function
Author: Tomas Vondra <tomas.vondra@2ndquadrant.com> Reviewed-by: Ashutosh Sharma <ashu.coek88@gmail.com>
This commit is contained in:
@ -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,
|
|||||||
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 @@
|
|||||||
#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)
|
|||||||
|
|
||||||
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);
|
|||||||
|
|
||||||
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 @@
|
|||||||
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>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user