From aa171d5c41ec966e42a60b39bb3c94331b347b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Fri, 1 Dec 2023 19:46:30 +0100 Subject: [PATCH] Add pg_sysconf_size, vm_free_size, drop pgsysconf pg_sysconf_size returns 'immutable' sizes from sysconf and pg: - postgres page size - system page size - total memory vm_free_size returns the current free memory on the system Remove pgsysconf datum which is obsolete, and add an SQL wrapper on top of the new functions. Users are encouraged to update their code using pgsysconf which is now deprecated and will be removed in the future. --- expected/pgfincore.out | 19 ++++++ pgfincore--1.3.1--2.0.0.sql | 47 ++++++++++++++ pgfincore--2.0.0.sql | 52 ++++++++++++---- pgfincore.c | 118 ++++++++++++++++++++++-------------- sql/pgfincore.sql | 14 +++++ 5 files changed, 194 insertions(+), 56 deletions(-) diff --git a/expected/pgfincore.out b/expected/pgfincore.out index d1425ec..a217019 100644 --- a/expected/pgfincore.out +++ b/expected/pgfincore.out @@ -92,3 +92,22 @@ select NULL || pgfincore_drawer(databit) from pgfincore('test','main',true); (1 row) +-- +-- tests pg_sysconf_size +-- +-- assume most systems have same defaults +-- it's possible to add another output file +-- to manage larger PostgreSQL and or system page size. +select pg_page_size, sys_pages_size from pg_sysconf_size(); + pg_page_size | sys_pages_size +--------------+---------------- + 8192 | 4096 +(1 row) + +-- +-- tests vm_free_pages +-- +select from vm_free_pages(); +-- +(1 row) + diff --git a/pgfincore--1.3.1--2.0.0.sql b/pgfincore--1.3.1--2.0.0.sql index e69de29..f003f3b 100644 --- a/pgfincore--1.3.1--2.0.0.sql +++ b/pgfincore--1.3.1--2.0.0.sql @@ -0,0 +1,47 @@ +CREATE FUNCTION +pg_sysconf_size( + OUT pg_page_size bigint +, OUT sys_pages_size bigint +, OUT sys_total_pages bigint +) +RETURNS record +AS '$libdir/pgfincore' +LANGUAGE C IMMUTABLE; + +COMMENT ON FUNCTION pg_sysconf_size() +IS 'Get system information: + - pg_page_size is PostgreSQL page size + - sys_pages_size is system page size + - sys_total_pages is total memory pages'; + +CREATE FUNCTION +vm_free_pages( + OUT sys_pages_free bigint +) +RETURNS bigint +AS '$libdir/pgfincore' +LANGUAGE C STABLE; + +COMMENT ON FUNCTION vm_free_pages() +IS 'Get system information: + - sys_pages_free is current number of free pages in system memory'; + +REPLACE FUNCTION +pgsysconf(OUT os_page_size bigint, + OUT os_pages_free bigint, + OUT os_total_pages bigint) +RETURNS record +AS $pgsysconf$ +SELECT + p.sys_pages_size as os_page_size +, v.sys_pages_free as os_pages_free +, p.sys_total_pages as os_total_pages +FROM pg_sysconf_size() p, vm_free_pages() v +$pgsysconf$ +LANGUAGE SQL STABLE; + +COMMENT ON FUNCTION pgsysconf() +IS 'pgsysconf is DEPRECATED, use pg_sysconf_size and vm_free_pages instead.'; + +COMMENT ON FUNCTION pgsysconf_pretty() +IS 'pgsysconf_pretty is DEPRECATED, use pg_sysconf_size and vm_free_pages with pg_size_pretty'; diff --git a/pgfincore--2.0.0.sql b/pgfincore--2.0.0.sql index 3e4643c..cc598cb 100644 --- a/pgfincore--2.0.0.sql +++ b/pgfincore--2.0.0.sql @@ -1,24 +1,52 @@ -- -- SYSCONF -- -CREATE OR REPLACE FUNCTION +CREATE FUNCTION +pg_sysconf_size( + OUT pg_page_size bigint +, OUT sys_pages_size bigint +, OUT sys_total_pages bigint +) +RETURNS record +AS '$libdir/pgfincore' +LANGUAGE C IMMUTABLE; + +COMMENT ON FUNCTION pg_sysconf_size() +IS 'Get system information: + - pg_page_size is PostgreSQL page size + - sys_pages_size is system page size + - sys_total_pages is total memory pages'; + +CREATE FUNCTION +vm_free_pages( + OUT sys_pages_free bigint +) +RETURNS bigint +AS '$libdir/pgfincore' +LANGUAGE C STABLE; + +COMMENT ON FUNCTION vm_free_pages() +IS 'Get system information: + - sys_pages_free is current number of free pages in system memory'; + +CREATE FUNCTION pgsysconf(OUT os_page_size bigint, OUT os_pages_free bigint, OUT os_total_pages bigint) RETURNS record -AS '$libdir/pgfincore' -LANGUAGE C; +AS $pgsysconf$ +SELECT + p.sys_pages_size as os_page_size +, v.sys_pages_free as os_pages_free +, p.sys_total_pages as os_total_pages +FROM pg_sysconf_size() p, vm_free_pages() v +$pgsysconf$ +LANGUAGE SQL STABLE; COMMENT ON FUNCTION pgsysconf() -IS 'Get system configuration information at run time: - - os_page_size is _SC_PAGESIZE - - os_pages_free is _SC_AVPHYS_PAGES - - os_total_pages is _SC_PHYS_PAGES - -man 3 sysconf for details'; +IS 'pgsysconf is DEPRECATED, use pg_sysconf_size and vm_free_pages instead.'; - -CREATE OR REPLACE FUNCTION +CREATE FUNCTION pgsysconf_pretty(OUT os_page_size text, OUT os_pages_free text, OUT os_total_pages text) @@ -31,7 +59,7 @@ from pgsysconf()' LANGUAGE SQL; COMMENT ON FUNCTION pgsysconf_pretty() -IS 'Pgsysconf() with human readable output'; +IS 'pgsysconf_pretty is DEPRECATED, use pg_sysconf_size and vm_free_pages with pg_size_pretty'; -- -- PGFADVISE diff --git a/pgfincore.c b/pgfincore.c index 45d0b88..2eefdaf 100644 --- a/pgfincore.c +++ b/pgfincore.c @@ -44,7 +44,16 @@ PG_MODULE_MAGIC; #endif -#define PGSYSCONF_COLS 3 +#define PG_SYSCONF_SIZE_COLS 3 +static long _sc_pagesize = 0; +static long _sc_phys_pages = 0; + +PG_FUNCTION_INFO_V1(pg_sysconf_size); +Datum pg_sysconf_size(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(vm_free_pages); +Datum vm_free_pages(PG_FUNCTION_ARGS); + #define PGFADVISE_COLS 4 #define PGFADVISE_LOADER_COLS 5 #define PGFINCORE_COLS 10 @@ -62,6 +71,7 @@ PG_MODULE_MAGIC; #else #define FINCORE_BITS 2 #endif + /* * pgfadvise_fctx structure is needed * to keep track of relation path, segment number, ... @@ -127,8 +137,6 @@ typedef struct VarBit *databit; } pgfincoreStruct; -Datum pgsysconf(PG_FUNCTION_ARGS); - Datum pgfadvise(PG_FUNCTION_ARGS); static int pgfadvise_file(char *filename, int advice, pgfadviseStruct *pgfdv); @@ -151,44 +159,6 @@ Datum pgfincore_drawer(PG_FUNCTION_ARGS); relpathbackend((rel)->rd_locator, (rel)->rd_backend, (forkname_to_number(text_to_cstring(forkName)))) #endif -/* - * pgsysconf - * just output the actual system value for - * _SC_PAGESIZE --> Page Size - * _SC_AVPHYS_PAGES --> Free page in memory - * _SC_PHYS_PAGES --> Total memory - * - */ -PG_FUNCTION_INFO_V1(pgsysconf); -Datum -pgsysconf(PG_FUNCTION_ARGS) -{ - HeapTuple tuple; - TupleDesc tupdesc; - Datum values[PGSYSCONF_COLS]; - bool nulls[PGSYSCONF_COLS]; - - /* initialize nulls array to build the tuple */ - memset(nulls, 0, sizeof(nulls)); - - /* Build a tuple descriptor for our result type */ - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) - elog(ERROR, "pgsysconf: return type must be a row type"); - - /* Page size */ - values[0] = Int64GetDatum(sysconf(_SC_PAGESIZE)); - - /* free page in memory */ - values[1] = Int64GetDatum(sysconf(_SC_AVPHYS_PAGES)); - - /* total memory */ - values[2] = Int64GetDatum(sysconf(_SC_PHYS_PAGES)); - - /* Build and return the result tuple. */ - tuple = heap_form_tuple(tupdesc, values, nulls); - PG_RETURN_DATUM( HeapTupleGetDatum(tuple) ); -} - #if defined(USE_POSIX_FADVISE) /* * pgfadvise_file @@ -209,7 +179,9 @@ pgfadvise_file(char *filename, int advice, pgfadviseStruct *pgfdv) /* * OS Page size and Free pages */ - pgfdv->pageSize = sysconf(_SC_PAGESIZE); + if (_sc_pagesize == 0) + _sc_pagesize = sysconf(_SC_PAGESIZE); + pgfdv->pageSize = _sc_pagesize; /* * Fopen and fstat file @@ -472,7 +444,9 @@ pgfadvise_loader_file(char *filename, /* * OS things : Page size */ - pgfloader->pageSize = sysconf(_SC_PAGESIZE); + if (_sc_pagesize == 0) + _sc_pagesize = sysconf(_SC_PAGESIZE); + pgfloader->pageSize = _sc_pagesize; /* * we count the action we perform @@ -717,7 +691,9 @@ pgfincore_file(char *filename, pgfincoreStruct *pgfncr) /* * OS Page size */ - pgfncr->pageSize = sysconf(_SC_PAGESIZE); + if (_sc_pagesize == 0) + _sc_pagesize = sysconf(_SC_PAGESIZE); + pgfncr->pageSize = _sc_pagesize; /* * Initialize counters @@ -1111,3 +1087,57 @@ pgfincore_drawer(PG_FUNCTION_ARGS) *r = '\0'; PG_RETURN_CSTRING(result); } + +/* + * Output the value for: + * - System page size: sysconf(_SC_PAGESIZE) + * - Total memory: sysconf(_SC_PHYS_PAGES) + * - PostgreSQL page size + * + * All of them are of interest to output size in bytes instead of blocks with + * other functions provided by pgfincore. + * We consider the values are immutable. + */ +Datum +pg_sysconf_size(PG_FUNCTION_ARGS) +{ + TupleDesc tupdesc; + Datum values[PG_SYSCONF_SIZE_COLS]; + bool nulls[PG_SYSCONF_SIZE_COLS] = {0}; + int col = 0; + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + ereport(ERROR, + errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("return type must be a row type"), + errhint("please report a bug if you get this message: function is not correctly defined")); + + if (_sc_pagesize == 0) + _sc_pagesize = sysconf(_SC_PAGESIZE); + + if (_sc_phys_pages == 0) + _sc_phys_pages = sysconf(_SC_PHYS_PAGES); + + /* PostgreSQL Page size */ + values[col++] = Int64GetDatum((off_t) BLCKSZ); + /* System Page size */ + values[col++] = Int64GetDatum(_sc_pagesize); + /* total memory */ + values[col++] = Int64GetDatum(_sc_phys_pages); + + /* Build and return the result tuple. */ + PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); +} + +/* + * vm_free_pages + * just output the actual system value for + * _SC_AVPHYS_PAGES --> Free page in memory + */ +Datum +vm_free_pages(PG_FUNCTION_ARGS) +{ + long free_pages = sysconf(_SC_AVPHYS_PAGES); + PG_RETURN_INT64(free_pages); +} diff --git a/sql/pgfincore.sql b/sql/pgfincore.sql index 3371cd1..3e43831 100644 --- a/sql/pgfincore.sql +++ b/sql/pgfincore.sql @@ -51,3 +51,17 @@ select from pgfadvise_normal('test'); -- tests drawers -- select NULL || pgfincore_drawer(databit) from pgfincore('test','main',true); + + +-- +-- tests pg_sysconf_size +-- +-- assume most systems have same defaults +-- it's possible to add another output file +-- to manage larger PostgreSQL and or system page size. +select pg_page_size, sys_pages_size from pg_sysconf_size(); + +-- +-- tests vm_free_pages +-- +select from vm_free_pages(); \ No newline at end of file