diff options
author | Heikki Linnakangas | 2008-09-30 10:52:14 +0000 |
---|---|---|
committer | Heikki Linnakangas | 2008-09-30 10:52:14 +0000 |
commit | 15c121b3ed7eb2f290e19533e41ccca734d23574 (patch) | |
tree | b60226d720f87b82b5b44647e3d3031081cdfb07 /contrib | |
parent | 2dbc0ca937f8ba9c76866a99fd04866232acea95 (diff) |
Rewrite the FSM. Instead of relying on a fixed-size shared memory segment, the
free space information is stored in a dedicated FSM relation fork, with each
relation (except for hash indexes; they don't use FSM).
This eliminates the max_fsm_relations and max_fsm_pages GUC options; remove any
trace of them from the backend, initdb, and documentation.
Rewrite contrib/pg_freespacemap to match the new FSM implementation. Also
introduce a new variant of the get_raw_page(regclass, int4, int4) function in
contrib/pageinspect that let's you to return pages from any relation fork, and
a new fsm_page_contents() function to inspect the new FSM pages.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/pageinspect/Makefile | 4 | ||||
-rw-r--r-- | contrib/pageinspect/fsmfuncs.c | 61 | ||||
-rw-r--r-- | contrib/pageinspect/pageinspect.sql.in | 17 | ||||
-rw-r--r-- | contrib/pageinspect/rawpage.c | 12 | ||||
-rw-r--r-- | contrib/pg_freespacemap/pg_freespacemap.sql.in | 48 |
5 files changed, 102 insertions, 40 deletions
diff --git a/contrib/pageinspect/Makefile b/contrib/pageinspect/Makefile index 63da705215d..3a6b729c174 100644 --- a/contrib/pageinspect/Makefile +++ b/contrib/pageinspect/Makefile @@ -2,12 +2,12 @@ # # pageinspect Makefile # -# $PostgreSQL: pgsql/contrib/pageinspect/Makefile,v 1.3 2007/11/10 23:59:51 momjian Exp $ +# $PostgreSQL: pgsql/contrib/pageinspect/Makefile,v 1.4 2008/09/30 10:52:09 heikki Exp $ # #------------------------------------------------------------------------- MODULE_big = pageinspect -OBJS = rawpage.o heapfuncs.o btreefuncs.o +OBJS = rawpage.o heapfuncs.o btreefuncs.o fsmfuncs.o DATA_built = pageinspect.sql DATA = uninstall_pageinspect.sql diff --git a/contrib/pageinspect/fsmfuncs.c b/contrib/pageinspect/fsmfuncs.c new file mode 100644 index 00000000000..fb522e5ff5f --- /dev/null +++ b/contrib/pageinspect/fsmfuncs.c @@ -0,0 +1,61 @@ +/*------------------------------------------------------------------------- + * + * fsmfuncs.c + * Functions to investigate FSM pages + * + * These functions are restricted to superusers for the fear of introducing + * security holes if the input checking isn't as water-tight as it should. + * You'd need to be superuser to obtain a raw page image anyway, so + * there's hardly any use case for using these without superuser-rights + * anyway. + * + * Copyright (c) 2007-2008, PostgreSQL Global Development Group + * + * IDENTIFICATION + * $PostgreSQL: pgsql/contrib/pageinspect/fsmfuncs.c,v 1.1 2008/09/30 10:52:09 heikki Exp $ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "lib/stringinfo.h" +#include "storage/fsm_internals.h" +#include "utils/builtins.h" +#include "miscadmin.h" +#include "funcapi.h" + +Datum fsm_page_contents(PG_FUNCTION_ARGS); + +/* + * Dumps the contents of a FSM page. + */ +PG_FUNCTION_INFO_V1(fsm_page_contents); + +Datum +fsm_page_contents(PG_FUNCTION_ARGS) +{ + bytea *raw_page = PG_GETARG_BYTEA_P(0); + int raw_page_size; + StringInfoData sinfo; + FSMPage fsmpage; + int i; + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to use raw page functions")))); + + raw_page_size = VARSIZE(raw_page) - VARHDRSZ; + fsmpage = (FSMPage) PageGetContents(VARDATA(raw_page)); + + initStringInfo(&sinfo); + + for(i=0; i < NodesPerPage; i++) + { + if (fsmpage->fp_nodes[i] != 0) + appendStringInfo(&sinfo, "%d: %d\n", i, fsmpage->fp_nodes[i]); + } + appendStringInfo(&sinfo, "fp_next_slot: %d\n", fsmpage->fp_next_slot); + + PG_RETURN_TEXT_P(cstring_to_text(sinfo.data)); +} diff --git a/contrib/pageinspect/pageinspect.sql.in b/contrib/pageinspect/pageinspect.sql.in index 1af59f70f46..49fea9eb51f 100644 --- a/contrib/pageinspect/pageinspect.sql.in +++ b/contrib/pageinspect/pageinspect.sql.in @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/contrib/pageinspect/pageinspect.sql.in,v 1.4 2007/11/13 04:24:28 momjian Exp $ */ +/* $PostgreSQL: pgsql/contrib/pageinspect/pageinspect.sql.in,v 1.5 2008/09/30 10:52:09 heikki Exp $ */ -- Adjust this setting to control where the objects get created. SET search_path = public; @@ -6,11 +6,16 @@ SET search_path = public; -- -- get_raw_page() -- -CREATE OR REPLACE FUNCTION get_raw_page(text, int4) +CREATE OR REPLACE FUNCTION get_raw_page(text, int4, int4) RETURNS bytea AS 'MODULE_PATHNAME', 'get_raw_page' LANGUAGE C STRICT; +CREATE OR REPLACE FUNCTION get_raw_page(text, int4) +RETURNS bytea +AS $$ SELECT get_raw_page($1, 0, $2); $$ +LANGUAGE SQL STRICT; + -- -- page_header() -- @@ -92,3 +97,11 @@ CREATE OR REPLACE FUNCTION bt_page_items(IN relname text, IN blkno int4, RETURNS SETOF record AS 'MODULE_PATHNAME', 'bt_page_items' LANGUAGE C STRICT; + +-- +-- fsm_page_contents() +-- +CREATE OR REPLACE FUNCTION fsm_page_contents(IN page bytea) +RETURNS text +AS 'MODULE_PATHNAME', 'fsm_page_contents' +LANGUAGE C STRICT; diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c index 0bc6bdc0174..51c6ee179f4 100644 --- a/contrib/pageinspect/rawpage.c +++ b/contrib/pageinspect/rawpage.c @@ -8,7 +8,7 @@ * Copyright (c) 2007-2008, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.6 2008/05/12 00:00:43 alvherre Exp $ + * $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.7 2008/09/30 10:52:09 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -41,7 +41,8 @@ Datum get_raw_page(PG_FUNCTION_ARGS) { text *relname = PG_GETARG_TEXT_P(0); - uint32 blkno = PG_GETARG_UINT32(1); + uint32 forknum = PG_GETARG_UINT32(1); + uint32 blkno = PG_GETARG_UINT32(2); Relation rel; RangeVar *relrv; @@ -54,6 +55,11 @@ get_raw_page(PG_FUNCTION_ARGS) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw functions")))); + if (forknum > MAX_FORKNUM) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid fork number"))); + relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); @@ -80,7 +86,7 @@ get_raw_page(PG_FUNCTION_ARGS) /* Take a verbatim copy of the page */ - buf = ReadBuffer(rel, blkno); + buf = ReadBufferWithFork(rel, forknum, blkno); LockBuffer(buf, BUFFER_LOCK_SHARE); memcpy(raw_page_data, BufferGetPage(buf), BLCKSZ); diff --git a/contrib/pg_freespacemap/pg_freespacemap.sql.in b/contrib/pg_freespacemap/pg_freespacemap.sql.in index e950d9a1128..0ab5e1d1eae 100644 --- a/contrib/pg_freespacemap/pg_freespacemap.sql.in +++ b/contrib/pg_freespacemap/pg_freespacemap.sql.in @@ -1,44 +1,26 @@ -/* $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.sql.in,v 1.8 2007/11/13 04:24:28 momjian Exp $ */ +/* $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.sql.in,v 1.9 2008/09/30 10:52:09 heikki Exp $ */ -- Adjust this setting to control where the objects get created. SET search_path = public; --- Register the functions. -CREATE OR REPLACE FUNCTION pg_freespacemap_pages() -RETURNS SETOF RECORD -AS 'MODULE_PATHNAME', 'pg_freespacemap_pages' +-- Register the C function. +CREATE OR REPLACE FUNCTION pg_freespace(regclass, int4) +RETURNS int2 +AS 'MODULE_PATHNAME', 'pg_freespace' LANGUAGE C; -CREATE OR REPLACE FUNCTION pg_freespacemap_relations() +-- pg_freespace shows the recorded space avail at each block in a relation +CREATE OR REPLACE FUNCTION + pg_freespace(rel regclass, blkno OUT int4, avail OUT int2) RETURNS SETOF RECORD -AS 'MODULE_PATHNAME', 'pg_freespacemap_relations' -LANGUAGE C; +AS $$ + SELECT blkno::int4, pg_freespace($1, blkno::int4) AS avail + FROM generate_series(0, pg_relation_size($1) / current_setting('block_size')::bigint - 1) AS blkno; +$$ +LANGUAGE SQL; --- Create views for convenient access. -CREATE VIEW pg_freespacemap_pages AS - SELECT P.* FROM pg_freespacemap_pages() AS P - (reltablespace oid, - reldatabase oid, - relfilenode oid, - relblocknumber bigint, - bytes integer); - -CREATE VIEW pg_freespacemap_relations AS - SELECT P.* FROM pg_freespacemap_relations() AS P - (reltablespace oid, - reldatabase oid, - relfilenode oid, - avgrequest integer, - interestingpages integer, - storedpages integer, - nextpage integer); - - -- Don't want these to be available to public. -REVOKE ALL ON FUNCTION pg_freespacemap_pages() FROM PUBLIC; -REVOKE ALL ON pg_freespacemap_pages FROM PUBLIC; - -REVOKE ALL ON FUNCTION pg_freespacemap_relations() FROM PUBLIC; -REVOKE ALL ON pg_freespacemap_relations FROM PUBLIC; +REVOKE ALL ON FUNCTION pg_freespace(regclass, int4) FROM PUBLIC; +REVOKE ALL ON FUNCTION pg_freespace(regclass) FROM PUBLIC; |