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