pgpool2.git / summary / log / commit / refs
commit 666d71f69c7521b8ebefa96fd6735858aac739fa
Author: Tatsuo Ishii <ishii@postgresql.org>
Date: Tue Mar 13 14:33:43 2012 +0000
Add watchdog feature.
Makefile.am | 4 +-
Makefile.in | 6 +-
configure | 3 +-
main.c | 5 +-
pgpool.conf.sample | 35 +
pool_config.c | 1646 +++++++++++++++++++++++++---------------
pool_config.h | 19 +
pool_config.l | 225 ++++++
watchdog/Makefile.am | 15 +
watchdog/Makefile.in | 492 ++++++++++++
watchdog/test/stab.c | 266 +++++++
watchdog/test/test.c | 85 +++
watchdog/test/wd_child_t.c | 87 +++
watchdog/test/wd_lifecheck_t.c | 87 +++
watchdog/test/wd_packet_t.c | 87 +++
watchdog/test/wd_ping_t.c | 20 +
watchdog/watchdog.c | 125 +++
watchdog/watchdog.h | 112 +++
watchdog/wd_child.c | 199 +++++
watchdog/wd_ext.h | 67 ++
watchdog/wd_if.c | 144 ++++
watchdog/wd_init.c | 79 ++
watchdog/wd_lifecheck.c | 216 ++++++
watchdog/wd_list.c | 169 +++++
watchdog/wd_packet.c | 630 +++++++++++++++
watchdog/wd_ping.c | 228 ++++++
26 files changed, 4423 insertions(+), 628 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 3394cf367..57e59a4c1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -46,7 +46,7 @@ AM_CPPFLAGS = -D_GNU_SOURCE -I @PGSQL_INCLUDE_DIR@
# suggested by libtoolize
ACLOCAL_AMFLAGS = -I m4
-pgpool_LDADD = -L@PGSQL_LIB_DIR@ -lpq parser/libsql-parser.a pcp/libpcp.la parser/nodes.o
+pgpool_LDADD = -L@PGSQL_LIB_DIR@ -lpq parser/libsql-parser.a pcp/libpcp.la parser/nodes.o watchdog/lib-watchdog.a -lpthread
if enable_rpath
pgpool_LDFLAGS = -rpath @PGSQL_LIB_DIR@ -rpath $(libdir)
else
@@ -128,4 +128,4 @@ EXTRA_DIST = pgpool.8.in sample/pgpool.pam \
redhat/pgpool.init redhat/pgpool.sysconfig redhat/pgpool.conf.sample.patch
-SUBDIRS = parser pcp
+SUBDIRS = parser pcp watchdog
diff --git a/Makefile.in b/Makefile.in
index 3bbdefdff..1ca5533b5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -87,7 +87,7 @@ am_pgpool_OBJECTS = main.$(OBJEXT) child.$(OBJEXT) pool_auth.$(OBJEXT) \
getopt_long.$(OBJEXT)
pgpool_OBJECTS = $(am_pgpool_OBJECTS)
pgpool_DEPENDENCIES = parser/libsql-parser.a pcp/libpcp.la \
- parser/nodes.o
+ parser/nodes.o watchdog/lib-watchdog.a
pgpool_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(pgpool_LDFLAGS) \
$(LDFLAGS) -o $@
@@ -353,7 +353,7 @@ AM_CPPFLAGS = -D_GNU_SOURCE -I @PGSQL_INCLUDE_DIR@
# suggested by libtoolize
ACLOCAL_AMFLAGS = -I m4
-pgpool_LDADD = -L@PGSQL_LIB_DIR@ -lpq parser/libsql-parser.a pcp/libpcp.la parser/nodes.o
+pgpool_LDADD = -L@PGSQL_LIB_DIR@ -lpq parser/libsql-parser.a pcp/libpcp.la parser/nodes.o watchdog/lib-watchdog.a -lpthread
@enable_rpath_FALSE@pgpool_LDFLAGS =
@enable_rpath_TRUE@pgpool_LDFLAGS = -rpath @PGSQL_LIB_DIR@ -rpath $(libdir)
AM_YFLAGS = -d
@@ -425,7 +425,7 @@ EXTRA_DIST = pgpool.8.in sample/pgpool.pam \
test/timestamp/parse_schedule test/timestamp/run-test \
redhat/pgpool.init redhat/pgpool.sysconfig redhat/pgpool.conf.sample.patch
-SUBDIRS = parser pcp
+SUBDIRS = parser pcp watchdog
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
diff --git a/configure b/configure
index 758246e31..de112aa65 100755
--- a/configure
+++ b/configure
@@ -13566,7 +13566,7 @@ $as_echo "$enable_table_lock" >&6; }
ac_config_headers="$ac_config_headers config.h"
-ac_config_files="$ac_config_files Makefile parser/Makefile pcp/Makefile"
+ac_config_files="$ac_config_files Makefile parser/Makefile pcp/Makefile watchdog/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -14543,6 +14543,7 @@ do
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"parser/Makefile") CONFIG_FILES="$CONFIG_FILES parser/Makefile" ;;
"pcp/Makefile") CONFIG_FILES="$CONFIG_FILES pcp/Makefile" ;;
+ "watchdog/Makefile") CONFIG_FILES="$CONFIG_FILES watchdog/Makefile" ;;
*) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
diff --git a/main.c b/main.c
index d97af2b37..43fd0af80 100644
--- a/main.c
+++ b/main.c
@@ -60,7 +60,7 @@
#include "parser/pool_string.h"
#include "pool_passwd.h"
#include "pool_memqcache.h"
-
+#include "watchdog/wd_ext.h"
/*
* Process pending signal actions.
*/
@@ -413,6 +413,9 @@ int main(int argc, char **argv)
/* set signal masks */
poolinitmask();
+ /* start watchdog */
+ wd_main(1);
+
if (not_detach)
write_pid_file();
else
diff --git a/pgpool.conf.sample b/pgpool.conf.sample
index fb600ae2e..f3268ef5a 100644
--- a/pgpool.conf.sample
+++ b/pgpool.conf.sample
@@ -416,6 +416,41 @@ client_idle_limit_in_recovery = 0
# -1 means immediate disconnection
+#------------------------------------------------------------------------------
+# WATCHDOG
+#------------------------------------------------------------------------------
+trusted_servers = ''
+ # trusted server list which are used
+ # to confirm network connection
+ # (hostA,hostB,hostC,...)
+delegate_IP = ''
+ # delegate IP address
+wd_port = 9000
+ # port number for watchdog service
+wd_interval = 10;
+ # lifecheck interval (sec) > 0
+ping_path = '/bin'
+ # ping command path
+ifconfig_path = '/sbin'
+ # ifconfig command path
+if_up_cmd = 'ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0'
+ # startup delegate IP command
+if_down_cmd = 'ifconfig eth0:0 down'
+ # shutdown delegate IP command
+wd_life_point = 3
+ # lifecheck retry times
+# Other pgpool Connection Settings
+
+#other_pgpool_hostname0 = 'host0'
+ # Host name or IP address to connect to for other pgpool 0
+#other_pgpool_port0 = 5432
+ # Port number for othet pgpool 0
+#other_wd_port0 = 9000
+ # Port number for othet watchdog 0
+#other_pgpool_hostname1 = 'host1'
+#other_pgpool_port1 = 5432
+#other_wd_port1 = 9000
+
#------------------------------------------------------------------------------
# OTHERS
#------------------------------------------------------------------------------
diff --git a/pool_config.c b/pool_config.c
index 1e83da887..ce7f51970 100644
--- a/pool_config.c
+++ b/pool_config.c
@@ -1,67 +1,112 @@
-/* A lexical scanner generated by flex*/
-/* Scanner skeleton version:
- * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
- */
+#line 3 "pool_config.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+/* begin standard C headers. */
#include <stdio.h>
-#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+#ifndef FLEXINT_H
+#define FLEXINT_H
-/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
-#ifdef c_plusplus
-#ifndef __cplusplus
-#define __cplusplus
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
#endif
+#endif /* ! FLEXINT_H */
#ifdef __cplusplus
-#include <stdlib.h>
-
-/* Use prototypes in function declarations. */
-#define YY_USE_PROTOS
-
/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST
#else /* ! __cplusplus */
-#if __STDC__
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
-#define YY_USE_PROTOS
#define YY_USE_CONST
-#endif /* __STDC__ */
+#endif /* defined (__STDC__) */
#endif /* ! __cplusplus */
-#ifdef __TURBOC__
- #pragma warn -rch
- #pragma warn -use
-#include <io.h>
-#include <stdlib.h>
-#define YY_USE_CONST
-#define YY_USE_PROTOS
-#endif
-
#ifdef YY_USE_CONST
#define yyconst const
#else
#define yyconst
#endif
-
-#ifdef YY_USE_PROTOS
-#define YY_PROTO(proto) proto
-#else
-#define YY_PROTO(proto) ()
-#endif
-
/* Returned upon end-of-file. */
#define YY_NULL 0
@@ -76,80 +121,70 @@
* but we do it the disgusting crufty way forced on us by the ()-less
* definition of BEGIN.
*/
-#define BEGIN yy_start = 1 + 2 *
+#define BEGIN (yy_start) = 1 + 2 *
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
-#define YY_START ((yy_start - 1) / 2)
+#define YY_START (((yy_start) - 1) / 2)
#define YYSTATE YY_START
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart( yyin )
+#define YY_NEW_FILE yyrestart(yyin )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
#define YY_BUF_SIZE 16384
+#endif
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
extern int yyleng;
+
extern FILE *yyin, *yyout;
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
-/* The funky do-while in the following #define is used to turn the definition
- * int a single C statement (which needs a semi-colon terminator). This
- * avoids problems with code like:
- *
- * if ( condition_holds )
- * yyless( 5 );
- * else
- * do_something_else();
- *
- * Prior to using the do-while the compiler would get upset at the
- * "else" because it interpreted the "if" statement as being all
- * done when it reached the ';' after the yyless() call.
- */
-
-/* Return all but the first 'n' matched characters back to the input stream. */
-
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
{ \
/* Undo effects of setting up yytext. */ \
- *yy_cp = yy_hold_char; \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
YY_RESTORE_YY_MORE_OFFSET \
- yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
-#define unput(c) yyunput( c, yytext_ptr )
+#define unput(c) yyunput( c, (yytext_ptr) )
-/* Some routines like yy_flex_realloc() are emitted as static but are
- not called by all lexers. This generates warnings in some compilers,
- notably GCC. Arrange to suppress these. */
-#ifdef __GNUC__
-#define YY_MAY_BE_UNUSED __attribute__((unused))
-#else
-#define YY_MAY_BE_UNUSED
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
#endif
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-typedef unsigned int yy_size_t;
-
-
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
{
FILE *yy_input_file;
@@ -186,12 +221,16 @@ struct yy_buffer_state
*/
int yy_at_bol;
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
int yy_buffer_status;
+
#define YY_BUFFER_NEW 0
#define YY_BUFFER_NORMAL 1
/* When an EOF's been seen but there's still some text to process
@@ -205,28 +244,38 @@ struct yy_buffer_state
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
+
};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-static YY_BUFFER_STATE yy_current_buffer = 0;
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
/* We provide macros for accessing buffer states in case in the
* future we want to put the buffer states in a more general
* "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
*/
-#define YY_CURRENT_BUFFER yy_current_buffer
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
/* yy_hold_char holds the character lost when yytext is formed. */
static char yy_hold_char;
-
static int yy_n_chars; /* number of characters read into yy_ch_buf */
-
-
int yyleng;
/* Points to current character in buffer. */
static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1; /* whether we need to initialize */
+static int yy_init = 0; /* whether we need to initialize */
static int yy_start = 0; /* start state number */
/* Flag which is used to allow yywrap()'s to do buffer switches
@@ -234,69 +283,95 @@ static int yy_start = 0; /* start state number */
*/
static int yy_did_buffer_switch_on_eof;
-void yyrestart YY_PROTO(( FILE *input_file ));
+void yyrestart (FILE *input_file );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
+void yy_delete_buffer (YY_BUFFER_STATE b );
+void yy_flush_buffer (YY_BUFFER_STATE b );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
+void yypop_buffer_state (void );
-void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
-void yy_load_buffer_state YY_PROTO(( void ));
-YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
-void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
-void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
-YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
-YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
-YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
-static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )) YY_MAY_BE_UNUSED;
-static void yy_flex_free YY_PROTO(( void * ));
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
+
+void *yyalloc (yy_size_t );
+void *yyrealloc (void *,yy_size_t );
+void yyfree (void * );
#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
- if ( ! yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_is_interactive = is_interactive; \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
#define yy_set_bol(at_bol) \
{ \
- if ( ! yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_at_bol = at_bol; \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
-#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+/* Begin user sect3 */
-#define yywrap() 1
+#define yywrap(n) 1
#define YY_SKIP_YYWRAP
+
typedef unsigned char YY_CHAR;
+
FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
extern char *yytext;
#define yytext_ptr yytext
-static yy_state_type yy_get_previous_state YY_PROTO(( void ));
-static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
-static int yy_get_next_buffer YY_PROTO(( void ));
-static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
*/
#define YY_DO_BEFORE_ACTION \
- yytext_ptr = yy_bp; \
- yyleng = (int) (yy_cp - yy_bp); \
- yy_hold_char = *yy_cp; \
+ (yytext_ptr) = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
*yy_cp = '\0'; \
- yy_c_buf_p = yy_cp;
+ (yy_c_buf_p) = yy_cp;
#define YY_NUM_RULES 11
#define YY_END_OF_BUFFER 12
-static yyconst short int yy_accept[38] =
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[38] =
{ 0,
0, 0, 12, 10, 2, 1, 10, 10, 10, 8,
7, 7, 9, 4, 2, 0, 3, 0, 5, 0,
@@ -304,7 +379,7 @@ static yyconst short int yy_accept[38] =
5, 0, 0, 8, 7, 6, 0
} ;
-static yyconst int yy_ec[256] =
+static yyconst flex_int32_t yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
@@ -336,13 +411,13 @@ static yyconst int yy_ec[256] =
15, 15, 15, 15, 15
} ;
-static yyconst int yy_meta[19] =
+static yyconst flex_int32_t yy_meta[19] =
{ 0,
1, 1, 2, 1, 1, 1, 3, 3, 3, 4,
4, 1, 5, 4, 3, 1, 3, 3
} ;
-static yyconst short int yy_base[45] =
+static yyconst flex_int16_t yy_base[45] =
{ 0,
0, 0, 61, 86, 58, 86, 55, 14, 23, 43,
10, 46, 86, 28, 47, 40, 86, 16, 86, 22,
@@ -351,7 +426,7 @@ static yyconst short int yy_base[45] =
70, 75, 77, 80
} ;
-static yyconst short int yy_def[45] =
+static yyconst flex_int16_t yy_def[45] =
{ 0,
37, 1, 37, 37, 37, 37, 38, 39, 37, 40,
9, 9, 37, 41, 37, 38, 37, 39, 37, 42,
@@ -360,7 +435,7 @@ static yyconst short int yy_def[45] =
37, 37, 37, 37
} ;
-static yyconst short int yy_nxt[105] =
+static yyconst flex_int16_t yy_nxt[105] =
{ 0,
4, 5, 6, 7, 8, 9, 9, 10, 4, 11,
12, 13, 14, 14, 14, 4, 14, 14, 19, 23,
@@ -376,7 +451,7 @@ static yyconst short int yy_nxt[105] =
37, 37, 37, 37
} ;
-static yyconst short int yy_chk[105] =
+static yyconst flex_int16_t yy_chk[105] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 8, 11,
@@ -395,6 +470,9 @@ static yyconst short int yy_chk[105] =
static yy_state_type yy_last_accepting_state;
static char *yy_last_accepting_cpos;
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
*/
@@ -404,7 +482,6 @@ static char *yy_last_accepting_cpos;
#define YY_RESTORE_YY_MORE_OFFSET
char *yytext;
#line 1 "pool_config.l"
-#define INITIAL 0
/* -*-pgsql-c-*- */
/*
*
@@ -464,9 +541,52 @@ static char *extract_string(char *value, POOL_TOKEN token);
static char **extract_string_tokens(char *str, char *delim, int *n);
static void clear_host_entry(int slot);
-#define YY_NEVER_INTERACTIVE 1
-#define YY_NO_UNPUT 1
-#line 470 "pool_config.c"
+#line 545 "pool_config.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined );
+
+FILE *yyget_in (void );
+
+void yyset_in (FILE * in_str );
+
+FILE *yyget_out (void );
+
+void yyset_out (FILE * out_str );
+
+int yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -474,65 +594,28 @@ static void clear_host_entry(int slot);
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int yywrap YY_PROTO(( void ));
+extern "C" int yywrap (void );
#else
-extern int yywrap YY_PROTO(( void ));
+extern int yywrap (void );
#endif
#endif
-#ifndef YY_NO_UNPUT
-static void yyunput YY_PROTO(( int c, char *buf_ptr ));
-#endif
-
#ifndef yytext_ptr
-static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+static void yy_flex_strncpy (char *,yyconst char *,int );
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+static int yy_flex_strlen (yyconst char * );
#endif
#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-static int yyinput YY_PROTO(( void ));
-#else
-static int input YY_PROTO(( void ));
-#endif
-#endif
-
-#if YY_STACK_USED
-static int yy_start_stack_ptr = 0;
-static int yy_start_stack_depth = 0;
-static int *yy_start_stack = 0;
-#ifndef YY_NO_PUSH_STATE
-static void yy_push_state YY_PROTO(( int new_state ));
-#endif
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state YY_PROTO(( void ));
-#endif
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state YY_PROTO(( void ));
-#endif
+#ifdef __cplusplus
+static int yyinput (void );
#else
-#define YY_NO_PUSH_STATE 1
-#define YY_NO_POP_STATE 1
-#define YY_NO_TOP_STATE 1
+static int input (void );
#endif
-#ifdef YY_MALLOC_DECL
-YY_MALLOC_DECL
-#else
-#if __STDC__
-#ifndef __cplusplus
-#include <stdlib.h>
-#endif
-#else
-/* Just try to get by without declaring the routines. This will fail
- * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
- * or sizeof(void*) != sizeof(int).
- */
-#endif
#endif
/* Amount of stuff to slurp up with each read. */
@@ -541,12 +624,11 @@ YY_MALLOC_DECL
#endif
/* Copy whatever the last rule matched to the standard output. */
-
#ifndef ECHO
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -554,9 +636,10 @@ YY_MALLOC_DECL
*/
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
- if ( yy_current_buffer->yy_is_interactive ) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
- int c = '*', n; \
+ int c = '*'; \
+ unsigned n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -566,9 +649,22 @@ YY_MALLOC_DECL
YY_FATAL_ERROR( "input in flex scanner failed" ); \
result = n; \
} \
- else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
- && ferror( yyin ) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" );
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
#endif
/* No semi-colon after return; correct usage is to write "yyterminate();" -
@@ -589,12 +685,18 @@ YY_MALLOC_DECL
#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
#endif
+/* end tables serialization structures and prototypes */
+
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
-#define YY_DECL int yylex YY_PROTO(( void ))
-#endif
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
/* Code executed at the beginning of each rule, after yytext and yyleng
* have been set up.
@@ -611,27 +713,29 @@ YY_MALLOC_DECL
#define YY_RULE_SETUP \
YY_USER_ACTION
+/** The main scanner function which does all the work.
+ */
YY_DECL
- {
+{
register yy_state_type yy_current_state;
- register char *yy_cp = NULL, *yy_bp = NULL;
+ register char *yy_cp, *yy_bp;
register int yy_act;
-
+
#line 85 "pool_config.l"
-#line 624 "pool_config.c"
+#line 728 "pool_config.c"
- if ( yy_init )
+ if ( !(yy_init) )
{
- yy_init = 0;
+ (yy_init) = 1;
#ifdef YY_USER_INIT
YY_USER_INIT;
#endif
- if ( ! yy_start )
- yy_start = 1; /* first start state */
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
if ( ! yyin )
yyin = stdin;
@@ -639,34 +743,36 @@ YY_DECL
if ( ! yyout )
yyout = stdout;
- if ( ! yy_current_buffer )
- yy_current_buffer =
- yy_create_buffer( yyin, YY_BUF_SIZE );
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
- yy_load_buffer_state();
+ yy_load_buffer_state( );
}
while ( 1 ) /* loops until end-of-file is reached */
{
- yy_cp = yy_c_buf_p;
+ yy_cp = (yy_c_buf_p);
/* Support of yytext. */
- *yy_cp = yy_hold_char;
+ *yy_cp = (yy_hold_char);
/* yy_bp points to the position in yy_ch_buf of the start of
* the current run.
*/
yy_bp = yy_cp;
- yy_current_state = yy_start;
+ yy_current_state = (yy_start);
yy_match:
do
{
register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
@@ -677,33 +783,28 @@ yy_match:
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 86 );
+ while ( yy_current_state != 37 );
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
yy_find_action:
yy_act = yy_accept[yy_current_state];
- if ( yy_act == 0 )
- { /* have to back up */
- yy_cp = yy_last_accepting_cpos;
- yy_current_state = yy_last_accepting_state;
- yy_act = yy_accept[yy_current_state];
- }
YY_DO_BEFORE_ACTION;
-
do_action: /* This label is used only to access EOF actions. */
-
switch ( yy_act )
{ /* beginning of action switch */
case 0: /* must back up */
/* undo the effects of YY_DO_BEFORE_ACTION */
- *yy_cp = yy_hold_char;
- yy_cp = yy_last_accepting_cpos;
- yy_current_state = yy_last_accepting_state;
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
goto yy_find_action;
case 1:
+/* rule 1 can match eol */
YY_RULE_SETUP
#line 87 "pool_config.l"
Lineno++; return POOL_EOL;
@@ -714,8 +815,8 @@ YY_RULE_SETUP
/* eat whitespace */
YY_BREAK
case 3:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp -= 1;
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp -= 1;
YY_DO_BEFORE_ACTION; /* set up yytext again */
YY_RULE_SETUP
#line 89 "pool_config.l"
@@ -761,33 +862,33 @@ YY_RULE_SETUP
#line 100 "pool_config.l"
ECHO;
YY_BREAK
-#line 765 "pool_config.c"
+#line 866 "pool_config.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
case YY_END_OF_BUFFER:
{
/* Amount of text matched not including the EOB char. */
- int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
/* Undo the effects of YY_DO_BEFORE_ACTION. */
- *yy_cp = yy_hold_char;
+ *yy_cp = (yy_hold_char);
YY_RESTORE_YY_MORE_OFFSET
- if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
{
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
* yylex(). If so, then we have to assure
- * consistency between yy_current_buffer and our
+ * consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
* back-up) that will match for the new input source.
*/
- yy_n_chars = yy_current_buffer->yy_n_chars;
- yy_current_buffer->yy_input_file = yyin;
- yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
}
/* Note that here we test for yy_c_buf_p "<=" to the position
@@ -797,13 +898,13 @@ case YY_STATE_EOF(INITIAL):
* end-of-buffer state). Contrast this with the test
* in input().
*/
- if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
{ /* This was really a NUL. */
yy_state_type yy_next_state;
- yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
- yy_current_state = yy_get_previous_state();
+ yy_current_state = yy_get_previous_state( );
/* Okay, we're now positioned to make the NUL
* transition. We couldn't have
@@ -816,30 +917,31 @@ case YY_STATE_EOF(INITIAL):
yy_next_state = yy_try_NUL_trans( yy_current_state );
- yy_bp = yytext_ptr + YY_MORE_ADJ;
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
if ( yy_next_state )
{
/* Consume the NUL. */
- yy_cp = ++yy_c_buf_p;
+ yy_cp = ++(yy_c_buf_p);
yy_current_state = yy_next_state;
goto yy_match;
}
else
{
- yy_cp = yy_c_buf_p;
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
goto yy_find_action;
}
}
- else switch ( yy_get_next_buffer() )
+ else switch ( yy_get_next_buffer( ) )
{
case EOB_ACT_END_OF_FILE:
{
- yy_did_buffer_switch_on_eof = 0;
+ (yy_did_buffer_switch_on_eof) = 0;
- if ( yywrap() )
+ if ( yywrap( ) )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
@@ -850,7 +952,7 @@ case YY_STATE_EOF(INITIAL):
* YY_NULL, it'll still work - another
* YY_NULL will get returned.
*/
- yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
yy_act = YY_STATE_EOF(YY_START);
goto do_action;
@@ -858,30 +960,30 @@ case YY_STATE_EOF(INITIAL):
else
{
- if ( ! yy_did_buffer_switch_on_eof )
+ if ( ! (yy_did_buffer_switch_on_eof) )
YY_NEW_FILE;
}
break;
}
case EOB_ACT_CONTINUE_SCAN:
- yy_c_buf_p =
- yytext_ptr + yy_amount_of_matched_text;
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
- yy_current_state = yy_get_previous_state();
+ yy_current_state = yy_get_previous_state( );
- yy_cp = yy_c_buf_p;
- yy_bp = yytext_ptr + YY_MORE_ADJ;
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
goto yy_match;
case EOB_ACT_LAST_MATCH:
- yy_c_buf_p =
- &yy_current_buffer->yy_ch_buf[yy_n_chars];
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
- yy_current_state = yy_get_previous_state();
+ yy_current_state = yy_get_previous_state( );
- yy_cp = yy_c_buf_p;
- yy_bp = yytext_ptr + YY_MORE_ADJ;
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
goto yy_find_action;
}
break;
@@ -892,8 +994,7 @@ case YY_STATE_EOF(INITIAL):
"fatal flex scanner internal error--no action found" );
} /* end of action switch */
} /* end of scanning one token */
- } /* end of yylex */
-
+} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
*
@@ -902,21 +1003,20 @@ case YY_STATE_EOF(INITIAL):
* EOB_ACT_CONTINUE_SCAN - continue scanning from current position
* EOB_ACT_END_OF_FILE - end of file
*/
-
-static int yy_get_next_buffer()
- {
- register char *dest = yy_current_buffer->yy_ch_buf;
- register char *source = yytext_ptr;
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
register int number_to_move, i;
int ret_val;
- if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
YY_FATAL_ERROR(
"fatal flex scanner internal error--end of buffer missed" );
- if ( yy_current_buffer->yy_fill_buffer == 0 )
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
{ /* Don't try to fill the buffer, so this is an EOF. */
- if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
{
/* We matched a single character, the EOB, so
* treat this as a final EOF.
@@ -936,34 +1036,30 @@ static int yy_get_next_buffer()
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
- if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
/* don't do the read, it's not guaranteed to return an EOF,
* just force an EOF
*/
- yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
else
{
- int num_to_read =
- yy_current_buffer->yy_buf_size - number_to_move - 1;
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
{ /* Not enough room in the buffer - grow it. */
-#ifdef YY_USES_REJECT
- YY_FATAL_ERROR(
-"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
-#else
/* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = yy_current_buffer;
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
int yy_c_buf_p_offset =
- (int) (yy_c_buf_p - b->yy_ch_buf);
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
if ( b->yy_is_our_buffer )
{
@@ -976,8 +1072,7 @@ static int yy_get_next_buffer()
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
- yy_flex_realloc( (void *) b->yy_ch_buf,
- b->yy_buf_size + 2 );
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
}
else
/* Can't grow it, we don't own it. */
@@ -987,35 +1082,35 @@ static int yy_get_next_buffer()
YY_FATAL_ERROR(
"fatal error - scanner input buffer overflow" );
- yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
- num_to_read = yy_current_buffer->yy_buf_size -
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
number_to_move - 1;
-#endif
+
}
if ( num_to_read > YY_READ_BUF_SIZE )
num_to_read = YY_READ_BUF_SIZE;
/* Read in more data. */
- YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
- yy_n_chars, num_to_read );
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
- yy_current_buffer->yy_n_chars = yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
}
- if ( yy_n_chars == 0 )
+ if ( (yy_n_chars) == 0 )
{
if ( number_to_move == YY_MORE_ADJ )
{
ret_val = EOB_ACT_END_OF_FILE;
- yyrestart( yyin );
+ yyrestart(yyin );
}
else
{
ret_val = EOB_ACT_LAST_MATCH;
- yy_current_buffer->yy_buffer_status =
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
YY_BUFFER_EOF_PENDING;
}
}
@@ -1023,32 +1118,39 @@ static int yy_get_next_buffer()
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- yy_n_chars += number_to_move;
- yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+ if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
- yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
return ret_val;
- }
-
+}
/* yy_get_previous_state - get the state just before the EOB char was reached */
-static yy_state_type yy_get_previous_state()
- {
+ static yy_state_type yy_get_previous_state (void)
+{
register yy_state_type yy_current_state;
register char *yy_cp;
+
+ yy_current_state = (yy_start);
- yy_current_state = yy_start;
-
- for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
@@ -1060,30 +1162,23 @@ static yy_state_type yy_get_previous_state()
}
return yy_current_state;
- }
-
+}
/* yy_try_NUL_trans - try to make a transition on the NUL character
*
* synopsis
* next_state = yy_try_NUL_trans( current_state );
*/
-
-#ifdef YY_USE_PROTOS
-static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
-#else
-static yy_state_type yy_try_NUL_trans( yy_current_state )
-yy_state_type yy_current_state;
-#endif
- {
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
register int yy_is_jam;
- register char *yy_cp = yy_c_buf_p;
+ register char *yy_cp = (yy_c_buf_p);
register YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
@@ -1095,81 +1190,36 @@ yy_state_type yy_current_state;
yy_is_jam = (yy_current_state == 37);
return yy_is_jam ? 0 : yy_current_state;
- }
-
-
-#ifndef YY_NO_UNPUT
-#ifdef YY_USE_PROTOS
-static void yyunput( int c, register char *yy_bp )
-#else
-static void yyunput( c, yy_bp )
-int c;
-register char *yy_bp;
-#endif
- {
- register char *yy_cp = yy_c_buf_p;
-
- /* undo effects of setting up yytext */
- *yy_cp = yy_hold_char;
-
- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
- { /* need to shift things up to make room */
- /* +2 for EOB chars. */
- register int number_to_move = yy_n_chars + 2;
- register char *dest = &yy_current_buffer->yy_ch_buf[
- yy_current_buffer->yy_buf_size + 2];
- register char *source =
- &yy_current_buffer->yy_ch_buf[number_to_move];
-
- while ( source > yy_current_buffer->yy_ch_buf )
- *--dest = *--source;
-
- yy_cp += (int) (dest - source);
- yy_bp += (int) (dest - source);
- yy_current_buffer->yy_n_chars =
- yy_n_chars = yy_current_buffer->yy_buf_size;
-
- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
- YY_FATAL_ERROR( "flex scanner push-back overflow" );
- }
-
- *--yy_cp = (char) c;
-
-
- yytext_ptr = yy_bp;
- yy_hold_char = *yy_cp;
- yy_c_buf_p = yy_cp;
- }
-#endif /* ifndef YY_NO_UNPUT */
-
+}
#ifndef YY_NO_INPUT
#ifdef __cplusplus
-static int yyinput()
+ static int yyinput (void)
#else
-static int input()
+ static int input (void)
#endif
- {
- int c;
- *yy_c_buf_p = yy_hold_char;
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
- if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
{
/* yy_c_buf_p now points to the character we want to return.
* If this occurs *before* the EOB characters, then it's a
* valid NUL; if not, then we've hit the end of the buffer.
*/
- if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
/* This was really a NUL. */
- *yy_c_buf_p = '\0';
+ *(yy_c_buf_p) = '\0';
else
{ /* need more input */
- int offset = yy_c_buf_p - yytext_ptr;
- ++yy_c_buf_p;
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
- switch ( yy_get_next_buffer() )
+ switch ( yy_get_next_buffer( ) )
{
case EOB_ACT_LAST_MATCH:
/* This happens because yy_g_n_b()
@@ -1183,16 +1233,16 @@ static int input()
*/
/* Reset buffer status. */
- yyrestart( yyin );
+ yyrestart(yyin );
- /* fall through */
+ /*FALLTHROUGH*/
case EOB_ACT_END_OF_FILE:
{
- if ( yywrap() )
+ if ( yywrap( ) )
return EOF;
- if ( ! yy_did_buffer_switch_on_eof )
+ if ( ! (yy_did_buffer_switch_on_eof) )
YY_NEW_FILE;
#ifdef __cplusplus
return yyinput();
@@ -1202,90 +1252,92 @@ static int input()
}
case EOB_ACT_CONTINUE_SCAN:
- yy_c_buf_p = yytext_ptr + offset;
+ (yy_c_buf_p) = (yytext_ptr) + offset;
break;
}
}
}
- c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
- *yy_c_buf_p = '\0'; /* preserve yytext */
- yy_hold_char = *++yy_c_buf_p;
-
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
return c;
- }
-#endif /* YY_NO_INPUT */
-
-#ifdef YY_USE_PROTOS
-void yyrestart( FILE *input_file )
-#else
-void yyrestart( input_file )
-FILE *input_file;
-#endif
- {
- if ( ! yy_current_buffer )
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+}
+#endif /* ifndef YY_NO_INPUT */
- yy_init_buffer( yy_current_buffer, input_file );
- yy_load_buffer_state();
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
}
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+ yy_load_buffer_state( );
+}
-#ifdef YY_USE_PROTOS
-void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
-#else
-void yy_switch_to_buffer( new_buffer )
-YY_BUFFER_STATE new_buffer;
-#endif
- {
- if ( yy_current_buffer == new_buffer )
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
return;
- if ( yy_current_buffer )
+ if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
- *yy_c_buf_p = yy_hold_char;
- yy_current_buffer->yy_buf_pos = yy_c_buf_p;
- yy_current_buffer->yy_n_chars = yy_n_chars;
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
}
- yy_current_buffer = new_buffer;
- yy_load_buffer_state();
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
/* We don't actually know whether we did this switch during
* EOF (yywrap()) processing, but the only time this flag
* is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
- yy_did_buffer_switch_on_eof = 1;
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_load_buffer_state( void )
-#else
-void yy_load_buffer_state()
-#endif
- {
- yy_n_chars = yy_current_buffer->yy_n_chars;
- yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
- yyin = yy_current_buffer->yy_input_file;
- yy_hold_char = *yy_c_buf_p;
- }
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+static void yy_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
-#else
-YY_BUFFER_STATE yy_create_buffer( file, size )
-FILE *file;
-int size;
-#endif
- {
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+{
YY_BUFFER_STATE b;
-
- b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
@@ -1294,75 +1346,71 @@ int size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
- b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_is_our_buffer = 1;
- yy_init_buffer( b, file );
+ yy_init_buffer(b,file );
return b;
- }
-
+}
-#ifdef YY_USE_PROTOS
-void yy_delete_buffer( YY_BUFFER_STATE b )
-#else
-void yy_delete_buffer( b )
-YY_BUFFER_STATE b;
-#endif
- {
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b )
+{
+
if ( ! b )
return;
- if ( b == yy_current_buffer )
- yy_current_buffer = (YY_BUFFER_STATE) 0;
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
if ( b->yy_is_our_buffer )
- yy_flex_free( (void *) b->yy_ch_buf );
-
- yy_flex_free( (void *) b );
- }
-
+ yyfree((void *) b->yy_ch_buf );
+ yyfree((void *) b );
+}
-#ifdef YY_USE_PROTOS
-void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
-#else
-void yy_init_buffer( b, file )
-YY_BUFFER_STATE b;
-FILE *file;
-#endif
-
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
- {
- yy_flush_buffer( b );
+{
+ int oerrno = errno;
+
+ yy_flush_buffer(b );
b->yy_input_file = file;
b->yy_fill_buffer = 1;
-#if YY_ALWAYS_INTERACTIVE
- b->yy_is_interactive = 1;
-#else
-#if YY_NEVER_INTERACTIVE
- b->yy_is_interactive = 0;
-#else
- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-#endif
-#endif
- }
-
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
-#ifdef YY_USE_PROTOS
-void yy_flush_buffer( YY_BUFFER_STATE b )
-#else
-void yy_flush_buffer( b )
-YY_BUFFER_STATE b;
-#endif
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
- {
- if ( ! b )
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
return;
b->yy_n_chars = 0;
@@ -1379,29 +1427,125 @@ YY_BUFFER_STATE b;
b->yy_at_bol = 1;
b->yy_buffer_status = YY_BUFFER_NEW;
- if ( b == yy_current_buffer )
- yy_load_buffer_state();
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void yypop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
}
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-#ifndef YY_NO_SCAN_BUFFER
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
-#else
-YY_BUFFER_STATE yy_scan_buffer( base, size )
-char *base;
-yy_size_t size;
-#endif
- {
- YY_BUFFER_STATE b;
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/* They forgot to leave room for the EOB's. */
return 0;
- b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
@@ -1415,56 +1559,51 @@ yy_size_t size;
b->yy_fill_buffer = 0;
b->yy_buffer_status = YY_BUFFER_NEW;
- yy_switch_to_buffer( b );
+ yy_switch_to_buffer(b );
return b;
- }
-#endif
-
-
-#ifndef YY_NO_SCAN_STRING
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
-#else
-YY_BUFFER_STATE yy_scan_string( yy_str )
-yyconst char *yy_str;
-#endif
- {
- int len;
- for ( len = 0; yy_str[len]; ++len )
- ;
-
- return yy_scan_bytes( yy_str, len );
- }
-#endif
+}
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) );
+}
-#ifndef YY_NO_SCAN_BYTES
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
-#else
-YY_BUFFER_STATE yy_scan_bytes( bytes, len )
-yyconst char *bytes;
-int len;
-#endif
- {
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
int i;
-
+
/* Get memory for full buffer, including space for trailing EOB's. */
- n = len + 2;
- buf = (char *) yy_flex_alloc( n );
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
- for ( i = 0; i < len; ++i )
- buf[i] = bytes[i];
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
- buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
- b = yy_scan_buffer( buf, n );
+ b = yy_scan_buffer(buf,n );
if ( ! b )
YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
@@ -1474,148 +1613,196 @@ int len;
b->yy_is_our_buffer = 1;
return b;
- }
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
#endif
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
-#ifndef YY_NO_PUSH_STATE
-#ifdef YY_USE_PROTOS
-static void yy_push_state( int new_state )
-#else
-static void yy_push_state( new_state )
-int new_state;
-#endif
- {
- if ( yy_start_stack_ptr >= yy_start_stack_depth )
- {
- yy_size_t new_size;
+/* Redefine yyless() so it works in section 3 code. */
- yy_start_stack_depth += YY_START_STACK_INCR;
- new_size = yy_start_stack_depth * sizeof( int );
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
- if ( ! yy_start_stack )
- yy_start_stack = (int *) yy_flex_alloc( new_size );
+/* Accessor methods (get/set functions) to struct members. */
- else
- yy_start_stack = (int *) yy_flex_realloc(
- (void *) yy_start_stack, new_size );
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
- if ( ! yy_start_stack )
- YY_FATAL_ERROR(
- "out of memory expanding start-condition stack" );
- }
+/** Get the input stream.
+ *
+ */
+FILE *yyget_in (void)
+{
+ return yyin;
+}
- yy_start_stack[yy_start_stack_ptr++] = YY_START;
+/** Get the output stream.
+ *
+ */
+FILE *yyget_out (void)
+{
+ return yyout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int yyget_leng (void)
+{
+ return yyleng;
+}
- BEGIN(new_state);
- }
-#endif
+/** Get the current token.
+ *
+ */
+char *yyget_text (void)
+{
+ return yytext;
+}
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state()
- {
- if ( --yy_start_stack_ptr < 0 )
- YY_FATAL_ERROR( "start-condition stack underflow" );
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void yyset_lineno (int line_number )
+{
+
+ yylineno = line_number;
+}
- BEGIN(yy_start_stack[yy_start_stack_ptr]);
- }
-#endif
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str )
+{
+ yyin = in_str ;
+}
+void yyset_out (FILE * out_str )
+{
+ yyout = out_str ;
+}
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state()
- {
- return yy_start_stack[yy_start_stack_ptr - 1];
- }
-#endif
+int yyget_debug (void)
+{
+ return yy_flex_debug;
+}
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
+void yyset_debug (int bdebug )
+{
+ yy_flex_debug = bdebug ;
+}
-#ifdef YY_USE_PROTOS
-static void yy_fatal_error( yyconst char msg[] )
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
#else
-static void yy_fatal_error( msg )
-char msg[];
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
#endif
- {
- (void) fprintf( stderr, "%s\n", msg );
- exit( YY_EXIT_FAILURE );
- }
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
+ }
-/* Redefine yyless() so it works in section 3 code. */
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
-#undef yyless
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- yytext[yyleng] = yy_hold_char; \
- yy_c_buf_p = yytext + n; \
- yy_hold_char = *yy_c_buf_p; \
- *yy_c_buf_p = '\0'; \
- yyleng = n; \
- } \
- while ( 0 )
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( );
+ return 0;
+}
-/* Internal utility routines. */
+/*
+ * Internal utility routines.
+ */
#ifndef yytext_ptr
-#ifdef YY_USE_PROTOS
-static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
-#else
-static void yy_flex_strncpy( s1, s2, n )
-char *s1;
-yyconst char *s2;
-int n;
-#endif
- {
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
register int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
- }
+}
#endif
#ifdef YY_NEED_STRLEN
-#ifdef YY_USE_PROTOS
-static int yy_flex_strlen( yyconst char *s )
-#else
-static int yy_flex_strlen( s )
-yyconst char *s;
-#endif
- {
+static int yy_flex_strlen (yyconst char * s )
+{
register int n;
for ( n = 0; s[n]; ++n )
;
return n;
- }
+}
#endif
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_alloc( yy_size_t size )
-#else
-static void *yy_flex_alloc( size )
-yy_size_t size;
-#endif
- {
+void *yyalloc (yy_size_t size )
+{
return (void *) malloc( size );
- }
+}
-#ifdef YY_USE_PROTOS
-static void *yy_flex_realloc( void *ptr, yy_size_t size )
-#else
-static void *yy_flex_realloc( ptr, size )
-void *ptr;
-yy_size_t size;
-#endif
- {
+void *yyrealloc (void * ptr, yy_size_t size )
+{
/* The cast to (char *) in the following accommodates both
* implementations that use char* generic pointers, and those
* that use void* generic pointers. It works with the latter
@@ -1624,28 +1811,19 @@ yy_size_t size;
* as though doing an assignment.
*/
return (void *) realloc( (char *) ptr, size );
- }
+}
-#ifdef YY_USE_PROTOS
-static void yy_flex_free( void *ptr )
-#else
-static void yy_flex_free( ptr )
-void *ptr;
-#endif
- {
- free( ptr );
- }
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
-#if YY_MAIN
-int main()
- {
- yylex();
- return 0;
- }
-#endif
#line 100 "pool_config.l"
+
int pool_init_config(void)
{
int res;
@@ -1677,6 +1855,17 @@ int pool_init_config(void)
}
#endif
+ /*
+ * add for watchdog
+ */
+ pool_config->other_wd = malloc(sizeof(WdDesc));
+ if (pool_config->other_wd == NULL)
+ {
+ pool_error("failed to allocate pool_config->cwother_wd");
+ return -1;
+ }
+ memset(pool_config->other_wd,0,sizeof(WdDesc));
+
/* set hardcoded default values */
pool_config->listen_addresses = "localhost";
pool_config->port = 9999;
@@ -1763,6 +1952,20 @@ int pool_init_config(void)
pool_config->lists_patterns = NULL;
pool_config->pattc = 0;
pool_config->current_pattern_size = 0;
+ /*
+ * add for watchdog
+ */
+ pool_config->trusted_servers = NULL;
+ pool_config->delegate_IP = NULL;
+ pool_config->wd_port = 9000;
+ pool_config->other_wd->num_wd = 0;
+ pool_config->wd_interval = 10;
+ pool_config->ping_path = "/bin";
+ pool_config->ifconfig_path = "/sbin";
+ pool_config->if_up_cmd = "ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0";
+ pool_config->if_down_cmd = "ifconfig eth0:0 down";
+ pool_config->wd_life_point = 3;
+
pool_config->memory_cache_enabled = 0;
pool_config->memqcache_method = "shmem";
@@ -3389,6 +3592,206 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
pool_config->lobj_lock_table = str;
}
+ /*
+ * add for watchdog
+ */
+ else if (!strncmp(key, "other_pgpool_hostname", 21) &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context) &&
+ mypid == getpid()) /* this parameter must be modified by parent pid */
+ {
+ int slot;
+ char *str;
+
+ slot = atoi(key + 21) ;
+ if (slot < 0 || slot >= MAX_CONNECTION_SLOTS)
+ {
+ pool_error("pool_config: pgpool number %s for other_pgpool_hostname out of range", key);
+ fclose(fd);
+ return(-1);
+ }
+
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ if (context == INIT_CONFIG || (context == RELOAD_CONFIG ))
+ strlcpy(WD_INFO(slot).hostname, str, WD_MAX_HOST_NAMELEN);
+ }
+
+ else if (!strncmp(key, "other_pgpool_port", 17) &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context) &&
+ mypid == getpid()) /* this parameter must be modified by parent pid */
+ {
+ int slot;
+
+ slot = atoi(key + 17);
+ if (slot < 0 || slot >= MAX_CONNECTION_SLOTS)
+ {
+ pool_error("pool_config: pgpool number %s for other_pgpool_port out of range", key);
+ fclose(fd);
+ return(-1);
+ }
+
+ if (context == INIT_CONFIG || (context == RELOAD_CONFIG ))
+ WD_INFO(slot).pgpool_port = atoi(yytext);
+ }
+
+ else if (!strncmp(key, "other_pgpool_wd_port", 20) &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context) &&
+ mypid == getpid()) /* this parameter must be modified by parent pid */
+ {
+ int slot;
+
+ slot = atoi(key + 20);
+ if (slot < 0 || slot >= MAX_CONNECTION_SLOTS)
+ {
+ pool_error("pool_config: pgpool number %s for other_pgpool_wd_port out of range", key);
+ fclose(fd);
+ return(-1);
+ }
+
+ if (context == INIT_CONFIG || (context == RELOAD_CONFIG ))
+ {
+ WD_INFO(slot).wd_port = atoi(yytext);
+ WD_INFO(slot).status = WD_INIT;
+ pool_config->other_wd->num_wd = slot+1;
+ }
+ }
+ else if (!strcmp(key, "trusted_servers") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->trusted_servers = str;
+ }
+ else if (!strcmp(key, "delegate_IP") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->delegate_IP = str;
+ }
+ else if (!strcmp(key, "wd_interval") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ int v = atoi(yytext);
+
+ if (token != POOL_INTEGER || v <= 0)
+ {
+ pool_error("pool_config: %s must be higher than 1 numeric value", key);
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->wd_interval = v;
+ }
+ else if (!strcmp(key, "ping_path") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->ping_path = str;
+ }
+ else if (!strcmp(key, "ifconfig_path") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->ifconfig_path = str;
+ }
+ else if (!strcmp(key, "if_up_cmd") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->if_up_cmd = str;
+ }
+ else if (!strcmp(key, "if_down_cmd") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->if_down_cmd = str;
+ }
+ else if (!strcmp(key, "wd_life_point") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ int v = atoi(yytext);
+
+ if (token != POOL_INTEGER || v <= 0)
+ {
+ pool_error("pool_config: %s must be higher than 1 numeric value", key);
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->wd_life_point = v;
+ }
+
else if (!strcmp(key, "ssl") && CHECK_CONTEXT(INIT_CONFIG, context))
{
@@ -4107,3 +4510,4 @@ char *pool_flag_to_str(unsigned short flag)
snprintf(buf, sizeof(buf), "DISALLOW_TO_FAILOVER");
return buf;
}
+
diff --git a/pool_config.h b/pool_config.h
index a118bfd51..f9eeb4ba5 100644
--- a/pool_config.h
+++ b/pool_config.h
@@ -26,6 +26,11 @@
#ifndef POOL_CONFIG_H
#define POOL_CONFIG_H
+/*
+ * watchdog
+ */
+#include "watchdog/watchdog.h"
+
/*
* Master/slave sub mode
*/
@@ -205,6 +210,20 @@ typedef struct {
RegPattern *lists_memqcache_table_patterns; /* Precompiled regex patterns for black/white lists */
int memqcache_table_pattc; /* number of regexp pattern */
int current_memqcache_table_pattern_size; /* size of the regex pattern array */
+
+ /*
+ * add for watchdog
+ */
+ int wd_port; /* watchdog port */
+ WdDesc * other_wd; /* watchdog lists */
+ char * trusted_servers; /* icmp reachable server list (A,B,C) */
+ char * delegate_IP; /* delegate IP address */
+ int wd_interval; /* lifecheck interval (sec) */
+ char * ping_path; /* path to ping command */
+ char * ifconfig_path; /* path to ifconfig command */
+ char * if_up_cmd; /* ifup command */
+ char * if_down_cmd; /* ifdown command */
+ int wd_life_point; /* life point (retry times at lifecheck) */
} POOL_CONFIG;
typedef enum {
diff --git a/pool_config.l b/pool_config.l
index aaf3c301d..63e2b706b 100644
--- a/pool_config.l
+++ b/pool_config.l
@@ -130,6 +130,17 @@ int pool_init_config(void)
}
#endif
+ /*
+ * add for watchdog
+ */
+ pool_config->other_wd = malloc(sizeof(WdDesc));
+ if (pool_config->other_wd == NULL)
+ {
+ pool_error("failed to allocate pool_config->cwother_wd");
+ return -1;
+ }
+ memset(pool_config->other_wd,0,sizeof(WdDesc));
+
/* set hardcoded default values */
pool_config->listen_addresses = "localhost";
pool_config->port = 9999;
@@ -216,6 +227,20 @@ int pool_init_config(void)
pool_config->lists_patterns = NULL;
pool_config->pattc = 0;
pool_config->current_pattern_size = 0;
+ /*
+ * add for watchdog
+ */
+ pool_config->trusted_servers = NULL;
+ pool_config->delegate_IP = NULL;
+ pool_config->wd_port = 9000;
+ pool_config->other_wd->num_wd = 0;
+ pool_config->wd_interval = 10;
+ pool_config->ping_path = "/bin";
+ pool_config->ifconfig_path = "/sbin";
+ pool_config->if_up_cmd = "ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0";
+ pool_config->if_down_cmd = "ifconfig eth0:0 down";
+ pool_config->wd_life_point = 3;
+
pool_config->memory_cache_enabled = 0;
pool_config->memqcache_method = "shmem";
@@ -1842,6 +1867,206 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
pool_config->lobj_lock_table = str;
}
+ /*
+ * add for watchdog
+ */
+ else if (!strncmp(key, "other_pgpool_hostname", 21) &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context) &&
+ mypid == getpid()) /* this parameter must be modified by parent pid */
+ {
+ int slot;
+ char *str;
+
+ slot = atoi(key + 21) ;
+ if (slot < 0 || slot >= MAX_CONNECTION_SLOTS)
+ {
+ pool_error("pool_config: pgpool number %s for other_pgpool_hostname out of range", key);
+ fclose(fd);
+ return(-1);
+ }
+
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ if (context == INIT_CONFIG || (context == RELOAD_CONFIG ))
+ strlcpy(WD_INFO(slot).hostname, str, WD_MAX_HOST_NAMELEN);
+ }
+
+ else if (!strncmp(key, "other_pgpool_port", 17) &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context) &&
+ mypid == getpid()) /* this parameter must be modified by parent pid */
+ {
+ int slot;
+
+ slot = atoi(key + 17);
+ if (slot < 0 || slot >= MAX_CONNECTION_SLOTS)
+ {
+ pool_error("pool_config: pgpool number %s for other_pgpool_port out of range", key);
+ fclose(fd);
+ return(-1);
+ }
+
+ if (context == INIT_CONFIG || (context == RELOAD_CONFIG ))
+ WD_INFO(slot).pgpool_port = atoi(yytext);
+ }
+
+ else if (!strncmp(key, "other_pgpool_wd_port", 20) &&
+ CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context) &&
+ mypid == getpid()) /* this parameter must be modified by parent pid */
+ {
+ int slot;
+
+ slot = atoi(key + 20);
+ if (slot < 0 || slot >= MAX_CONNECTION_SLOTS)
+ {
+ pool_error("pool_config: pgpool number %s for other_pgpool_wd_port out of range", key);
+ fclose(fd);
+ return(-1);
+ }
+
+ if (context == INIT_CONFIG || (context == RELOAD_CONFIG ))
+ {
+ WD_INFO(slot).wd_port = atoi(yytext);
+ WD_INFO(slot).status = WD_INIT;
+ pool_config->other_wd->num_wd = slot+1;
+ }
+ }
+ else if (!strcmp(key, "trusted_servers") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->trusted_servers = str;
+ }
+ else if (!strcmp(key, "delegate_IP") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->delegate_IP = str;
+ }
+ else if (!strcmp(key, "wd_interval") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ int v = atoi(yytext);
+
+ if (token != POOL_INTEGER || v <= 0)
+ {
+ pool_error("pool_config: %s must be higher than 1 numeric value", key);
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->wd_interval = v;
+ }
+ else if (!strcmp(key, "ping_path") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->ping_path = str;
+ }
+ else if (!strcmp(key, "ifconfig_path") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->ifconfig_path = str;
+ }
+ else if (!strcmp(key, "if_up_cmd") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->if_up_cmd = str;
+ }
+ else if (!strcmp(key, "if_down_cmd") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->if_down_cmd = str;
+ }
+ else if (!strcmp(key, "wd_life_point") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ int v = atoi(yytext);
+
+ if (token != POOL_INTEGER || v <= 0)
+ {
+ pool_error("pool_config: %s must be higher than 1 numeric value", key);
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->wd_life_point = v;
+ }
+
else if (!strcmp(key, "ssl") && CHECK_CONTEXT(INIT_CONFIG, context))
{
diff --git a/watchdog/Makefile.am b/watchdog/Makefile.am
new file mode 100644
index 000000000..707f1961f
--- /dev/null
+++ b/watchdog/Makefile.am
@@ -0,0 +1,15 @@
+noinst_LIBRARIES = lib-watchdog.a
+
+lib_watchdog_a_SOURCES = \
+ watchdog.c \
+ watchdog.h \
+ wd_child.c \
+ wd_ext.h \
+ wd_if.c \
+ wd_init.c \
+ wd_lifecheck.c \
+ wd_list.c \
+ wd_packet.c \
+ wd_ping.c
+
+AM_CPPFLAGS = -D_GNU_SOURCE -I .. -I @PGSQL_INCLUDE_DIR@
diff --git a/watchdog/Makefile.in b/watchdog/Makefile.in
new file mode 100644
index 000000000..2ddc1ac15
--- /dev/null
+++ b/watchdog/Makefile.in
@@ -0,0 +1,492 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = watchdog
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/c-compiler.m4 \
+ $(top_srcdir)/c-library.m4 $(top_srcdir)/general.m4 \
+ $(top_srcdir)/ac_func_accept_argtypes.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+lib_watchdog_a_AR = $(AR) $(ARFLAGS)
+lib_watchdog_a_LIBADD =
+am_lib_watchdog_a_OBJECTS = watchdog.$(OBJEXT) wd_child.$(OBJEXT) \
+ wd_if.$(OBJEXT) wd_init.$(OBJEXT) wd_lifecheck.$(OBJEXT) \
+ wd_list.$(OBJEXT) wd_packet.$(OBJEXT) wd_ping.$(OBJEXT)
+lib_watchdog_a_OBJECTS = $(am_lib_watchdog_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(lib_watchdog_a_SOURCES)
+DIST_SOURCES = $(lib_watchdog_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PGCONFIG = @PGCONFIG@
+PGSQL_INCLUDE_DIR = @PGSQL_INCLUDE_DIR@
+PGSQL_LIB_DIR = @PGSQL_LIB_DIR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = lib-watchdog.a
+lib_watchdog_a_SOURCES = \
+ watchdog.c \
+ watchdog.h \
+ wd_child.c \
+ wd_ext.h \
+ wd_if.c \
+ wd_init.c \
+ wd_lifecheck.c \
+ wd_list.c \
+ wd_packet.c \
+ wd_ping.c
+
+AM_CPPFLAGS = -D_GNU_SOURCE -I .. -I @PGSQL_INCLUDE_DIR@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu watchdog/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu watchdog/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+lib-watchdog.a: $(lib_watchdog_a_OBJECTS) $(lib_watchdog_a_DEPENDENCIES)
+ -rm -f lib-watchdog.a
+ $(lib_watchdog_a_AR) lib-watchdog.a $(lib_watchdog_a_OBJECTS) $(lib_watchdog_a_LIBADD)
+ $(RANLIB) lib-watchdog.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/watchdog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_child.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_if.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_init.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_lifecheck.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_packet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wd_ping.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/watchdog/test/stab.c b/watchdog/test/stab.c
new file mode 100644
index 000000000..0ad42c394
--- /dev/null
+++ b/watchdog/test/stab.c
@@ -0,0 +1,266 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <wait.h>
+
+#include "pool.h"
+#include "pool_config.h"
+
+#define MAXSTRFTIME 128
+
+int debug = 0;
+
+
+static char *nowsec(void);
+static void child_wait(int signo);
+
+void pool_error(const char *fmt,...)
+{
+ va_list ap;
+#ifdef HAVE_ASPRINTF
+ char *fmt2;
+ int len;
+#endif
+
+#ifdef HAVE_SIGPROCMASK
+ sigset_t oldmask;
+#else
+ int oldmask;
+#endif
+ /* Write error message to syslog */
+ if (pool_config->logsyslog == 1) {
+ va_start(ap, fmt);
+ vsyslog(pool_config->syslog_facility | LOG_ERR, fmt, ap);
+ va_end(ap);
+ return;
+ }
+
+ POOL_SETMASK2(&BlockSig, &oldmask);
+
+ if (pool_config->print_timestamp)
+#ifdef HAVE_ASPRINTF
+ len = asprintf(&fmt2, "%s ERROR: pid %d: %s\n", nowsec(), (int)getpid(), fmt);
+ else
+ len = asprintf(&fmt2, "ERROR: pid %d: %s\n", (int)getpid(), fmt);
+
+ if (len >= 0 && fmt2)
+ {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt2, ap);
+ va_end(ap);
+ fflush(stderr);
+ free(fmt2);
+ }
+#else
+ fprintf(stderr, "%s ERROR: pid %d: ", nowsec(), (int)getpid());
+ else
+ fprintf(stderr, "ERROR: pid %d: ", (int)getpid());
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+#endif
+
+ POOL_SETMASK(&oldmask);
+}
+
+void pool_debug(const char *fmt,...)
+{
+ va_list ap;
+#ifdef HAVE_ASPRINTF
+ char *fmt2;
+ int len;
+#endif
+
+#ifdef HAVE_SIGPROCMASK
+ sigset_t oldmask;
+#else
+ int oldmask;
+#endif
+
+ if (1)
+ {
+ if (!debug)
+ return;
+ }
+ else
+ {
+ if (pool_config->debug_level <= 0)
+ return;
+ }
+ /* Write debug message to syslog */
+ if (pool_config->logsyslog == 1) {
+ va_start(ap, fmt);
+ vsyslog(pool_config->syslog_facility | LOG_DEBUG, fmt, ap);
+ va_end(ap);
+ return;
+ }
+
+ POOL_SETMASK2(&BlockSig, &oldmask);
+
+ if (pool_config->print_timestamp)
+#ifdef HAVE_ASPRINTF
+ len = asprintf(&fmt2, "%s DEBUG: pid %d: %s\n", nowsec(), (int)getpid(), fmt);
+ else
+ len = asprintf(&fmt2, "DEBUG: pid %d: %s\n", (int)getpid(), fmt);
+
+ if (len >= 0 && fmt2)
+ {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt2, ap);
+ va_end(ap);
+ fflush(stderr);
+ free(fmt2);
+ }
+#else
+ fprintf(stderr, "%s DEBUG: pid %d: ", nowsec(), (int)getpid());
+ else
+ fprintf(stderr, "DEBUG: pid %d: ", (int)getpid());
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+#endif
+
+ POOL_SETMASK(&oldmask);
+}
+
+void pool_log(const char *fmt,...)
+{
+ va_list ap;
+#ifdef HAVE_ASPRINTF
+ char *fmt2;
+ int len;
+#endif
+
+#ifdef HAVE_SIGPROCMASK
+ sigset_t oldmask;
+#else
+ int oldmask;
+#endif
+ /* Write log message to syslog */
+ if (pool_config->logsyslog == 1) {
+ va_start(ap, fmt);
+ vsyslog(pool_config->syslog_facility | LOG_NOTICE, fmt, ap);
+ va_end(ap);
+ return;
+ }
+
+ POOL_SETMASK2(&BlockSig, &oldmask);
+
+ if (pool_config->print_timestamp)
+#ifdef HAVE_ASPRINTF
+ len = asprintf(&fmt2, "%s LOG: pid %d: %s\n", nowsec(), (int)getpid(), fmt);
+ else
+ len = asprintf(&fmt2, "LOG: pid %d: %s\n", (int)getpid(), fmt);
+
+ if (len >= 0 && fmt2)
+ {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt2, ap);
+ va_end(ap);
+ fflush(stderr);
+ free(fmt2);
+ }
+#else
+ fprintf(stderr, "%s LOG: pid %d: ", nowsec(), (int)getpid());
+ else
+ fprintf(stderr, "LOG: pid %d: ", (int)getpid());
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+#endif
+
+ POOL_SETMASK(&oldmask);
+}
+
+static char *nowsec(void)
+{
+ static char strbuf[MAXSTRFTIME];
+ time_t now = time(NULL);
+
+ strftime(strbuf, MAXSTRFTIME, "%Y-%m-%d %H:%M:%S", localtime(&now));
+ return strbuf;
+}
+
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0)
+ {
+ while (--n != 0)
+ {
+ if ((*d++ = *s++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0)
+ {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return (s - src - 1); /* count does not include NUL */
+}
+
+static void
+child_wait(int signo)
+{
+ pid_t pid = 0;
+
+ do {
+ int ret;
+ pid = waitpid(-1,&ret,WNOHANG);
+ } while(pid > 0);
+}
+
+void
+wd_exit(int exit_signo)
+{
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+
+ wd_notice_server_down();
+
+ pool_shmem_exit(1);
+
+ kill (0, exit_signo);
+
+ child_wait(0);
+
+ exit(0);
+}
+
+int pool_memset_system_db_info (SystemDBInfo *info)
+{
+ return 0;
+}
+
+int
+pool_query_cache_table_exists(void)
+{
+ return 0;
+}
+
diff --git a/watchdog/test/test.c b/watchdog/test/test.c
new file mode 100644
index 000000000..56440be43
--- /dev/null
+++ b/watchdog/test/test.c
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+#include "wd_ext.h"
+
+pid_t mypid;
+
+static void wdlist_dump(void);
+extern void wd_exit(int exit_signo);
+
+int
+main(int argc, char * argv[])
+{
+ int rtn;
+
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, wd_exit);
+ signal(SIGQUIT, wd_exit);
+ signal(SIGTERM, wd_exit);
+ signal(SIGPIPE, SIG_IGN);
+
+ mypid = getpid();
+ rtn = pool_init_config();
+
+ pool_config->recovery_user = "mitani";
+ pool_config->trusted_servers = "paris";
+ pool_config->delegate_IP = "192.168.100.99";
+ pool_config->pgpool2_hostname = "vm1";
+ pool_config->port = 5432;
+ pool_config->wd_port = 9999;
+ pool_config->other_wd->num_wd = 2;
+ strcpy(pool_config->other_wd->wd_info[0].hostname ,"vm2");
+ pool_config->other_wd->wd_info[0].pgpool_port = 5432;
+ pool_config->other_wd->wd_info[0].wd_port = 9999;
+ pool_config->other_wd->wd_info[0].status = WD_INIT;
+ strcpy(pool_config->other_wd->wd_info[1].hostname ,"paris");
+ pool_config->other_wd->wd_info[1].pgpool_port = 5432;
+ pool_config->other_wd->wd_info[1].wd_port = 9999;
+ pool_config->other_wd->wd_info[1].status = WD_INIT;
+ pool_config->ping_path = "/bin";
+ pool_config->ifconfig_path = "/sbin";
+ pool_config->if_up_cmd = "ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0";
+ pool_config->if_down_cmd = "ifconfig eth0:0 down";
+ pool_config->wd_interval = 3;
+ pool_config->wd_life_point = 1;
+
+ wd_main(3);
+
+ for (;;)
+ {
+ wdlist_dump();
+ sleep(5);
+ }
+ wd_exit(15);
+
+}
+
+
+static void
+wdlist_dump(void)
+{
+ int i;
+ WdInfo * p = WD_List;
+
+ i = 0;
+ while (p->status != WD_END)
+ {
+ printf("%d:s[%d] ts[%d] tu[%d] h[%s] pp[%d] wp[%d]\n",
+ i,p->status,
+ p->tv.tv_sec, p->tv.tv_usec,
+ p->hostname,
+ p->pgpool_port,
+ p->wd_port);
+ p++;
+ i++;
+ }
+}
diff --git a/watchdog/test/wd_child_t.c b/watchdog/test/wd_child_t.c
new file mode 100644
index 000000000..b9e69e847
--- /dev/null
+++ b/watchdog/test/wd_child_t.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+#include "wd_ext.h"
+
+pid_t mypid;
+WdInfo * WD_List = NULL; /* watchdog server list */
+
+static void wdlist_dump(void);
+extern void wd_exit(int exit_signo);
+
+int
+main(int argc, char * argv[])
+{
+ int rtn;
+
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, wd_exit);
+ signal(SIGQUIT, wd_exit);
+ signal(SIGTERM, wd_exit);
+ signal(SIGPIPE, SIG_IGN);
+
+ mypid = getpid();
+ rtn = pool_init_config();
+
+ pool_config->recovery_user = "mitani";
+ pool_config->trusted_servers = "paris";
+ pool_config->delegate_IP = "192.168.100.99";
+ pool_config->pgpool2_hostname = "vm1";
+ pool_config->port = 5432;
+ pool_config->wd_port = 9999;
+ pool_config->other_wd->num_wd = 2;
+ strcpy(pool_config->other_wd->wd_info[0].hostname ,"vm2");
+ pool_config->other_wd->wd_info[0].pgpool_port = 5432;
+ pool_config->other_wd->wd_info[0].wd_port = 9999;
+ pool_config->other_wd->wd_info[0].status = WD_INIT;
+ strcpy(pool_config->other_wd->wd_info[1].hostname ,"paris");
+ pool_config->other_wd->wd_info[1].pgpool_port = 5432;
+ pool_config->other_wd->wd_info[1].wd_port = 9999;
+ pool_config->other_wd->wd_info[1].status = WD_INIT;
+ pool_config->ping_path = "/bin";
+ pool_config->ifconfig_path = "/sbin";
+ pool_config->if_up_cmd = "ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0";
+ pool_config->if_down_cmd = "ifconfig eth0:0 down";
+ pool_config->wd_interval = 3;
+ pool_config->wd_life_point = 1;
+
+ wd_init();
+
+ wd_child(1);
+
+ for (;;)
+ {
+ wdlist_dump();
+ sleep(5);
+ }
+
+}
+
+
+static void
+wdlist_dump(void)
+{
+ int i;
+ WdInfo * p = WD_List;
+
+ i = 0;
+ while (p->status != WD_END)
+ {
+ printf("%d:s[%d] ts[%d] tu[%d] h[%s] pp[%d] wp[%d]\n",
+ i,p->status,
+ p->tv.tv_sec, p->tv.tv_usec,
+ p->hostname,
+ p->pgpool_port,
+ p->wd_port);
+ p++;
+ i++;
+ }
+}
diff --git a/watchdog/test/wd_lifecheck_t.c b/watchdog/test/wd_lifecheck_t.c
new file mode 100644
index 000000000..e1628287d
--- /dev/null
+++ b/watchdog/test/wd_lifecheck_t.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+#include "wd_ext.h"
+
+pid_t mypid;
+WdInfo * WD_List = NULL; /* watchdog server list */
+
+static void wdlist_dump(void);
+extern void wd_exit(int exit_signo);
+
+int
+main(int argc, char * argv[])
+{
+ int rtn;
+
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, wd_exit);
+ signal(SIGQUIT, wd_exit);
+ signal(SIGTERM, wd_exit);
+ signal(SIGPIPE, SIG_IGN);
+
+ mypid = getpid();
+ rtn = pool_init_config();
+
+ pool_config->recovery_user = "mitani";
+ pool_config->trusted_servers = "paris";
+ pool_config->delegate_IP = "192.168.100.99";
+ pool_config->pgpool2_hostname = "vm1";
+ pool_config->port = 5432;
+ pool_config->wd_port = 9999;
+ pool_config->other_wd->num_wd = 2;
+ strcpy(pool_config->other_wd->wd_info[0].hostname ,"vm2");
+ pool_config->other_wd->wd_info[0].pgpool_port = 5432;
+ pool_config->other_wd->wd_info[0].wd_port = 9999;
+ pool_config->other_wd->wd_info[0].status = WD_INIT;
+ strcpy(pool_config->other_wd->wd_info[1].hostname ,"paris");
+ pool_config->other_wd->wd_info[1].pgpool_port = 5432;
+ pool_config->other_wd->wd_info[1].wd_port = 9999;
+ pool_config->other_wd->wd_info[1].status = WD_INIT;
+ pool_config->ping_path = "/bin";
+ pool_config->ifconfig_path = "/sbin";
+ pool_config->if_up_cmd = "ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0";
+ pool_config->if_down_cmd = "ifconfig eth0:0 down";
+ pool_config->wd_interval = 3;
+ pool_config->wd_life_point = 1;
+
+ wd_init();
+
+ for (;;)
+ {
+ wdlist_dump();
+ wd_lifecheck();
+ sleep(pool_config->wd_interval);
+ }
+ wd_exit(15);
+
+}
+
+
+static void
+wdlist_dump(void)
+{
+ int i;
+ WdInfo * p = WD_List;
+
+ i = 0;
+ while (p->status != WD_END)
+ {
+ printf("%d:s[%d] ts[%d] tu[%d] h[%s] pp[%d] wp[%d]\n",
+ i,p->status,
+ p->tv.tv_sec, p->tv.tv_usec,
+ p->hostname,
+ p->pgpool_port,
+ p->wd_port);
+ p++;
+ i++;
+ }
+}
diff --git a/watchdog/test/wd_packet_t.c b/watchdog/test/wd_packet_t.c
new file mode 100644
index 000000000..0740a117e
--- /dev/null
+++ b/watchdog/test/wd_packet_t.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+#include "wd_ext.h"
+
+pid_t mypid;
+WdInfo * WD_List = NULL; /* watchdog server list */
+
+static void wdlist_dump(void);
+extern void wd_exit(int exit_signo);
+
+int
+main(int argc, char * argv[])
+{
+ int rtn;
+
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, wd_exit);
+ signal(SIGQUIT, wd_exit);
+ signal(SIGTERM, wd_exit);
+ signal(SIGPIPE, SIG_IGN);
+
+ mypid = getpid();
+ rtn = pool_init_config();
+
+ pool_config->recovery_user = "mitani";
+ pool_config->trusted_servers = "paris";
+ pool_config->delegate_IP = "192.168.100.99";
+ pool_config->pgpool2_hostname = "vm1";
+ pool_config->port = 5432;
+ pool_config->wd_port = 9999;
+ pool_config->other_wd->num_wd = 2;
+ strcpy(pool_config->other_wd->wd_info[0].hostname ,"vm2");
+ pool_config->other_wd->wd_info[0].pgpool_port = 5432;
+ pool_config->other_wd->wd_info[0].wd_port = 9999;
+ pool_config->other_wd->wd_info[0].status = WD_INIT;
+ strcpy(pool_config->other_wd->wd_info[1].hostname ,"paris");
+ pool_config->other_wd->wd_info[1].pgpool_port = 5432;
+ pool_config->other_wd->wd_info[1].wd_port = 9999;
+ pool_config->other_wd->wd_info[1].status = WD_INIT;
+ pool_config->ping_path = "/bin";
+ pool_config->ifconfig_path = "/sbin";
+ pool_config->if_up_cmd = "ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0";
+ pool_config->if_down_cmd = "ifconfig eth0:0 down";
+ pool_config->wd_interval = 3;
+ pool_config->wd_life_point = 1;
+
+ wd_init();
+
+ for (;;)
+ {
+ wdlist_dump();
+ sleep(5);
+ wd_lifecheck();
+ }
+ wd_exit(15);
+
+}
+
+
+static void
+wdlist_dump(void)
+{
+ int i;
+ WdInfo * p = WD_List;
+
+ i = 0;
+ while (p->status != WD_END)
+ {
+ printf("%d:s[%d] ts[%d] tu[%d] h[%s] pp[%d] wp[%d]\n",
+ i,p->status,
+ p->tv.tv_sec, p->tv.tv_usec,
+ p->hostname,
+ p->pgpool_port,
+ p->wd_port);
+ p++;
+ i++;
+ }
+}
diff --git a/watchdog/test/wd_ping_t.c b/watchdog/test/wd_ping_t.c
new file mode 100644
index 000000000..0b90178f9
--- /dev/null
+++ b/watchdog/test/wd_ping_t.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include "watchdog.h"
+
+extern int wd_is_upper_ok(char * server_list);
+
+int
+main(int argc,char * argv[])
+{
+ int rtn;
+ rtn = wd_is_upper_ok(argv[1]);
+ if (rtn == WD_OK)
+ {
+ printf("%s is ok",argv[1]);
+ }
+ else
+ {
+ printf("%s is ng",argv[1]);
+ }
+ return 0;
+}
diff --git a/watchdog/watchdog.c b/watchdog/watchdog.c
new file mode 100644
index 000000000..fee2cad31
--- /dev/null
+++ b/watchdog/watchdog.c
@@ -0,0 +1,125 @@
+/*
+ * $Header$
+ *
+ * Handles watchdog connection, and protocol communication with pgpool-II
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <wait.h>
+#include <ctype.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+#include "wd_ext.h"
+
+WdInfo * WD_List = NULL; /* watchdog server list */
+
+int wd_main(int fork_wait_time);
+static void child_wait(int signo);
+static void wd_exit(int exit_status);
+
+static void
+child_wait(int signo)
+{
+ pid_t pid = 0;
+
+ do {
+ int ret;
+ pid = waitpid(-1,&ret,WNOHANG);
+ } while(pid > 0);
+}
+
+static void
+wd_exit(int exit_signo)
+{
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+
+ wd_notice_server_down();
+
+ kill (0, exit_signo);
+
+ child_wait(0);
+
+ exit(0);
+}
+
+int
+wd_main(int fork_wait_time)
+{
+ int status = WD_INIT;
+ pid_t pgid = 0;
+ pid_t pid = 0;
+
+ /* initialize */
+ status = wd_init();
+ if (status < 0)
+ {
+ return WD_NG;
+ }
+
+ /* launch child process */
+ status = wd_child(1);
+ if (status != WD_OK)
+ {
+ return WD_NG;
+ }
+
+ pgid = getpgid(0);
+ pid = fork();
+ if (pid != 0)
+ {
+ return WD_OK;
+ }
+
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, wd_exit);
+ signal(SIGQUIT, wd_exit);
+ signal(SIGTERM, wd_exit);
+ signal(SIGPIPE, SIG_IGN);
+ setpgid(0,pgid);
+
+ if (fork_wait_time > 0) {
+ sleep(fork_wait_time);
+ }
+
+ /* watchdog loop */
+ for (;;)
+ {
+ /* pgpool life check */
+ wd_lifecheck();
+ sleep(pool_config->wd_interval);
+ }
+}
diff --git a/watchdog/watchdog.h b/watchdog/watchdog.h
new file mode 100644
index 000000000..38cce57ef
--- /dev/null
+++ b/watchdog/watchdog.h
@@ -0,0 +1,112 @@
+/* -*-pgsql-c-*- */
+/*
+ *
+ * $Header$
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * watchdog.h.: watchdog definition header file
+ *
+ */
+
+#ifndef WATCHDOG_H
+#define WATCHDOG_H
+
+#include <sys/time.h>
+#include "libpq-fe.h"
+
+#define WD_MAX_HOST_NAMELEN (128)
+#define MAX_WATCHDOG_NUM (128)
+#define WD_SEND_TIMEOUT (1)
+
+#define WD_INFO(wd_id) (pool_config->other_wd->wd_info[(wd_id)])
+
+#define WD_NG (0)
+#define WD_OK (1)
+
+/*
+ * packet number of watchdog negotiation
+ */
+typedef enum {
+ WD_INVALID = 0, /* invalid packet no */
+ WD_ADD_REQ, /* add request into the watchdog list */
+ WD_ADD_ACCEPT, /* accept the add request */
+ WD_ADD_REJECT, /* reject the add request */
+ WD_STAND_FOR_MASTER, /* announce candidacy */
+ WD_VOTE_YOU, /* agree to the candidacy */
+ WD_MASTER_EXIST, /* disagree to the candidacy */
+ WD_DECLARE_NEW_MASTER, /* announce assumption */
+ WD_SERVER_DOWN, /* announce server down */
+ WD_READY /* answer to the announce */
+} WD_PACKET_NO;
+
+/*
+ * watchdog status
+ */
+typedef enum {
+ WD_END = 0,
+ WD_INIT,
+ WD_NORMAL,
+ WD_MASTER,
+ WD_DOWN
+}WD_STATUS;
+
+/*
+ * watchdog list
+ */
+typedef struct {
+ WD_STATUS status; /* status */
+ struct timeval tv; /* startup time value */
+ char hostname[WD_MAX_HOST_NAMELEN]; /* host name */
+ int pgpool_port; /* pgpool port */
+ int wd_port; /* watchdog port */
+ int life; /* life point */
+}WdInfo;
+
+typedef struct {
+ int num_wd; /* number of watchdogs */
+ WdInfo wd_info[MAX_WATCHDOG_NUM];
+} WdDesc;
+
+/*
+ * negotiation paket
+ */
+typedef struct {
+ WD_PACKET_NO packet_no; /* packet number */
+ WdInfo wd_info; /* watchdog information */
+} WdPacket;
+
+/*
+ * thread argument for watchdog negotiation
+ */
+typedef struct {
+ int sock; /* socket */
+ WdInfo * target; /* target watchdog information */
+ WdPacket * packet; /* packet data */
+} WdPacketThreadArg;
+
+/*
+ * thread argument for lifecheck of pgpool
+ */
+typedef struct {
+ PGconn * conn; /* PGconn */
+ int retry; /* retry times */
+} WdPgpoolThreadArg;
+
+extern WdInfo * WD_List;
+
+#endif /* WATCHDOG_H */
diff --git a/watchdog/wd_child.c b/watchdog/wd_child.c
new file mode 100644
index 000000000..b976986fd
--- /dev/null
+++ b/watchdog/wd_child.c
@@ -0,0 +1,199 @@
+/* -*-pgsql-c-*- */
+/*
+ * $Header$
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * child.c: child process main
+ *
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include "watchdog.h"
+#include "wd_ext.h"
+
+int wd_child(int fork_wait_time);
+static void child_exit(int exit_signo);
+static int send_response(int sock, WdPacket * recv_pack);
+
+int
+wd_child(int fork_wait_time)
+{
+ int sock;
+ int fd;
+ int rtn;
+ pid_t pgid = 0;
+ pid_t pid = 0;
+
+ pgid = getpgid(0);
+ pid = fork();
+ if (pid != 0)
+ {
+ return WD_OK;
+ }
+
+ signal(SIGTERM, child_exit);
+ signal(SIGINT, child_exit);
+ signal(SIGQUIT, child_exit);
+ signal(SIGCHLD, child_exit);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGUSR1, SIG_IGN);
+ signal(SIGUSR2, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGALRM, SIG_IGN);
+ setpgid(0,pgid);
+
+ if (fork_wait_time > 0)
+ {
+ sleep(fork_wait_time);
+ }
+ if (WD_List == NULL)
+ {
+ /* memory allocate is not ready */
+ child_exit(15);
+ }
+ sock = wd_create_recv_socket(WD_List->wd_port);
+ if (sock < 0)
+ {
+ /* socket create failed */
+ child_exit(15);
+ }
+ /* child loop */
+ for(;;)
+ {
+ WdPacket buf;
+ fd = wd_accept(sock);
+ if (fd < 0)
+ {
+ continue;
+ }
+ rtn = wd_recv_packet(fd, &buf);
+ if (rtn == WD_OK)
+ {
+ send_response(fd,&buf);
+ }
+ close(fd);
+ }
+}
+
+static void
+child_exit(int exit_signo)
+{
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+
+ exit(0);
+}
+
+static int
+send_response(int sock, WdPacket * recv_pack)
+{
+ int rtn = WD_NG;
+ WdInfo * p;
+ WdPacket send_packet;
+ struct timeval tv;
+
+ if (recv_pack == NULL)
+ {
+ return rtn;
+ }
+ memset(&send_packet, 0, sizeof(WdPacket));
+ p = &(recv_pack->wd_info);
+
+ /* set response packet no */
+ switch (recv_pack->packet_no)
+ {
+ case WD_ADD_REQ:
+ p = &(recv_pack->wd_info);
+ if (wd_set_wd_list(p->hostname,p->pgpool_port, p->wd_port, &(p->tv), p->status) > 0)
+ {
+ send_packet.packet_no = WD_ADD_ACCEPT;
+ }
+ else
+ {
+ send_packet.packet_no = WD_ADD_REJECT;
+ }
+ memcpy(&(send_packet.wd_info), WD_List, sizeof(WdInfo));
+ break;
+ case WD_STAND_FOR_MASTER:
+ p = &(recv_pack->wd_info);
+ wd_set_wd_list(p->hostname,p->pgpool_port, p->wd_port, &(p->tv), p->status);
+ /* check exist master */
+ if ((p = wd_is_exist_master()) != NULL)
+ {
+ /* vote against the candidate */
+ send_packet.packet_no = WD_MASTER_EXIST;
+ memcpy(&(send_packet.wd_info), p, sizeof(WdInfo));
+ }
+ else
+ {
+ if (WD_List->tv.tv_sec <= p->tv.tv_sec )
+ {
+ memcpy(&tv,&(p->tv),sizeof(struct timeval));
+ tv.tv_sec += 1;
+ wd_set_myself(&tv, WD_NORMAL);
+ }
+ /* vote for the candidate */
+ send_packet.packet_no = WD_VOTE_YOU;
+ memcpy(&(send_packet.wd_info), WD_List, sizeof(WdInfo));
+ }
+ break;
+ case WD_DECLARE_NEW_MASTER:
+ p = &(recv_pack->wd_info);
+ wd_set_wd_list(p->hostname,p->pgpool_port, p->wd_port, &(p->tv), p->status);
+ if (WD_List->status == WD_MASTER)
+ {
+ /* resign master server */
+ wd_IP_down();
+ wd_set_myself(NULL, WD_NORMAL);
+ }
+ send_packet.packet_no = WD_READY;
+ memcpy(&(send_packet.wd_info), WD_List, sizeof(WdInfo));
+ break;
+ case WD_SERVER_DOWN:
+ p = &(recv_pack->wd_info);
+ wd_set_wd_list(p->hostname,p->pgpool_port, p->wd_port, &(p->tv), WD_DOWN);
+ send_packet.packet_no = WD_READY;
+ memcpy(&(send_packet.wd_info), WD_List, sizeof(WdInfo));
+ if (wd_am_I_oldest() == WD_OK)
+ {
+ wd_escalation();
+ }
+ break;
+ defalt:
+ send_packet.packet_no = WD_INVALID;
+ memcpy(&(send_packet.wd_info), WD_List, sizeof(WdInfo));
+ break;
+ }
+
+ /* send response packet */
+ rtn = wd_send_packet(sock, &send_packet);
+ return rtn;
+}
diff --git a/watchdog/wd_ext.h b/watchdog/wd_ext.h
new file mode 100644
index 000000000..6c8114e05
--- /dev/null
+++ b/watchdog/wd_ext.h
@@ -0,0 +1,67 @@
+/* -*-pgsql-c-*- */
+/*
+ *
+ * $Header$
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * wd_ext.h.: watchdog extern definition header file
+ *
+ */
+
+#ifndef WD_EXT_H
+#define WD_EXT_H
+/* watchdog.c */
+extern int wd_main(int fork_wait_time);
+
+/* wd_child.c */
+extern int wd_child(int fork_wait_time);
+
+/* wd_init.c */
+extern int wd_init(void);
+
+/* wd_list.c */
+extern int wd_set_wd_list(char * hostname, int pgpool_port, int wd_port, struct timeval * tv, int status);
+extern int wd_add_wd_list(WdDesc * other_wd);
+extern int wd_set_wd_info(WdInfo * info);
+extern WdInfo * wd_is_exist_master(void);
+extern int wd_am_I_oldest(void);
+extern int wd_set_myself(struct timeval * tv, int status);
+
+/* wd_packet.c */
+extern int wd_startup(void);
+extern int wd_declare(void);
+extern int wd_stand_for_master(void);
+extern int wd_notice_server_down(void);
+extern int wd_create_send_socket(char * hostname, int port);
+extern int wd_create_recv_socket(int port);
+extern int wd_accept(int sock);
+extern int wd_send_packet(int sock, WdPacket * snd_pack);
+extern int wd_recv_packet(int sock, WdPacket * buf);
+extern int wd_escalation(void);
+
+/* wd_ping.c */
+extern int wd_is_upper_ok(char * server_list);
+
+/* wd_if.c */
+extern int wd_IP_up(void);
+extern int wd_IP_down(void);
+
+/* wd_lifecheck.c */
+extern int wd_lifecheck(void);
+
+#endif /* WD_EXT_H */
diff --git a/watchdog/wd_if.c b/watchdog/wd_if.c
new file mode 100644
index 000000000..9e349ab97
--- /dev/null
+++ b/watchdog/wd_if.c
@@ -0,0 +1,144 @@
+/*
+ * $Header$
+ *
+ * Handles watchdog connection, and protocol communication with pgpool-II
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+
+int wd_IP_up(void);
+int wd_IP_down(void);
+static int exec_ifconfig(char * command);
+
+int
+wd_IP_up(void)
+{
+ int rtn;
+ rtn = exec_ifconfig(pool_config->if_up_cmd);
+ return rtn;
+}
+int
+wd_IP_down(void)
+{
+ int rtn;
+ rtn = exec_ifconfig(pool_config->if_down_cmd);
+ return rtn;
+}
+
+static int
+exec_ifconfig(char * command)
+{
+ int pfd[2];
+ int status;
+ char * args[24];
+ int pid, i = 0;
+ char ifconfig_path[128];
+ char buf[256];
+ char *bp, *ep;
+
+ sprintf(ifconfig_path,"%s/ifconfig",pool_config->ifconfig_path);
+ if (pipe(pfd) == -1)
+ {
+ pool_error("pipe open error:%s",strerror(errno));
+ return WD_NG;
+ }
+ memset(buf,0,sizeof(buf));
+ strncpy(buf,command,sizeof(buf));
+ bp = buf;
+ while (*bp == ' ')
+ {
+ bp ++;
+ }
+ while (*bp != '\0')
+ {
+ ep = strchr(bp,' ');
+ if (ep != NULL)
+ {
+ *ep = '\0';
+ }
+ if (!strncmp(bp,"$_IP_$",5))
+ {
+ args[i++] = pool_config->delegate_IP;
+ }
+ else
+ {
+ args[i++] = bp;
+ }
+ if (ep != NULL)
+ {
+ bp = ep +1;
+ while (*bp == ' ')
+ {
+ bp ++;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ args[i++] = NULL;
+
+ pid = fork();
+ if (pid == 0)
+ {
+ close(STDOUT_FILENO);
+ dup2(pfd[1], STDOUT_FILENO);
+ close(pfd[0]);
+ status = execv(ifconfig_path,args);
+ exit(0);
+ }
+ else
+ {
+ close(pfd[1]);
+ for (;;)
+ {
+ int result;
+ result = wait(&status);
+ if (result < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return WD_NG;
+ }
+
+ if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0)
+ return WD_NG;
+ else
+ break;
+ }
+ close(pfd[0]);
+ }
+ return WD_OK;
+}
+
+
diff --git a/watchdog/wd_init.c b/watchdog/wd_init.c
new file mode 100644
index 000000000..43494eca2
--- /dev/null
+++ b/watchdog/wd_init.c
@@ -0,0 +1,79 @@
+/*
+ * $Header$
+ *
+ * Handles watchdog connection, and protocol communication with pgpool-II
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+#include "wd_ext.h"
+
+int wd_init(void);
+
+int
+wd_init(void)
+{
+ struct timeval tv;
+
+ /* set startup time */
+ gettimeofday(&tv, NULL);
+
+ /* allocate watchdog list */
+ if (WD_List == NULL)
+ {
+ WD_List = pool_shared_memory_create(sizeof(WdInfo) * MAX_WATCHDOG_NUM);
+ if (WD_List == NULL)
+ {
+ pool_error("failed to allocate watchdog list");
+ return WD_NG;
+ }
+ memset(WD_List, 0, sizeof(WdInfo) * MAX_WATCHDOG_NUM);
+ }
+ /* set myself to watchdog list */
+ wd_set_wd_list(pool_config->pgpool2_hostname, pool_config->port, pool_config->wd_port, &tv, WD_NORMAL);
+ /* set other pgpools to watchdog list */
+ wd_add_wd_list(pool_config->other_wd);
+
+ /* check upper connection */
+ if (wd_is_upper_ok(pool_config->trusted_servers) != WD_OK)
+ {
+ pool_error("failed to connect trusted server");
+ return WD_NG;
+ }
+
+ /* send startup packet */
+ wd_startup();
+
+ /* check existence of master pgpool */
+ if (wd_is_exist_master() == NULL )
+ {
+ /* escalate to delegate_IP holder */
+ wd_escalation();
+ }
+
+ return WD_OK;
+}
diff --git a/watchdog/wd_lifecheck.c b/watchdog/wd_lifecheck.c
new file mode 100644
index 000000000..220fda66e
--- /dev/null
+++ b/watchdog/wd_lifecheck.c
@@ -0,0 +1,216 @@
+/*
+ * $Header$
+ *
+ * Handles watchdog connection, and protocol communication with pgpool-II
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ */
+#include <pthread.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <netdb.h>
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+#include "wd_ext.h"
+
+#include "libpq-fe.h"
+
+int wd_lifecheck(void);
+static void * ping_pgpool(void * arg);
+static PGconn * create_conn(char * hostname, int port);
+static int pgpool_down(WdInfo * pool);
+
+int
+wd_lifecheck(void)
+{
+ WdInfo * p = WD_List;
+ pthread_attr_t attr;
+ int rc;
+ int i,cnt;
+ struct timeval tv;
+ pthread_t thread[MAX_WATCHDOG_NUM];
+ WdPgpoolThreadArg thread_arg[MAX_WATCHDOG_NUM];
+
+ /* set startup time */
+ gettimeofday(&tv, NULL);
+
+ /* check upper connection */
+ if (wd_is_upper_ok(pool_config->trusted_servers) != WD_OK)
+ {
+ pool_error("failed to connect trusted server");
+ /* This server connection may be downwd */
+ if (p->status == WD_MASTER)
+ {
+ wd_IP_down();
+ }
+ wd_set_myself(&tv, WD_DOWN);
+ wd_notice_server_down();
+ return WD_NG;
+ }
+
+ /* thread init */
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ /* send packet to all watchdogs */
+ cnt = 0;
+ while (p->status != WD_END)
+ {
+ thread_arg[cnt].conn = create_conn(p->hostname, p->pgpool_port);
+ rc = pthread_create(&thread[cnt], &attr, ping_pgpool, (void*)&thread_arg[cnt]);
+ p ++;
+ cnt ++;
+ if (cnt >= MAX_WATCHDOG_NUM)
+ {
+ pool_error("trusted server num is out of range(%d)",cnt);
+ break;
+ }
+ }
+ pthread_attr_destroy(&attr);
+ p = WD_List;
+ for (i = 0; i < cnt; )
+ {
+ int result;
+ rc = pthread_join(thread[i], (void **)&result);
+ if ((rc != 0) && (errno == EINTR))
+ {
+ usleep(100);
+ continue;
+ }
+ if (result == WD_OK)
+ {
+ p->life = pool_config->wd_life_point;
+ if ((i == 0) &&
+ (WD_List->status == WD_DOWN))
+ {
+ wd_set_myself(&tv, WD_NORMAL);
+ wd_startup();
+ /* check existence of master pgpool */
+ if (wd_is_exist_master() == NULL )
+ {
+ /* escalate to delegate_IP holder */
+ wd_escalation();
+ }
+ }
+ }
+ else
+ {
+ if (p->life > 0)
+ {
+ p->life --;
+ }
+ if (p->life <= 0)
+ {
+ if ((i == 0) &&
+ (WD_List->status != WD_DOWN))
+ {
+ wd_set_myself(&tv, WD_DOWN);
+ wd_notice_server_down();
+ }
+ else
+ {
+ pgpool_down(p);
+ }
+ }
+ }
+ pthread_detach(thread[i]);
+ i++;
+ p++;
+ }
+ return WD_OK;
+}
+
+static void *
+ping_pgpool(void * arg)
+{
+ WdPgpoolThreadArg * thread_arg;
+ PGconn * conn;
+ uintptr_t rtn = (uintptr_t)WD_NG;
+ int status = PGRES_FATAL_ERROR;
+ PGresult * res = (PGresult *)NULL;
+ thread_arg = (WdPgpoolThreadArg *)arg;
+ conn = thread_arg->conn;
+
+ res = PQexec(conn, "SELECT 1" );
+
+ status = PQresultStatus(res);
+ if (res != NULL)
+ {
+ PQclear(res);
+ }
+ if ((status != PGRES_NONFATAL_ERROR ) &&
+ (status != PGRES_FATAL_ERROR ))
+ {
+ rtn = WD_OK;
+ }
+ PQfinish(conn);
+ pthread_exit((void *)rtn);
+}
+
+static PGconn *
+create_conn(char * hostname, int port)
+{
+ char port_str[16];
+ PGconn *conn;
+
+ snprintf(port_str, sizeof(port_str),
+ "%d", port);
+ conn = PQsetdbLogin(hostname,
+ port_str,
+ NULL,
+ NULL,
+ "template1",
+ pool_config->recovery_user,
+ pool_config->recovery_password);
+
+ if (PQstatus(conn) != CONNECTION_OK)
+ {
+ PQfinish(conn);
+ return NULL;
+ }
+ return conn;
+}
+
+static int
+pgpool_down(WdInfo * pool)
+{
+ int rtn = WD_DOWN;
+ if ((WD_List->status == WD_NORMAL) &&
+ (pool->status == WD_MASTER))
+ {
+ pool->status = WD_DOWN;
+ if (wd_am_I_oldest() == WD_OK)
+ {
+ /* stand for master */
+ rtn = wd_stand_for_master();
+ if (rtn == WD_OK)
+ {
+ /* win */
+ wd_escalation();
+ }
+ }
+ }
+ pool->status = WD_DOWN;
+ return rtn;
+}
diff --git a/watchdog/wd_list.c b/watchdog/wd_list.c
new file mode 100644
index 000000000..a883f66af
--- /dev/null
+++ b/watchdog/wd_list.c
@@ -0,0 +1,169 @@
+/*
+ * $Header$
+ *
+ * Handles watchdog connection, and protocol communication with pgpool-II
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+
+int wd_set_wd_list(char * hostname, int pgpool_port, int wd_port, struct timeval * tv, int status);
+int wd_add_wd_list(WdDesc * other_wd);
+int wd_set_wd_info(WdInfo * info);
+WdInfo * wd_is_exist_master(void);
+int wd_am_I_oldest(void);
+int wd_set_myself(struct timeval * tv, int status);
+
+int
+wd_set_wd_list(char * hostname, int pgpool_port, int wd_port, struct timeval * tv, int status)
+{
+ int i = 0;
+ WdInfo * p = NULL;
+
+ if ((WD_List == NULL) || (hostname == NULL))
+ {
+ pool_error("memory allocate error");
+ return -1;
+ }
+ for ( i = 0 ; i < MAX_WATCHDOG_NUM ; i ++)
+ {
+ p = (WD_List+i);
+ if( p->status != WD_END)
+ {
+ if ((!strncmp(p->hostname, hostname, sizeof(p->hostname))) &&
+ (p->pgpool_port == pgpool_port) &&
+ (p->wd_port == wd_port))
+ {
+ if (tv != NULL)
+ {
+ memcpy(&(p->tv),tv,sizeof(struct timeval));
+ }
+ p->status = status;
+ return i;
+ }
+ }
+ else
+ {
+ strncpy(p->hostname, hostname, sizeof(p->hostname));
+ p->pgpool_port = pgpool_port;
+ p->wd_port = wd_port;
+ if (tv != NULL)
+ {
+ memcpy(&(p->tv),tv,sizeof(struct timeval));
+ }
+ p->status = status;
+ return i;
+ }
+ }
+ pool_error("Can not add new watchdog information cause the WD_List is full.");
+ return -1;
+}
+
+int
+wd_add_wd_list(WdDesc * other_wd)
+{
+ WdInfo * p = NULL;
+ int i = 0;
+
+ if (other_wd == NULL)
+ {
+ pool_error("memory allocate error");
+ return -1;
+ }
+ for ( i = 0 ; i < other_wd->num_wd ; i ++)
+ {
+ p = &(other_wd->wd_info[i]);
+ wd_set_wd_info(p);
+ }
+ return i;
+}
+
+int
+wd_set_wd_info(WdInfo * info)
+{
+ int rtn;
+ rtn = wd_set_wd_list(info->hostname, info->pgpool_port, info->wd_port, &(info->tv), info->status);
+ return rtn;
+}
+
+WdInfo *
+wd_is_exist_master(void)
+{
+ WdInfo * p = WD_List;
+
+ p++;
+ while (p->status != WD_END)
+ {
+ /* find master pgpool in the other servers */
+ if (p->status == WD_MASTER)
+ {
+ /* master found */
+ return p;
+ }
+ p++;
+ }
+ /* not found */
+ return NULL;
+}
+
+int
+wd_am_I_oldest(void)
+{
+ WdInfo * p = WD_List;
+
+ p++;
+ while (p->status != WD_END)
+ {
+ if ((p->status == WD_NORMAL) ||
+ (p->status == WD_MASTER))
+ {
+ if ((p->tv.tv_sec < WD_List->tv.tv_sec) ||
+ ((p->tv.tv_sec == WD_List->tv.tv_sec) &&
+ (p->tv.tv_usec < WD_List->tv.tv_usec)))
+ {
+ return WD_NG;
+ }
+ }
+ p++;
+ }
+ return WD_OK;
+
+}
+
+int
+wd_set_myself(struct timeval * tv, int status)
+{
+ if (WD_List == NULL)
+ {
+ return WD_NG;
+ }
+ if (tv != NULL)
+ {
+ memcpy(&(WD_List->tv),tv,sizeof(struct timeval));
+ }
+ WD_List->status = status;
+ return WD_OK;
+}
diff --git a/watchdog/wd_packet.c b/watchdog/wd_packet.c
new file mode 100644
index 000000000..db12ca499
--- /dev/null
+++ b/watchdog/wd_packet.c
@@ -0,0 +1,630 @@
+/*
+ * $Header$
+ *
+ * Handles watchdog connection, and protocol communication with pgpool-II
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+#include "wd_ext.h"
+
+int wd_startup(void);
+int wd_declare(void);
+int wd_stand_for_master(void);
+int wd_notice_server_down(void);
+int wd_create_send_socket(char * hostname, int port);
+int wd_create_recv_socket(int port);
+int wd_accept(int sock);
+int wd_send_packet(int sock, WdPacket * snd_pack);
+int wd_recv_packet(int sock, WdPacket * buf);
+int wd_escalation(void);
+static void * wd_negotiation(void * arg);
+static int send_packet_4_all(WdPacket *packet);
+static int hton_wd_packet(WdPacket * to, WdPacket * from);
+static int ntoh_wd_packet(WdPacket * to, WdPacket * from);
+
+int
+wd_startup(void)
+{
+ int rtn;
+ WdPacket packet;
+
+ /* set add request packet */
+ packet.packet_no = WD_ADD_REQ;
+ memcpy(&(packet.wd_info),WD_List,sizeof(WdInfo));
+ /* send packet to all watchdogs */
+ rtn = send_packet_4_all(&packet);
+ return rtn;
+}
+
+int
+wd_declare(void)
+{
+ int rtn;
+ WdPacket packet;
+
+ /* set declare new master packet */
+ packet.packet_no = WD_DECLARE_NEW_MASTER;
+ memcpy(&(packet.wd_info),WD_List,sizeof(WdInfo));
+ /* send packet to all watchdogs */
+ rtn = send_packet_4_all(&packet);
+ return rtn;
+}
+
+int
+wd_stand_for_master(void)
+{
+ int rtn;
+ WdPacket packet;
+
+ /* set staqnd for master packet */
+ packet.packet_no = WD_STAND_FOR_MASTER;
+ memcpy(&(packet.wd_info),WD_List,sizeof(WdInfo));
+ /* send packet to all watchdogs */
+ rtn = send_packet_4_all(&packet);
+ return rtn;
+}
+
+int
+wd_notice_server_down(void)
+{
+ int rtn;
+ WdPacket packet;
+
+ wd_IP_down();
+ /* set notice server down packet */
+ packet.packet_no = WD_SERVER_DOWN;
+ memcpy(&(packet.wd_info),WD_List,sizeof(WdInfo));
+ /* send packet to all watchdogs */
+ rtn = send_packet_4_all(&packet);
+ return rtn;
+}
+
+int
+wd_create_send_socket(char * hostname, int port)
+{
+ int sock;
+ int one = 1;
+ size_t len = 0;
+ struct sockaddr_in addr;
+ struct hostent * hp;
+
+ /* create socket */
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ /* socket create failed */
+ return -1;
+ }
+
+ /* set socket option */
+ if ( setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1 )
+ {
+ return -1;
+ }
+ if ( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one)) == -1 )
+ {
+ return -1;
+ }
+
+ /* set sockaddr_in */
+ memset(&addr,0,sizeof(addr));
+ addr.sin_family = AF_INET;
+ hp = gethostbyname(hostname);
+ if ((hp == NULL) || (hp->h_addrtype != AF_INET))
+ {
+ hp = gethostbyaddr(hostname,strlen(hostname),AF_INET);
+ if ((hp == NULL) || (hp->h_addrtype != AF_INET))
+ {
+ pool_error("gethostbyname() failed: %s host: %s", hstrerror(h_errno), hostname);
+ close(sock);
+ return -1;
+ }
+ }
+ memmove((char *)&(addr.sin_addr), (char *)hp->h_addr, hp->h_length);
+ addr.sin_port = htons(port);
+ len = sizeof(struct sockaddr_in);
+
+ /* try to connect */
+ for (;;)
+ {
+ fd_set wmask;
+ fd_set emask;
+ struct timeval timeout;
+ int sockErrVal = 0;
+ int rtn;
+ socklen_t sockErrValLen = sizeof(int);
+
+ timeout.tv_sec = WD_SEND_TIMEOUT;
+ timeout.tv_usec = 0;
+
+ FD_ZERO(&wmask);
+ FD_ZERO(&emask);
+ FD_SET(sock,&wmask);
+ FD_SET(sock,&emask);
+
+ rtn = select(sock+1, NULL, &wmask, &emask, &timeout );
+ if ( rtn < 0 )
+ {
+ if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK )
+ {
+ continue;
+ }
+ /* connection failed */
+ break;
+ }
+ else if ( rtn == 0 )
+ {
+ /* timeout */
+ break;
+ }
+ else if ( FD_ISSET(sock, &emask) )
+ {
+ /* socket exception occured */
+ break;
+ }
+
+ if ( getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&sockErrVal, &sockErrValLen) == 0 && sockErrVal != 0 )
+ {
+ /* error occured on this socket while connecting to target */
+ break;
+ }
+
+ rtn = connect(sock,(struct sockaddr*)&addr, len);
+ if ( rtn < 0 )
+ {
+ if ( errno == EINPROGRESS || errno == EALREADY || errno == EWOULDBLOCK || errno == EINTR || errno == 0 )
+ continue;
+ else if ( errno == EISCONN )
+ {
+ return sock;
+ }
+ pool_error("connect() is failed,(%s)",strerror(errno));
+ break;
+ }
+ return sock;
+ }
+ close(sock);
+ return -1;
+}
+
+int
+wd_create_recv_socket(int port)
+{
+ size_t len = 0;
+ struct sockaddr_in addr;
+ int one = 1;
+ int sock = -1;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ /* socket create failed */
+ return -1;
+ }
+ if ( fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
+ {
+ /* failed to set nonblock */
+ close(sock);
+ return -1;
+ }
+ if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) == -1 )
+ {
+ /* setsockopt(SO_REUSEADDR) failed */
+ close(sock);
+ return -1;
+ }
+ if ( setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1 )
+ {
+ /* setsockopt(TCP_NODELAY) failed */
+ close(sock);
+ return -1;
+ }
+ if ( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one)) == -1 )
+ {
+ /* setsockopt(SO_KEEPALIVE) failed */
+ close(sock);
+ return -1;
+ }
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(port);
+ len = sizeof(struct sockaddr_in);
+
+ if ( bind(sock, (struct sockaddr *) & addr, len) < 0 )
+ {
+ /* bind failed */
+ close(sock);
+ return -1;
+ }
+
+ if ( listen(sock, MAX_WATCHDOG_NUM * 2) < 0 )
+ {
+ /* listen failed */
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int
+wd_accept(int sock)
+{
+ int fd = -1;
+ fd_set rmask;
+ fd_set emask;
+ int rtn;
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(struct sockaddr);
+
+ for (;;)
+ {
+ FD_ZERO(&rmask);
+ FD_ZERO(&emask);
+ FD_SET(sock,&rmask);
+ FD_SET(sock,&emask);
+
+ rtn = select(sock+1, &rmask, NULL, &emask, NULL );
+ if ( rtn < 0 )
+ {
+ if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK )
+ {
+ continue;
+ }
+ /* connection failed */
+ break;
+ }
+ else if ( rtn == 0 )
+ {
+ /* connection failed */
+ break;
+ }
+ else if ( FD_ISSET(sock, &emask) )
+ {
+ /* socket exception occured */
+ break;
+ }
+ else if ( FD_ISSET(sock, &rmask) )
+ {
+ fd = accept(sock, &addr, &addrlen);
+ if (fd < 0)
+ {
+ if ( errno == EINTR || errno == 0 || errno == EAGAIN || errno == EWOULDBLOCK )
+ {
+ /* nothing to accept now */
+ continue;
+ }
+ /* accept failed */
+ return -1;
+ }
+ return fd;
+ }
+ }
+ return -1;
+}
+
+int
+wd_send_packet(int sock, WdPacket * snd_pack)
+{
+ fd_set wmask;
+ struct timeval timeout;
+ char * send_ptr = NULL;
+ int send_size= 0;
+ int buf_size = 0;
+ int s = 0;
+ int flag = 0;
+ int rtn;
+ WdPacket buf;
+
+ memset(&buf,0,sizeof(WdPacket));
+ hton_wd_packet((WdPacket *)&buf,snd_pack);
+ send_ptr = (char*)&buf;
+ buf_size = sizeof(WdPacket);
+
+ for (;;)
+ {
+ timeout.tv_sec = WD_SEND_TIMEOUT;
+ timeout.tv_usec = 0;
+
+ FD_ZERO(&wmask);
+ FD_SET(sock,&wmask);
+ rtn = select(sock+1, (fd_set *)NULL, &wmask, (fd_set *)NULL, &timeout);
+
+ if (rtn < 0 )
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ {
+ continue;
+ }
+ return WD_NG;
+ }
+ else if (rtn & FD_ISSET(sock, &wmask))
+ {
+ s = send(sock,send_ptr + send_size,buf_size - send_size ,flag);
+ if (s < 0)
+ {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ else
+ {
+ /* send failed */
+ return WD_NG;
+ }
+ }
+ else if (s == 0)
+ {
+ /* send failed */
+ return WD_NG;
+ }
+ else /* s > 0 */
+ {
+ send_size += s;
+ if (send_size == buf_size)
+ {
+ return WD_OK;
+ }
+ }
+ }
+ }
+ return WD_NG;
+}
+
+int
+wd_recv_packet(int sock, WdPacket * recv_pack)
+{
+ int cnt = 0;
+ int r = 0;
+ WdPacket buf;
+ char * read_ptr = (char *)&buf;
+ int read_size = 0;
+ int len = sizeof(WdPacket);
+ cnt = 0;
+
+ memset(&buf,0,sizeof(WdPacket));
+ for (;;)
+ {
+ r = recv(sock,read_ptr + read_size ,len - read_size, 0);
+ if (r < 0)
+ {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ else
+ {
+ return WD_NG;
+ }
+ }
+ else if (r > 0)
+ {
+ read_size += r;
+ if (read_size == len)
+ {
+ ntoh_wd_packet(recv_pack,&buf);
+ return WD_OK;
+ }
+ }
+ else /* r == 0 */
+ {
+ return WD_NG;
+ }
+ }
+ return WD_NG;
+}
+
+static void *
+wd_negotiation(void * arg)
+{
+ WdPacketThreadArg * thread_arg;
+ int sock;
+ uintptr_t rtn;
+ WdPacket recv_packet;
+ WdInfo * p;
+
+ thread_arg = (WdPacketThreadArg *)arg;
+ sock = thread_arg->sock;
+
+ /* packet send to target watchdog */
+ rtn = (uintptr_t)wd_send_packet(sock, thread_arg->packet);
+ if (rtn != WD_OK)
+ {
+ close(sock);
+ pthread_exit((void *)rtn);
+ }
+
+ /* receive response packet */
+ memset(&recv_packet,0,sizeof(WdPacket));
+ rtn = (uintptr_t)wd_recv_packet(sock, &recv_packet);
+ if (rtn != WD_OK)
+ {
+ close(sock);
+ pthread_exit((void *)rtn);
+ }
+ rtn = WD_OK;
+ switch (thread_arg->packet->packet_no)
+ {
+ case WD_ADD_REQ:
+ if (recv_packet.packet_no == WD_ADD_ACCEPT)
+ {
+ memcpy(thread_arg->target, &(recv_packet.wd_info),sizeof(WdInfo));
+ }
+ else
+ {
+ rtn = WD_NG;
+ }
+ break;
+ case WD_STAND_FOR_MASTER:
+ if (recv_packet.packet_no == WD_MASTER_EXIST)
+ {
+ p = &(recv_packet.wd_info);
+ wd_set_wd_info(p);
+ rtn = WD_NG;
+ }
+ break;
+ case WD_DECLARE_NEW_MASTER:
+ if (recv_packet.packet_no != WD_READY)
+ {
+ rtn = WD_NG;
+ }
+ break;
+ default:
+ break;
+ }
+ close(sock);
+ pthread_exit((void *)rtn);
+}
+
+static int
+send_packet_4_all(WdPacket *packet)
+{
+ int rtn;
+ WdInfo * p = WD_List;
+ int i,cnt;
+ int sock;
+ int rc;
+ pthread_attr_t attr;
+ pthread_t thread[MAX_WATCHDOG_NUM];
+ WdPacketThreadArg thread_arg[MAX_WATCHDOG_NUM];
+
+ if (packet == NULL)
+ {
+ return WD_NG;
+ }
+
+ /* thread init */
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ /* send packet to all watchdogs */
+ p++;
+ cnt = 0;
+ while (p->status != WD_END)
+ {
+ sock = wd_create_send_socket(p->hostname, p->wd_port);
+ if (sock == -1)
+ {
+ p++;
+ continue;
+ }
+ thread_arg[cnt].sock = sock;
+ thread_arg[cnt].target = p;
+ thread_arg[cnt].packet = packet;
+ rc = pthread_create(&thread[cnt], &attr, wd_negotiation, (void*)&thread_arg[cnt]);
+ cnt ++;
+ p++;
+ }
+
+ pthread_attr_destroy(&attr);
+ rtn = (packet->packet_no == WD_STAND_FOR_MASTER)?WD_OK:WD_NG;
+ for (i=0; i<cnt; )
+ {
+ int result;
+ rc = pthread_join(thread[i], (void **)&result);
+ if ((rc != 0) && (errno == EINTR))
+ {
+ usleep(100);
+ continue;
+ }
+ if (packet->packet_no == WD_STAND_FOR_MASTER)
+ {
+ if (result == WD_NG)
+ {
+ rtn = WD_NG;
+ }
+ }
+ else
+ {
+ if (result == WD_OK)
+ {
+ rtn = WD_OK;
+ }
+ }
+ pthread_detach(thread[i]);
+ i++;
+ }
+
+ return rtn;
+}
+
+static int
+hton_wd_packet(WdPacket * to, WdPacket * from)
+{
+ if ((to == NULL) || (from == NULL))
+ {
+ return WD_NG;
+ }
+ to->packet_no = htonl(from->packet_no);
+ to->wd_info.status = htonl(from->wd_info.status);
+ to->wd_info.tv.tv_sec = htonl(from->wd_info.tv.tv_sec);
+ to->wd_info.tv.tv_usec = htonl(from->wd_info.tv.tv_usec);
+ to->wd_info.pgpool_port = htonl(from->wd_info.pgpool_port);
+ to->wd_info.wd_port = htonl(from->wd_info.wd_port);
+ memcpy(to->wd_info.hostname,from->wd_info.hostname,sizeof(to->wd_info.hostname));
+ return WD_OK;
+}
+
+static int
+ntoh_wd_packet(WdPacket * to, WdPacket * from)
+{
+ if ((to == NULL) || (from == NULL))
+ {
+ return WD_NG;
+ }
+ to->packet_no = ntohl(from->packet_no);
+ to->wd_info.status = ntohl(from->wd_info.status);
+ to->wd_info.tv.tv_sec = ntohl(from->wd_info.tv.tv_sec);
+ to->wd_info.tv.tv_usec = ntohl(from->wd_info.tv.tv_usec);
+ to->wd_info.pgpool_port = ntohl(from->wd_info.pgpool_port);
+ to->wd_info.wd_port = ntohl(from->wd_info.wd_port);
+ memcpy(to->wd_info.hostname,from->wd_info.hostname,sizeof(to->wd_info.hostname));
+ return WD_OK;
+}
+
+int
+wd_escalation(void)
+{
+ int rtn;
+
+ /* interface up as delegate IP */
+ wd_IP_up();
+ /* set master status to the wd list */
+ wd_set_wd_list(pool_config->pgpool2_hostname, pool_config->port, pool_config->wd_port, NULL, WD_MASTER);
+
+ /* send declare packet */
+ rtn = wd_declare();
+
+ return rtn;
+}
diff --git a/watchdog/wd_ping.c b/watchdog/wd_ping.c
new file mode 100644
index 000000000..2b134f615
--- /dev/null
+++ b/watchdog/wd_ping.c
@@ -0,0 +1,228 @@
+/*
+ * $Header$
+ *
+ * Handles watchdog connection, and protocol communication with pgpool-II
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2011 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "pool.h"
+#include "pool_config.h"
+#include "watchdog.h"
+
+int wd_is_upper_ok(char * server_list);
+
+static void * exec_ping(void * arg);
+static double get_result (char * ping_data);
+
+int
+wd_is_upper_ok(char * server_list)
+{
+ pthread_attr_t attr;
+ char * buf;
+ int rc = 0;
+ int i,cnt;
+ int len;
+ pthread_t thread[MAX_WATCHDOG_NUM];
+ WdInfo thread_arg[MAX_WATCHDOG_NUM];
+
+ char * bp, *ep;
+ int rtn = WD_NG;
+
+ if (server_list == NULL)
+ {
+ return WD_NG;
+ }
+ len = strlen(server_list)+2;
+ buf = malloc(len);
+ memset(buf,0,len);
+ strncpy(buf,server_list,len);
+ /* thread init */
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ /* set hostname as a thread_arg */
+ bp = buf;
+ cnt = 0;
+ while (*bp != '\0')
+ {
+ ep = strchr(bp,',');
+ if (ep != NULL)
+ {
+ *ep = '\0';
+ }
+ strncpy(thread_arg[cnt].hostname,bp,sizeof(thread_arg[cnt].hostname));
+ rc = pthread_create(&thread[cnt], &attr, exec_ping, (void*)&thread_arg[cnt]);
+
+ cnt ++;
+ if (ep != NULL)
+ {
+ bp = ep + 1;
+ }
+ else
+ {
+ break;
+ }
+ if (cnt >= MAX_WATCHDOG_NUM)
+ {
+ /*
+pool_error("trusted server num is out of range(%d)",cnt);
+ */
+ break;
+ }
+ }
+ pthread_attr_destroy(&attr);
+ for (i=0; i <cnt; )
+ {
+ int result;
+ rc = pthread_join(thread[i], (void **)&result);
+ if ((rc != 0) && (errno == EINTR))
+ {
+ usleep(100);
+ continue;
+ }
+ if (result == WD_OK)
+ {
+ rtn = WD_OK;
+ }
+ pthread_detach(thread[i]);
+ i++;
+ }
+ free(buf);
+ return rtn;
+}
+
+static void *
+exec_ping(void * arg)
+{
+ WdInfo * thread_arg;
+ uintptr_t rtn = (uintptr_t)WD_NG;
+ int pfd[2];
+ int status;
+ char * args[8];
+ int pid, i = 0;
+ int r_size = 0;
+ char result[256];
+ char ping_path[128];
+
+ sprintf(ping_path,"%s/ping",pool_config->ping_path);
+ thread_arg = (WdInfo *)arg;
+ memset(result,0,sizeof(result));
+ if (pipe(pfd) == -1)
+ {
+ fprintf(stderr,"pipe open error:%s\n",strerror(errno));
+ return NULL;
+ }
+
+ args[i++] = "ping";
+ args[i++] = "-q";
+ args[i++] = "-c3";
+ args[i++] = thread_arg->hostname;
+ args[i++] = NULL;
+
+ pid = fork();
+ if (pid == 0)
+ {
+ close(STDOUT_FILENO);
+ dup2(pfd[1], STDOUT_FILENO);
+ close(pfd[0]);
+ status = execv(ping_path,args);
+ exit(0);
+ }
+ else
+ {
+ close(pfd[1]);
+ for (;;)
+ {
+ int r;
+ r = wait(&status);
+ if (r < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return NULL;
+ }
+
+ if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0)
+ return NULL;
+ else
+ break;
+ }
+ i = 0;
+ while (( (r_size = read (pfd[0], &result[i], sizeof(result)-i)) > 0) && (errno == EINTR))
+ {
+ i += r_size;
+ }
+ close(pfd[0]);
+ }
+ rtn = (get_result (result) > 0)?WD_OK:WD_NG;
+ pthread_exit((void *)rtn);
+}
+
+static double
+get_result (char * ping_data)
+{
+ char * sp = NULL;
+ char * ep = NULL;
+ int i;
+ double msec = 0;
+
+ if (ping_data == NULL)
+ {
+ return -1;
+ }
+ /*
+ skip result until average data
+ tipical result of ping is as follows,
+ "rtt min/avg/max/mdev = 0.045/0.045/0.046/0.006 ms"
+ we can find the average data beyond the 4th '/'.
+ */
+ sp = ping_data;
+ for ( i = 0 ; i < 4 ; i ++)
+ {
+ sp = strchr(sp,'/');
+ if (sp == NULL)
+ {
+ return -1;
+ }
+ sp ++;
+ }
+ ep = strchr (sp,'/');
+ if (ep == NULL)
+ {
+ return -1;
+ }
+ *ep = '\0';
+ errno = 0;
+ /* convert to numeric data from text */
+ msec = strtod(sp,(char **)NULL);
+ if (errno != 0)
+ {
+ return -1;
+ }
+ return msec;
+}
[parent: 1cd60b0597de]