Add SQL functions to monitor the directory contents of replication slots
This commit adds a set of functions able to look at the contents of various paths related to replication slots: - pg_ls_logicalsnapdir, for pg_logical/snapshots/ - pg_ls_logicalmapdir, for pg_logical/mappings/ - pg_ls_replslotdir, for pg_replslot/<slot_name>/ These are intended to be used by monitoring tools. Unlike pg_ls_dir(), execution permission can be granted to non-superusers. Roles members of pg_monitor gain have access to those functions. Bump catalog version. Author: Bharath Rupireddy Reviewed-by: Nathan Bossart, Justin Pryzby Discussion: https://postgr.es/m/CALj2ACWsfizZjMN6bzzdxOk1ADQQeSw8HhEjhmVXn_Pu+7VzLw@mail.gmail.com
This commit is contained in:
parent
b55f2b6926
commit
1922d7c6e1
|
@ -48,6 +48,27 @@ SELECT pg_drop_replication_slot('regression_slot_t');
|
|||
ERROR: replication slot "regression_slot_t" does not exist
|
||||
SELECT pg_drop_replication_slot('regression_slot_t2');
|
||||
ERROR: replication slot "regression_slot_t2" does not exist
|
||||
-- monitoring functions for slot directories
|
||||
SELECT count(*) >= 0 AS ok FROM pg_ls_logicalmapdir();
|
||||
ok
|
||||
----
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT count(*) >= 0 AS ok FROM pg_ls_logicalsnapdir();
|
||||
ok
|
||||
----
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT count(*) >= 0 AS ok FROM pg_ls_replslotdir('regression_slot_p');
|
||||
ok
|
||||
----
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT count(*) >= 0 AS ok FROM pg_ls_replslotdir('not_existing_slot'); -- fails
|
||||
ERROR: replication slot "not_existing_slot" does not exist
|
||||
-- permanent slot has survived
|
||||
SELECT pg_drop_replication_slot('regression_slot_p');
|
||||
pg_drop_replication_slot
|
||||
|
|
|
@ -28,6 +28,12 @@ end';
|
|||
SELECT pg_drop_replication_slot('regression_slot_t');
|
||||
SELECT pg_drop_replication_slot('regression_slot_t2');
|
||||
|
||||
-- monitoring functions for slot directories
|
||||
SELECT count(*) >= 0 AS ok FROM pg_ls_logicalmapdir();
|
||||
SELECT count(*) >= 0 AS ok FROM pg_ls_logicalsnapdir();
|
||||
SELECT count(*) >= 0 AS ok FROM pg_ls_replslotdir('regression_slot_p');
|
||||
SELECT count(*) >= 0 AS ok FROM pg_ls_replslotdir('not_existing_slot'); -- fails
|
||||
|
||||
-- permanent slot has survived
|
||||
SELECT pg_drop_replication_slot('regression_slot_p');
|
||||
|
||||
|
|
|
@ -27417,6 +27417,79 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8');
|
|||
can be granted EXECUTE to run the function.
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>pg_ls_logicalsnapdir</primary>
|
||||
</indexterm>
|
||||
<function>pg_ls_logicalsnapdir</function> ()
|
||||
<returnvalue>setof record</returnvalue>
|
||||
( <parameter>name</parameter> <type>text</type>,
|
||||
<parameter>size</parameter> <type>bigint</type>,
|
||||
<parameter>modification</parameter> <type>timestamp with time zone</type> )
|
||||
</para>
|
||||
<para>
|
||||
Returns the name, size, and last modification time (mtime) of each
|
||||
ordinary file in the server's <filename>pg_logical/snapshots</filename>
|
||||
directory. Filenames beginning with a dot, directories, and other
|
||||
special files are excluded.
|
||||
</para>
|
||||
<para>
|
||||
This function is restricted to superusers and members of
|
||||
the <literal>pg_monitor</literal> role by default, but other users can
|
||||
be granted EXECUTE to run the function.
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>pg_ls_logicalmapdir</primary>
|
||||
</indexterm>
|
||||
<function>pg_ls_logicalmapdir</function> ()
|
||||
<returnvalue>setof record</returnvalue>
|
||||
( <parameter>name</parameter> <type>text</type>,
|
||||
<parameter>size</parameter> <type>bigint</type>,
|
||||
<parameter>modification</parameter> <type>timestamp with time zone</type> )
|
||||
</para>
|
||||
<para>
|
||||
Returns the name, size, and last modification time (mtime) of each
|
||||
ordinary file in the server's <filename>pg_logical/mappings</filename>
|
||||
directory. Filenames beginning with a dot, directories, and other
|
||||
special files are excluded.
|
||||
</para>
|
||||
<para>
|
||||
This function is restricted to superusers and members of
|
||||
the <literal>pg_monitor</literal> role by default, but other users can
|
||||
be granted EXECUTE to run the function.
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>pg_ls_replslotdir</primary>
|
||||
</indexterm>
|
||||
<function>pg_ls_replslotdir</function> ( <parameter>slot_name</parameter> <type>text</type> )
|
||||
<returnvalue>setof record</returnvalue>
|
||||
( <parameter>name</parameter> <type>text</type>,
|
||||
<parameter>size</parameter> <type>bigint</type>,
|
||||
<parameter>modification</parameter> <type>timestamp with time zone</type> )
|
||||
</para>
|
||||
<para>
|
||||
Returns the name, size, and last modification time (mtime) of each
|
||||
ordinary file in the server's <filename>pg_replslot/slot_name</filename>
|
||||
directory, where <parameter>slot_name</parameter> is the name of the
|
||||
replication slot provided as input of the function. Filenames beginning
|
||||
with a dot, directories, and other special files are excluded.
|
||||
</para>
|
||||
<para>
|
||||
This function is restricted to superusers and members of
|
||||
the <literal>pg_monitor</literal> role by default, but other users can
|
||||
be granted EXECUTE to run the function.
|
||||
</para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
|
|
@ -701,6 +701,12 @@ REVOKE EXECUTE ON FUNCTION pg_ls_dir(text,boolean,boolean) FROM public;
|
|||
|
||||
REVOKE EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer) FROM PUBLIC;
|
||||
|
||||
REVOKE EXECUTE ON FUNCTION pg_ls_logicalsnapdir() FROM PUBLIC;
|
||||
|
||||
REVOKE EXECUTE ON FUNCTION pg_ls_logicalmapdir() FROM PUBLIC;
|
||||
|
||||
REVOKE EXECUTE ON FUNCTION pg_ls_replslotdir(text) FROM PUBLIC;
|
||||
|
||||
--
|
||||
-- We also set up some things as accessible to standard roles.
|
||||
--
|
||||
|
@ -715,6 +721,12 @@ GRANT EXECUTE ON FUNCTION pg_ls_tmpdir() TO pg_monitor;
|
|||
|
||||
GRANT EXECUTE ON FUNCTION pg_ls_tmpdir(oid) TO pg_monitor;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION pg_ls_logicalsnapdir() TO pg_monitor;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION pg_ls_logicalmapdir() TO pg_monitor;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION pg_ls_replslotdir(text) TO pg_monitor;
|
||||
|
||||
GRANT pg_read_all_settings TO pg_monitor;
|
||||
|
||||
GRANT pg_read_all_stats TO pg_monitor;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "mb/pg_wchar.h"
|
||||
#include "miscadmin.h"
|
||||
#include "postmaster/syslogger.h"
|
||||
#include "replication/slot.h"
|
||||
#include "storage/fd.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
|
@ -720,3 +721,46 @@ pg_ls_archive_statusdir(PG_FUNCTION_ARGS)
|
|||
{
|
||||
return pg_ls_dir_files(fcinfo, XLOGDIR "/archive_status", true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to return the list of files in the pg_logical/snapshots directory.
|
||||
*/
|
||||
Datum
|
||||
pg_ls_logicalsnapdir(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return pg_ls_dir_files(fcinfo, "pg_logical/snapshots", false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to return the list of files in the pg_logical/mappings directory.
|
||||
*/
|
||||
Datum
|
||||
pg_ls_logicalmapdir(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return pg_ls_dir_files(fcinfo, "pg_logical/mappings", false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to return the list of files in the pg_replslot/<replication_slot>
|
||||
* directory.
|
||||
*/
|
||||
Datum
|
||||
pg_ls_replslotdir(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *slotname_t;
|
||||
char path[MAXPGPATH];
|
||||
char *slotname;
|
||||
|
||||
slotname_t = PG_GETARG_TEXT_PP(0);
|
||||
|
||||
slotname = text_to_cstring(slotname_t);
|
||||
|
||||
if (!SearchNamedReplicationSlot(slotname, true))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("replication slot \"%s\" does not exist",
|
||||
slotname)));
|
||||
|
||||
snprintf(path, sizeof(path), "pg_replslot/%s", slotname);
|
||||
return pg_ls_dir_files(fcinfo, path, false);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,6 @@
|
|||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 202111171
|
||||
#define CATALOG_VERSION_NO 202111231
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11623,6 +11623,28 @@
|
|||
proallargtypes => '{oid,text,int8,timestamptz}', proargmodes => '{i,o,o,o}',
|
||||
proargnames => '{tablespace,name,size,modification}',
|
||||
prosrc => 'pg_ls_tmpdir_1arg' },
|
||||
{ oid => '9858',
|
||||
descr => 'list of files in the pg_logical/snapshots directory',
|
||||
proname => 'pg_ls_logicalsnapdir', procost => '10', prorows => '20',
|
||||
proretset => 't', provolatile => 'v', prorettype => 'record',
|
||||
proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
|
||||
proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
|
||||
prosrc => 'pg_ls_logicalsnapdir' },
|
||||
{ oid => '9859',
|
||||
descr => 'list of files in the pg_logical/mappings directory',
|
||||
proname => 'pg_ls_logicalmapdir', procost => '10', prorows => '20',
|
||||
proretset => 't', provolatile => 'v', prorettype => 'record',
|
||||
proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
|
||||
proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
|
||||
prosrc => 'pg_ls_logicalmapdir' },
|
||||
{ oid => '9860',
|
||||
descr => 'list of files in the pg_replslot/slot_name directory',
|
||||
proname => 'pg_ls_replslotdir', procost => '10', prorows => '20',
|
||||
proretset => 't', provolatile => 'v', prorettype => 'record',
|
||||
proargtypes => 'text', proallargtypes => '{text,text,int8,timestamptz}',
|
||||
proargmodes => '{i,o,o,o}',
|
||||
proargnames => '{slot_name,name,size,modification}',
|
||||
prosrc => 'pg_ls_replslotdir' },
|
||||
|
||||
# hash partitioning constraint function
|
||||
{ oid => '5028', descr => 'hash partition CHECK constraint',
|
||||
|
|
|
@ -243,6 +243,56 @@ select count(*) > 0 from
|
|||
t
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- Test replication slot directory functions
|
||||
--
|
||||
CREATE ROLE regress_slot_dir_funcs;
|
||||
-- Not available by default.
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_logicalsnapdir()', 'EXECUTE');
|
||||
has_function_privilege
|
||||
------------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_logicalmapdir()', 'EXECUTE');
|
||||
has_function_privilege
|
||||
------------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_replslotdir(text)', 'EXECUTE');
|
||||
has_function_privilege
|
||||
------------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
GRANT pg_monitor TO regress_slot_dir_funcs;
|
||||
-- Role is now part of pg_monitor, so these are available.
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_logicalsnapdir()', 'EXECUTE');
|
||||
has_function_privilege
|
||||
------------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_logicalmapdir()', 'EXECUTE');
|
||||
has_function_privilege
|
||||
------------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_replslotdir(text)', 'EXECUTE');
|
||||
has_function_privilege
|
||||
------------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
DROP ROLE regress_slot_dir_funcs;
|
||||
--
|
||||
-- Test adding a support function to a subject function
|
||||
--
|
||||
|
|
|
@ -91,6 +91,27 @@ select count(*) > 0 from
|
|||
where spcname = 'pg_default') pts
|
||||
join pg_database db on pts.pts = db.oid;
|
||||
|
||||
--
|
||||
-- Test replication slot directory functions
|
||||
--
|
||||
CREATE ROLE regress_slot_dir_funcs;
|
||||
-- Not available by default.
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_logicalsnapdir()', 'EXECUTE');
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_logicalmapdir()', 'EXECUTE');
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_replslotdir(text)', 'EXECUTE');
|
||||
GRANT pg_monitor TO regress_slot_dir_funcs;
|
||||
-- Role is now part of pg_monitor, so these are available.
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_logicalsnapdir()', 'EXECUTE');
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_logicalmapdir()', 'EXECUTE');
|
||||
SELECT has_function_privilege('regress_slot_dir_funcs',
|
||||
'pg_ls_replslotdir(text)', 'EXECUTE');
|
||||
DROP ROLE regress_slot_dir_funcs;
|
||||
|
||||
--
|
||||
-- Test adding a support function to a subject function
|
||||
--
|
||||
|
|
Loading…
Reference in New Issue