<!ENTITY pcpStopPgpool SYSTEM "pcp_stop_pgpool.sgml">
<!ENTITY pcpRecoveryNode SYSTEM "pcp_recovery_node.sgml">
<!ENTITY pcpReloadConfig SYSTEM "pcp_reload_config.sgml">
+<!ENTITY pcpLogRotate SYSTEM "pcp_log_rotate.sgml">
<!ENTITY pgMd5 SYSTEM "pg_md5.sgml">
<!ENTITY pgEnc SYSTEM "pg_enc.sgml">
<!ENTITY wdCli SYSTEM "wd_cli.sgml">
--- /dev/null
+<!--
+doc/src/sgml/ref/pcp_reload_config.sgml
+Pgpool-II documentation
+-->
+
+<refentry id="PCP-LOG-ROTATE">
+ <indexterm zone="pcp-log-rotate">
+ <primary>pcp_log_rotate</primary>
+ </indexterm>
+
+ <refmeta>
+ <refentrytitle>pcp_log_rotate</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>PCP Command</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>pcp_log_rotate</refname>
+ <refpurpose>
+ Pgpool-IIのログファイルをローテーションします</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>pcp_log_rotate</command>
+ <arg rep="repeat"><replaceable>options</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="R1-PCP-LOG-ROTATE-1">
+ <title>説明</title>
+ <para>
+ <command>pcp_log_rotate</command>
+ Pgpool-IIのログファイルをローテーションします。
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>オプション</title>
+ <para>
+ <variablelist>
+
+ <varlistentry>
+ <term><option>-s <replaceable class="parameter">scope</replaceable></option></term>
+ <term><option>--scope=<replaceable class="parameter">scope</replaceable></option></term>
+ <listitem>
+ <para>
+ コマンドの与える影響範囲を指定します。
+ </para>
+ <para>
+ サポートされているコマンドスコープは以下です。
+ デフォルトは"local"です。
+ <itemizedlist>
+ <listitem><para>c, cluster : クラスタを構成するすべてのPgpool-IIのログファイルをローテーションします。</para></listitem>
+ <listitem><para>l, local : ローカルPgpool-IIのログファイルをローテーションします。</para></listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>その他のオプション</option></term>
+ <listitem>
+ <para>
+ <xref linkend="pcp-common-options"> を参照してください。
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </refsect1>
+
+</refentry>
&pcpStopPgpool;
&pcpReloadConfig;
&pcpRecoveryNode;
+ &pcpLogRotate;
</reference>
<!ENTITY pcpPromoteNode SYSTEM "pcp_promote_node.sgml">
<!ENTITY pcpStopPgpool SYSTEM "pcp_stop_pgpool.sgml">
<!ENTITY pcpRecoveryNode SYSTEM "pcp_recovery_node.sgml">
-<!ENTITY pcpReloadConfig SYSTEM "pcp_reload_config.sgml">
+<!ENTITY pcpReloadConfig SYSTEM "pcp_reload_config.sgml">
+<!ENTITY pcpLogRotate SYSTEM "pcp_log_rotate.sgml">
<!ENTITY pgMd5 SYSTEM "pg_md5.sgml">
<!ENTITY pgEnc SYSTEM "pg_enc.sgml">
<!ENTITY wdCli SYSTEM "wd_cli.sgml">
--- /dev/null
+<!--
+doc/src/sgml/ref/pcp_logrotate_pgpool.sgml
+Pgpool-II documentation
+-->
+
+<refentry id="PCP-LOG-ROTATE">
+ <indexterm zone="pcp-log-rotate">
+ <primary>pcp_log_rotate</primary>
+ </indexterm>
+
+ <refmeta>
+ <refentrytitle>pcp_log_rotate</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>PCP Command</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>pcp_log_rotate</refname>
+ <refpurpose>
+ rotates the Pgpool-II's log file</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>pcp_log_rotate</command>
+ <arg rep="repeat"><replaceable>options</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="R1-PCP-LOG-ROTATE-1">
+ <title>Description</title>
+ <para>
+ <command>pcp_log_rotate</command>
+ rotates the Pgpool-II's log file.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+ <para>
+ <variablelist>
+
+ <varlistentry>
+ <term><option>-s <replaceable class="parameter">scope</replaceable></option></term>
+ <term><option>--scope=<replaceable class="parameter">scope</replaceable></option></term>
+ <listitem>
+ <para>
+ Specifies the breadth of a command's impact.
+ </para>
+ <para>
+ The supported command scopes are as follows (The default is "local"):
+ <itemizedlist>
+ <listitem><para>c, cluster : rotates the Pgpool-II's log files of all Pgpool-II nodes part of the cluster </para></listitem>
+ <listitem><para>l, local : rotates the Pgpool-II's log file of local Pgpool-II node only </para></listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>Other options </option></term>
+ <listitem>
+ <para>
+ See <xref linkend="pcp-common-options">.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </refsect1>
+
+</refentry>
&pcpStopPgpool;
&pcpReloadConfig;
&pcpRecoveryNode;
+ &pcpLogRotate;
</reference>
extern PCPResultInfo * pcp_process_count(PCPConnInfo * pcpConn);
extern PCPResultInfo * pcp_process_info(PCPConnInfo * pcpConn, int pid);
extern PCPResultInfo * pcp_reload_config(PCPConnInfo * pcpConn,char command_scope);
+extern PCPResultInfo * pcp_log_rotate(PCPConnInfo * pcpConn,char command_scope);
extern PCPResultInfo * pcp_detach_node(PCPConnInfo * pcpConn, int nid);
extern PCPResultInfo * pcp_detach_node_gracefully(PCPConnInfo * pcpConn, int nid);
extern void * pool_shared_memory_segment_get_chunk(size_t size);
-/* pool_main.c*/
+/* pgpool_main.c*/
extern BackendInfo * pool_get_node_info(int node_number);
extern int pool_get_node_count(void);
extern int *pool_get_process_list(int *array_size);
extern int get_next_main_node(void);
extern bool pool_acquire_follow_primary_lock(bool block, bool remote_reques);
extern void pool_release_follow_primary_lock(bool remote_reques);
+extern void pool_signal_logrotate(void);
/* strlcpy.c */
#ifndef HAVE_STRLCPY
#define WD_COMMAND_REELECT_LEADER "REELECT_LEADER"
#define WD_COMMAND_SHUTDOWN_CLUSTER "SHUTDOWN_CLUSTER"
#define WD_COMMAND_RELOAD_CONFIG_CLUSTER "RELOAD_CONFIG_CLUSTER"
+#define WD_COMMAND_LOGROTATE_CLUSTER "LOGROTATE_CLUSTER"
#define WD_COMMAND_LOCK_ON_STANDBY "APPLY_LOCK_ON_STANDBY"
process_command_complete_response(pcpConn, buf, rsize);
break;
+ case 'v': /* pcp_log_rotate */
+ if (sentMsg != 'V')
+ setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE);
+ else
+ process_command_complete_response(pcpConn, buf, rsize);
+ break;
+
case 'w':
if (sentMsg != 'W')
setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE);
return process_pcp_response(pcpConn, 'Z');
}
+PCPResultInfo *
+pcp_log_rotate(PCPConnInfo * pcpConn,char command_scope)
+{
+ int wsize;
+/*
+ * pcp packet format for pcp_log_rotate
+ * v[size][command_scope]
+ */
+ if (PCPConnectionStatus(pcpConn) != PCP_CONNECTION_OK)
+ {
+ pcp_internal_error(pcpConn, "invalid PCP connection");
+ return NULL;
+ }
+
+ pcp_write(pcpConn->pcpConn, "V", 1);
+ wsize = htonl(sizeof(int) + sizeof(char));
+ pcp_write(pcpConn->pcpConn, &wsize, sizeof(int));
+ pcp_write(pcpConn->pcpConn, &command_scope, sizeof(char));
+ if (PCPFlush(pcpConn) < 0)
+ return NULL;
+ if (pcpConn->Pfdebug)
+ fprintf(pcpConn->Pfdebug, "DEBUG: send: tos=\"Z\", len=%d\n", ntohl(wsize));
+
+ return process_pcp_response(pcpConn, 'V');
+}
/*
* Process health check response from PCP server.
{
/*
* Force rotation when both values are zero. It means the request
- * was sent by pg_rotate_logfile() or "pg_ctl logrotate".
+ * was sent by pcp_log_rotate.
*/
if (!time_based_rotation && size_rotation_for == 0)
size_rotation_for = LOG_DESTINATION_STDERR | LOG_DESTINATION_CSVLOG;
}
+/*
+ * Sending log rotation signal to logger process.
+ */
+void
+pool_signal_logrotate(void)
+{
+ if (!pool_config->logging_collector)
+ {
+ ereport(ERROR,
+ (errmsg("process log rotation request failed"),
+ errdetail("logging_collector is disabled")));
+ }
+
+ if (pgpool_logger_pid != 0)
+ {
+ ereport(DEBUG1,
+ (errmsg("sending SIGUSR1 to logger process with PID:%d to rotate log file", pgpool_logger_pid)));
+
+ if (kill(pgpool_logger_pid, SIGUSR1) != 0)
+ ereport(ERROR,
+ (errmsg("process log rotation request failed"),
+ errdetail("failed to send SIGUSR1 to logger process with PID:%d", pgpool_logger_pid)));
+ }
+ else
+ {
+ ereport(ERROR,
+ (errmsg("process log rotation request failed"),
+ errdetail("logger process PID:%d is not valid", pgpool_logger_pid)));
+ }
+}
+
/*
* -------------------------------------------------------------------------
* Subroutines for failover() begin
static void inform_node_info(PCP_CONNECTION * frontend, char *buf);
static void inform_node_count(PCP_CONNECTION * frontend);
static void process_reload_config(PCP_CONNECTION * frontend,char scope);
+static void process_log_rotate(PCP_CONNECTION * frontend,char scope);
static void inform_health_check_stats(PCP_CONNECTION *frontend, char *buf);
static void process_detach_node(PCP_CONNECTION * frontend, char *buf, char tos);
static void process_attach_node(PCP_CONNECTION * frontend, char *buf);
process_reload_config(pcp_frontend, buf[0]);
break;
+ case 'V': /* log rotate */
+ set_ps_display("PCP: processing log rotation request", false);
+ process_log_rotate(pcp_frontend, buf[0]);
+ break;
+
case 'J': /* promote node */
case 'j': /* promote node gracefully */
set_ps_display("PCP: processing promote node request", false);
(errmsg("PCP: informing node count"),
errdetail("%d node(s) found", node_count)));
}
+
static void
process_reload_config(PCP_CONNECTION * frontend, char scope)
{
do_pcp_flush(frontend);
}
+static void
+process_log_rotate(PCP_CONNECTION * frontend, char scope)
+{
+ char code[] = "CommandComplete";
+ int wsize;
+
+ if (scope == 'c' && pool_config->use_watchdog)
+ {
+ ereport(LOG,
+ (errmsg("PCP: sending command to watchdog to logrotate cluster")));
+
+ if (wd_execute_cluster_command(WD_COMMAND_LOGROTATE_CLUSTER, NULL) != COMMAND_OK)
+ ereport(ERROR,
+ (errmsg("PCP: error while processing log rotation request for cluster"),
+ errdetail("failed to propagate log rotation command through watchdog")));
+ }
+
+ pool_signal_logrotate();
+
+ pcp_write(frontend, "v", 1);
+ wsize = htonl(sizeof(code) + sizeof(int));
+ pcp_write(frontend, &wsize, sizeof(int));
+ pcp_write(frontend, code, sizeof(code));
+ do_pcp_flush(frontend);
+}
+
static void
process_detach_node(PCP_CONNECTION * frontend, char *buf, char tos)
{
--- /dev/null
+#!/usr/bin/env bash
+#-------------------------------------------------------------------
+# Test script for pcp commands.
+#
+source $TESTLIBS
+TESTDIR=testdir
+PSQL=$PGBIN/psql
+
+rm -fr $TESTDIR
+mkdir $TESTDIR
+cd $TESTDIR
+
+# create test environment.
+echo -n "creating test environment..."
+$PGPOOL_SETUP -m s -n 2 || exit 1
+echo "done."
+
+source ./bashrc.ports
+export PGPORT=$PGPOOL_PORT
+
+echo "=== test1: pcp_log_rotate"
+
+BASEDIR=`pwd`
+echo "logging_collector = on" >> etc/pgpool.conf
+echo "log_directory = '$BASEDIR/log'" >> etc/pgpool.conf
+echo "log_filename = 'pgpool.log'" >> etc/pgpool.conf
+
+./startall
+wait_for_pgpool_startup
+
+mv log/pgpool.log log/pgpool.log.1
+
+sleep 1
+$PSQL -h localhost -c "SELECT 1" test > /dev/null 2>&1
+
+grep "SELECT 1" log/pgpool.log.1 > /dev/null 2>&1
+if [ $? != 0 ];then
+ r1=fail
+ echo "test1 failed before running pcp_log_rotate."
+else
+ $PGPOOL_INSTALL_DIR/bin/pcp_log_rotate -h localhost -w -p $PCP_PORT
+ $PSQL -h localhost -c "SELECT 1" test > /dev/null 2>&1
+
+ sleep 1
+ grep "SELECT 1" log/pgpool.log > /dev/null 2>&1
+ if [ $? = 0 ];then
+ r1=ok
+ echo "test1 ok"
+ else
+ echo "test1 failed."
+ fi
+fi
+
+./shutdownall
+
+if [ $r1 = ok ]; then
+ echo "all test succeeded"
+ exit 0
+else
+ echo "some tests failed"
+ echo "test1: $r1"
+ exit 1
+fi
pcp_attach_node
pcp_detach_node
pcp_health_check_stats
+pcp_log_rotate
pcp_node_count
pcp_node_info
pcp_pool_status
pcp_recovery_node \
pcp_promote_node \
pcp_pool_status \
- pcp_watchdog_info\
- pcp_reload_config
+ pcp_watchdog_info \
+ pcp_reload_config \
+ pcp_log_rotate
client_sources = pcp_frontend_client.c ../fe_memutils.c ../../utils/sprompt.c ../../utils/pool_path.c
pcp_watchdog_info_LDADD = $(libs_dir)/pcp/libpcp.la
pcp_reload_config_SOURCES = $(client_sources)
pcp_reload_config_LDADD = $(libs_dir)/pcp/libpcp.la
-
+pcp_log_rotate_SOURCES = $(client_sources)
+pcp_log_rotate_LDADD = $(libs_dir)/pcp/libpcp.la
PCP_STOP_PGPOOL,
PCP_WATCHDOG_INFO,
PCP_RELOAD_CONFIG,
+ PCP_LOG_ROTATE,
UNKNOWN,
} PCP_UTILITIES;
{"pcp_stop_pgpool", PCP_STOP_PGPOOL, "m:h:p:U:s:wWvda", "terminate pgpool-II"},
{"pcp_watchdog_info", PCP_WATCHDOG_INFO, "n:h:p:U:wWvd", "display a pgpool-II watchdog's information"},
{"pcp_reload_config",PCP_RELOAD_CONFIG,"h:p:U:s:wWvd", "reload a pgpool-II config file"},
+ {"pcp_log_rotate",PCP_LOG_ROTATE,"h:p:U:s:wWvd", "rotate the Pgpool-II's log file"},
{NULL, UNKNOWN, NULL, NULL},
};
struct AppTypes *current_app_type;
pcpResInfo = pcp_reload_config(pcpConn,command_scope);
}
+ else if (current_app_type->app_type == PCP_LOG_ROTATE)
+ {
+ pcpResInfo = pcp_log_rotate(pcpConn,command_scope);
+ }
+
else
{
/* should never happen */
app_support_cluster_mode(void)
{
return (current_app_type->app_type == PCP_STOP_PGPOOL ||
- current_app_type->app_type == PCP_RELOAD_CONFIG);
+ current_app_type->app_type == PCP_RELOAD_CONFIG ||
+ current_app_type->app_type == PCP_LOG_ROTATE);
}
static void
ereport(LOG,
(errmsg("Watchdog has received reload config cluster command from IPC channel")));
}
+ else if (strcasecmp(WD_COMMAND_LOGROTATE_CLUSTER, clusterCommand) == 0)
+ {
+ ereport(LOG,
+ (errmsg("Watchdog has received log rotation cluster command from IPC channel")));
+ }
else if (strcasecmp(WD_COMMAND_LOCK_ON_STANDBY, clusterCommand) == 0)
{
ereport(LOG,
(errmsg("processing reload config command from remote node \"%s\"", wdNode->nodeName)));
pool_signal_parent(SIGHUP);
}
+ else if (strcasecmp(WD_COMMAND_LOGROTATE_CLUSTER, clusterCommand) == 0)
+ {
+ ereport(LOG,
+ (errmsg("processing log rotation command from remote node \"%s\"", wdNode->nodeName)));
+ pool_signal_logrotate();
+ }
else if (strcasecmp(WD_COMMAND_LOCK_ON_STANDBY, clusterCommand) == 0)
{
int lock_type = -1;