Skip to Content.
Sympa Menu

sm-commit - [SM-Commit] GIT changes to master grimoire by George Sherwood (69a3b0643fbf2e99a7dafb6fd1783c495e9b1b9e)

sm-commit AT lists.ibiblio.org

Subject: Source Mage code commit list

List archive

Chronological Thread  
  • From: George Sherwood <scm AT mail.sourcemage.org>
  • To: sm-commit AT lists.ibiblio.org
  • Subject: [SM-Commit] GIT changes to master grimoire by George Sherwood (69a3b0643fbf2e99a7dafb6fd1783c495e9b1b9e)
  • Date: Tue, 12 Dec 2006 12:01:03 -0600

GIT changes to master grimoire by George Sherwood <chat AT sourcemage.org>:

database/postgresql/DETAILS | 4
database/postgresql/HISTORY | 6
database/postgresql/PRE_BUILD | 3
database/postgresql/pgcluster-1.5.0rc7-smgl-patch |30328
--------------------
database/postgresql/pgcluster-1.7.0rc1-patch.tar.gz |binary
5 files changed, 10 insertions(+), 30331 deletions(-)

New commits:
commit 69a3b0643fbf2e99a7dafb6fd1783c495e9b1b9e
Author: George Sherwood <chat AT sourcemage.org>
Commit: George Sherwood <chat AT sourcemage.org>

postgresql: Updated to version 8.2.0. Updated pgcluster patch. Keep
patch as a tar.gz since it is over 2MEG now.

diff --git a/database/postgresql/DETAILS b/database/postgresql/DETAILS
index 08933cf..9528f91 100755
--- a/database/postgresql/DETAILS
+++ b/database/postgresql/DETAILS
@@ -1,6 +1,6 @@
SPELL=postgresql
- VERSION=8.1.5
-
SOURCE_HASH=sha512:26e9756a46c7d604b6ebfbfdadcc191bfed5028df822a4b0a61d7daba476ea3e49d70542f1c3a6f3a8196ae6888be84fb573bfe20d5ac35189646656393c7721
+ VERSION=8.2.0
+
SOURCE_HASH=sha512:c172bf84996cb6c466ba871c28b6b2e9c4e2f06d56a64b1a4289e3e5456170e9481e12d4626b263623c3654878617c1734bec47c21e788a74c2f8e0187b0b51c
SOURCE=$SPELL-$VERSION.tar.bz2
SOURCE_DIRECTORY=$BUILD_DIRECTORY/$SPELL-$VERSION
SOURCE_URI=v$VERSION/$SOURCE
diff --git a/database/postgresql/HISTORY b/database/postgresql/HISTORY
index 825273b..3c8d474 100644
--- a/database/postgresql/HISTORY
+++ b/database/postgresql/HISTORY
@@ -1,3 +1,9 @@
+2006-12-12 George Sherwood <george AT beernabeer.com>
+ * DETAILS: Updated to version 8.2.0.
+ * PRE_BUILD: Updated pgcluster patch. Keep patch as a tarball.
+ * pgcluster-1.5.0rc7-smgl.patch: Removed
+ * pgcluster-1.7.0rc1-patch.tar.gz: Added
+
2006-11-12 Flavien Bridault <vlaaad AT sourcemage.org>
* TRIGGERS: Restored to get the trigger on linux-pam cast, use of
if_depends_enabled
diff --git a/database/postgresql/PRE_BUILD b/database/postgresql/PRE_BUILD
index 05c5e75..86f2b83 100755
--- a/database/postgresql/PRE_BUILD
+++ b/database/postgresql/PRE_BUILD
@@ -2,5 +2,6 @@ create_account postgres &
default_pre_build &&
cd $SOURCE_DIRECTORY &&
if [ "$PGSQL_CLUSTER" = "y" ]; then
- patch -p1 < $SCRIPT_DIRECTORY/pgcluster-1.5.0rc7-smgl-patch
+ tar zxvf $SCRIPT_DIRECTORY/pgcluster-1.7.0rc1-patch.tar.gz &&
+ patch -p1 < $SOURCE_DIRECTORY/pgcluster-1.7.0rc1-patch
fi
diff --git a/database/postgresql/pgcluster-1.5.0rc7-smgl-patch
b/database/postgresql/pgcluster-1.5.0rc7-smgl-patch
deleted file mode 100644
index 9a8f385..0000000
--- a/database/postgresql/pgcluster-1.5.0rc7-smgl-patch
+++ /dev/null
@@ -1,30328 +0,0 @@
-diff -aruN postgresql-8.1.2/GNUmakefile.in pgcluster-1.5.0rc7/GNUmakefile.in
---- postgresql-8.1.2/GNUmakefile.in 2005-05-01 08:15:51.000000000 +0200
-+++ pgcluster-1.5.0rc7/GNUmakefile.in 2006-01-10 17:39:30.000000000 +0100
-@@ -57,13 +57,13 @@
-
- ##########################################################################
-
--distdir := postgresql-$(VERSION)
-+distdir := pgcluster-$(PGCLUSTER_VERSION)
- dummy := =install=
--garbage := =* "#"* ."#"* *~* *.orig *.rej core postgresql-*
-+garbage := =* "#"* ."#"* *~* *.orig *.rej core pgcluster-*
-
- dist: $(distdir).tar.gz
- ifeq ($(split-dist), yes)
--dist: postgresql-base-$(VERSION).tar.gz postgresql-docs-$(VERSION).tar.gz
postgresql-opt-$(VERSION).tar.gz postgresql-test-$(VERSION).tar.gz
-+dist: pgcluster-base-$(PGCLUSTER_VERSION).tar.gz
pgcluster-docs-$(PGCLUSTER_VERSION).tar.gz
pgcluster-opt-$(PGCLUSTER_VERSION).tar.gz
pgcluster-test-$(PGCLUSTER_VERSION).tar.gz
- endif
- dist:
- -rm -rf $(distdir)
-@@ -75,19 +75,19 @@
- src/tools src/tutorial \
- $(addprefix src/pl/, plperl plpython tcl)
-
--docs_files := doc/postgres.tar.gz doc/src doc/TODO.detail
-+docs_files := doc/pgcluster.tar.gz doc/src doc/TODO.detail
-
--postgresql-base-$(VERSION).tar: distdir
-+pgcluster-base-$(PGCLUSTER_VERSION).tar: distdir
- $(TAR) -c $(addprefix --exclude $(distdir)/, $(docs_files)
$(opt_files) src/test) \
- -f $@ $(distdir)
-
--postgresql-docs-$(VERSION).tar: distdir
-+pgcluster-docs-$(PGCLUSTER_VERSION).tar: distdir
- $(TAR) cf $@ $(addprefix $(distdir)/, $(docs_files))
-
--postgresql-opt-$(VERSION).tar: distdir
-+pgcluster-opt-$(PGCLUSTER_VERSION).tar: distdir
- $(TAR) cf $@ $(addprefix $(distdir)/, $(opt_files))
-
--postgresql-test-$(VERSION).tar: distdir
-+pgcluster-test-$(PGCLUSTER_VERSION).tar: distdir
- $(TAR) cf $@ $(distdir)/src/test
-
- distdir:
-diff -aruN postgresql-8.1.2/INSTALL_PGCLUSTER
pgcluster-1.5.0rc7/INSTALL_PGCLUSTER
---- postgresql-8.1.2/INSTALL_PGCLUSTER 1970-01-01 01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/INSTALL_PGCLUSTER 2006-02-09 17:55:54.000000000
+0100
-@@ -0,0 +1,286 @@
-+PGCluster Installation Instructions
-+
-+=============================================================
-+1. Installation
-+=============================================================
-+
-+1-1. Install Cluster DB Server, Replication Server & Load Balancer
-+----------------------------------------------------------------
-+$ cd $source_dir
-+$ ./configure
-+$ gmake
-+$ su
-+# gmake install
-+# chown -R postgres /usr/local/pgsql
-+----------------------------------------------------------------
-+
-+=============================================================
-+2. Initialize DB
-+=============================================================
-+$ su
-+# adduser postgres
-+# mkdir /usr/local/pgsql/data
-+# chown postgres /usr/local/pgsql/data
-+# su - postgres
-+$ /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
-+
-+
-+=============================================================
-+3. Configuration
-+=============================================================
-+(EX.System Composition)
-+
-+ |
-+ ((Load Balance Server))
-+ ( hostname: lb.hoo.com)
-+ ( receive port:5432 )
-+ ( recovery port:6001 )
-+ |
-+----------+-------------+------------+----------
-+ | |
-+ (( Cluster DB 1 )) (( Cluster DB 2 ))
-+ ( hostname:c1.hoo.com) ( hostname:c2.hoo.com)
-+ ( receive port: 5432 ) ( receive port:5432 )
-+ ( recovery port:7001 ) ( recovery port 7002 )
-+ | |
-+----------+-------------+------------+----------
-+ |
-+ ((Replication Server))
-+ ( hostname:pgr.hoo.com)
-+ ( receive port:8001 )
-+ ( recovery port:8101 )
-+
-+
-+3-1. Load Balance Server
-+
-+The setup file of load balance server is copied from the sample file and
edited.
-+(the sample file is installed '/usr/local/pgsql/share' in default)
-+----------------------------------------------------------------
-+$cd /usr/local/pgsql/share
-+$cp pglb.conf.sample pglb.conf
-+----------------------------------------------------------------
-+
-+In the case of the above system composition example,
-+the setup example of pglb.conf file is as the following
-+
-+#============================================================
-+# Load Balance Server configuration file
-+#-------------------------------------------------------------
-+# file: pglb.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts are db cluster server
-+# o which port use connect to db cluster server
-+# o how many connections are allowed on each DB server
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Max_Connection : maximun number of connection to postmaster
-+#-------------------------------------------------------------
-+<Cluster_Server_Info>
-+ <Host_Name> c1.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Max_Connect> 32 </Max_Connect>
-+</Cluster_Server_Info>
-+<Cluster_Server_Info>
-+ <Host_Name> c2.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Max_Connect> 32 </Max_Connect>
-+</Cluster_Server_Info>
-+#-------------------------------------------------------------
-+# set Load Balance server information
-+# o Receive_Port : connection from client
-+# o Recovery_Port : connection for recovery process
-+# o Max_Cluster_Num : maximun number of cluster DB servers
-+# o Use_Connection_Pooling : use connection pool [yes/no]
-+# o Max_Pool_Each_Server : number of pool connections/DB server
-+#-------------------------------------------------------------
-+<Receive_Port> 5432 </Receive_Port>
-+<Recovery_Port> 6001 </Recovery_Port>
-+<Max_Cluster_Num> 128 </Max_Cluster_Num>
-+<Use_Connection_Pooling> yes </Use_Connection_Pooling>
-+<Max_Pool_Each_Server> 1 </Max_Pool_Each_Server>
-+
-+3-2. Cluster DB Server
-+
-+The Cluster DB server need edit two configuration files
-+('pg_hba.conf' and 'cluster.conf').
-+These files are create under the $PG_DATA directory after 'initdb'.
-+
-+A. pg_hba.conf
-+Permission to connect DB via IP connectoins is need for this system.
-+
-+B. cluster.conf
-+In the case of the above system composition example,
-+the setup example of cluster.conf file is as the following
-+
-+#============================================================
-+# Cluster DB Server configuration file
-+#-------------------------------------------------------------
-+# file: cluster.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts & port are replication server
-+# o which port use for replication request to replication server
-+# o which command use for recovery function
-+#
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Recovery_Port : connection for recovery process
-+#-------------------------------------------------------------
-+<Replicate_Server_Info>
-+ <Host_Name> pgr.hoo.com </Host_Name>
-+ <Port> 8001 </Port>
-+ <Recovery_Port> 8101 </Recovery_Port>
-+</Replicate_Server_Info>
-+#-------------------------------------------------------------
-+# set Cluster DB Server information
-+# o Recovery_Port : connection for recovery
-+# o Rsync_Path : path of rsync command
-+# o Rsync_Option : file transfer option for rsync
-+# o When_Stand_Alone : When all replication servers fell,
-+# you can set up two kinds of permittion,
-+# "real_only" or "read_write".
-+#-------------------------------------------------------------
-+<Recovery_Port> 7001 </Recovery_Port>
-+<Rsync_Path> /usr/bin/rsync </Rsync_Path>
-+<Rsync_Option> ssh -1 </Rsync_Option>
-+<When_Stand_Alone> read_only </When_Stand_Alone>
-+#-------------------------------------------------------------
-+# set partitional replicate control information
-+# set DB name and Table name to stop reprication
-+# o DB_Name : DB name
-+# o Table_Name : table name
-+#-------------------------------------------------------------
-+#<Not_Replicate_Info>
-+# <DB_Name> test_db </DB_Name>
-+# <Table_Name> log_table </Table_Name>
-+#</Not_Replicate_Info>
-+
-+3-3. Replication Server
-+
-+The setup file of replication server is copied from the sample file and
edited.
-+(the sample file is installed '/usr/local/pgsql/share' in default)
-+----------------------------------------------------------------
-+$cd /usr/local/pgsql/share
-+$cp pgreplicate.conf.sample pgreplicate.conf
-+----------------------------------------------------------------
-+In the case of the above system composition example,
-+the setup example of pgreplicate.conf file is as the following
-+
-+#============================================================
-+# PGReplicate configuration file
-+#-------------------------------------------------------------
-+# file: pgreplicate.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts & port are cluster server
-+# o which port use for replication request from cluster server
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Recovery_Port : connection for recovery
-+#-------------------------------------------------------------
-+<Cluster_Server_Info>
-+ <Host_Name> c1.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Recovery_Port> 7001 </Recovery_Port>
-+</Cluster_Server_Info>
-+<Cluster_Server_Info>
-+ <Host_Name> c2.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Recovery_Port> 7001 </Recovery_Port>
-+</Cluster_Server_Info>
-+#-------------------------------------------------------------
-+# set Load Balance server information
-+# o Host_Name : hostname
-+# o Recovery_Port : connection for recovery
-+#-------------------------------------------------------------
-+<LoadBalance_Server_Info>
-+ <Host_Name> lb.hoo.com </Host_Name>
-+ <Recovery_Port> 6001 </Recovery_Port>
-+</LoadBalance_Server_Info>
-+#-------------------------------------------------------------
-+# A setup of a replication server
-+#
-+# o Replicate_Port : connection for replication
-+# o Recovery_Port : connection for recovery
-+# o Response_mode : timing which returns a response
-+# normal -- return result of DB which received the query
-+# reliable -- return result after waiting for response of
-+# all Cluster DBs.
-+# o Use_Replication_Log : use replication log
-+# [yes/no]. default : no
-+# o RLOG_Port : connection for replication log
-+#-------------------------------------------------------------
-+<Replication_Port> 8001 </Replication_Port>
-+<Recovery_Port> 8101 </Recovery_Port>
-+<Response_Mode> normal </Response_Mode>
-+<Use_Replication_Log> no </Use_Replication_Log>
-+<RLOG_Port> 8301 </RLOG_Port>
-+
-+=============================================================
-+4. Start Up / Stop
-+=============================================================
-+
-+4-1. replication server
-+
-+A. Start replication server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pgreplicate -D /usr/local/pgsql/etc
-+----------------------------------------------------------------
-+
-+B. Stop replication server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pgreplicate -D /usr/local/pgsql/etc stop
-+----------------------------------------------------------------
-+
-+usage: pgreplicate [-D path_of_config_file] [-W path_of_work_files] [-U
login us
-+er][-l][-n][-v][-h][stop]
-+ -l: print error logs in the log file.
-+ -n: don't run in daemon mode.
-+ -v: debug mode. need '-n' flag
-+ -h: print this help
-+ stop: stop pgreplicate
-+(config file default path: ./pgreplicate.conf)
-+
-+4-2. cluster DB server
-+$PG_HOME = /usr/local/pgsql
-+$PG_DATA = /usr/local/pgsql/data
-+
-+A. Start cluster DB server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -o "-i" start
-+----------------------------------------------------------------
-+
-+B. Stop cluster DB server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data stop
-+----------------------------------------------------------------
-+
-+4-3. load balance server
-+
-+A. Start load balance server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pglb -D /usr/local/pgsql/share
-+----------------------------------------------------------------
-+
-+B. Stop load balance server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pglb -D /usr/local/pgsql/share stop
-+----------------------------------------------------------------
-+
-+usage: pglb [-D path_of_config_file] [-W path_of_work_files]
[-n][-v][-h][stop]
-+ -l: print error logs in the log file.
-+ -n: don't run in daemon mode.
-+ -v: debug mode. need '-n' flag
-+ -h: print this help
-+ stop: stop pglb
-+ (config file default path: ./pglb.conf)
-diff -aruN postgresql-8.1.2/README_PGCLUSTER
pgcluster-1.5.0rc7/README_PGCLUSTER
---- postgresql-8.1.2/README_PGCLUSTER 1970-01-01 01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/README_PGCLUSTER 2006-01-10 17:39:32.000000000
+0100
-@@ -0,0 +1,47 @@
-+PGCluster: Multi-Master Synchronous Replication System for PostgreSQL
-+===========================================================
-+
-+PGCluster is a multi-master and synchronous replication system that
supports load balancing of PostgreSQL.
-+
-+Changed:
-+ src/Makefile.global.in
-+ src/backend/Makefile
-+ src/backend/libpq/Makefile
-+ src/backend/access/transam/clog.c
-+ src/backend/access/transam/xact.c
-+ src/backend/catalog/pg_depend.c
-+ src/backend/commands/analyze.c
-+ src/backend/commands/copy.c
-+ src/backend/commands/sequence.c
-+ src/backend/executor/functions.c
-+ src/backend/postmaster/postmaster.c
-+ src/backend/storage/lmgr/lock.c
-+ src/backend/tcop/postgres.c
-+ src/backend/utils/adt/float.c
-+ src/backend/utils/adt/misc.c
-+ src/backend/utils/adt/nabstime.c
-+ src/backend/utils/error/assert.c
-+ src/backend/utils/error/elog.c
-+ src/backend/utils/fmgr/dfmgr.c
-+ src/backend/utils/mb/mbutils.c
-+ src/bin/initdb/initdb.sh
-+
-+Added:
-+ src/include/replicate.h
-+ src/include/replicate_com.h
-+ src/backend/libpq/recovery.c
-+ src/backend/libpq/relicate.c
-+ src/backend/libpq/relicate_com.c
-+ src/backend/libpq/cluster.conf.sample
-+ src/pgcluster/*
-+
-+The latest version of this software may be obtained at
-+http://hiroshima.sraw.co.jp/people/mitani/jpug/pgcluster/en/current/last_night.html
-+<for Japanese>
-+http://hiroshima.sraw.co.jp/people/mitani/jpug/pgcluster/current/last_night.html
-+
-+For more information look at my web
-+site located at
-+http://hiroshima.sraw.co.jp/people/mitani/jpug/pgcluster/en/
-+<for Japanese>
-+http://hiroshima.sraw.co.jp/people/mitani/jpug/pgcluster/
-diff -aruN postgresql-8.1.2/configure pgcluster-1.5.0rc7/configure
---- postgresql-8.1.2/configure 2006-01-05 05:02:18.000000000 +0100
-+++ pgcluster-1.5.0rc7/configure 2006-02-09 17:47:19.000000000 +0100
-@@ -275,6 +275,8 @@
- PACKAGE_STRING='PostgreSQL 8.1.2'
- PACKAGE_BUGREPORT='pgsql-bugs AT postgresql.org'
-
-+PGCLUSTER_VERSION='1.5.0rc7'
-+
- ac_unique_file="src/backend/access/common/heaptuple.c"
- ac_default_prefix=/usr/local/pgsql
- # Factoring default headers for most tests.
-@@ -314,7 +316,7 @@
- # include <unistd.h>
- #endif"
-
--ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME
PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix
program_transform_name bindir sbindir libexecdir datadir sysconfdir
sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir
build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS
configure_args build build_cpu build_vendor build_os host host_cpu
host_vendor host_os PORTNAME docdir enable_nls WANTED_LANGUAGES default_port
enable_shared enable_rpath enable_debug CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC
EXEEXT OBJEXT CPP GCC TAS autodepend INCLUDES enable_thread_safety with_tcl
with_perl with_python with_krb5 krb_srvtab with_pam with_bonjour with_openssl
with_zlib EGREP ELF_SYS LDFLAGS_SL AWK FLEX FLEXFLAGS LN_S LD with_gnu_ld
ld_R_works RANLIB ac_ct_RANLIB LORDER TAR STRIP ac_ct_STRIP STRIP_STATIC_LIB
STRIP_SHARED_LIB YACC YFLAGS PERL perl_archlibexp perl_privlibexp
perl_useshrplib perl_embed_ldflags PYTHON python_version python_configdir
python_includespec python_libdir python_libspec python_additional_libs
HAVE_IPV6 LIBOBJS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS
HAVE_POSIX_SIGNALS MSGFMT MSGMERGE XGETTEXT localedir TCLSH TCL_CONFIG_SH
TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIBS TCL_LIB_SPEC TCL_SHARED_BUILD
TCL_SHLIB_LD_LIBS NSGMLS JADE have_docbook DOCBOOKSTYLE COLLATEINDEX SGMLSPL
vpath_build LTLIBOBJS'
-+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME
PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix
program_transform_name bindir sbindir libexecdir datadir sysconfdir
sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir
build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS
configure_args build build_cpu build_vendor build_os host host_cpu
host_vendor host_os PORTNAME docdir enable_nls WANTED_LANGUAGES default_port
enable_shared enable_rpath enable_debug CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC
EXEEXT OBJEXT CPP GCC TAS autodepend INCLUDES enable_thread_safety with_tcl
with_perl with_python with_krb5 krb_srvtab with_pam with_bonjour with_openssl
with_zlib EGREP ELF_SYS LDFLAGS_SL AWK FLEX FLEXFLAGS LN_S LD with_gnu_ld
ld_R_works RANLIB ac_ct_RANLIB LORDER TAR STRIP ac_ct_STRIP STRIP_STATIC_LIB
STRIP_SHARED_LIB YACC YFLAGS PERL perl_archlibexp perl_privlibexp
perl_useshrplib perl_embed_ldflags PYTHON python_version python_configdir
python_includespec python_libdir python_libspec python_additional_libs
HAVE_IPV6 LIBOBJS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS
HAVE_POSIX_SIGNALS MSGFMT MSGMERGE XGETTEXT localedir TCLSH TCL_CONFIG_SH
TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIBS TCL_LIB_SPEC TCL_SHARED_BUILD
TCL_SHLIB_LD_LIBS NSGMLS JADE have_docbook DOCBOOKSTYLE COLLATEINDEX SGMLSPL
vpath_build LTLIBOBJS PGCLUSTER_VERSION'
- ac_subst_files=''
-
- # Initialize some variables set by options.
-@@ -1238,6 +1240,10 @@
- #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
- _ACEOF
-
-+cat >>confdefs.h <<_ACEOF
-+#define PGCLUSTER_VERSION "$PGCLUSTER_VERSION"
-+_ACEOF
-+
-
- # Let the site file select an alternate cache file if it wants to.
- # Prefer explicitly selected file to automatically selected ones.
-@@ -1361,6 +1367,8 @@
-
-
-
-+
-+
- ac_aux_dir=
- for ac_dir in config $srcdir/config; do
- if test -f $ac_dir/install-sh; then
-@@ -23204,6 +23212,7 @@
- s,@host_os@,$host_os,;t t
- s,@PORTNAME@,$PORTNAME,;t t
- s,@docdir@,$docdir,;t t
-+s,@PGCLUSTER_VERSION@,$PGCLUSTER_VERSION,;t t
- s,@enable_nls@,$enable_nls,;t t
- s,@WANTED_LANGUAGES@,$WANTED_LANGUAGES,;t t
- s,@default_port@,$default_port,;t t
-diff -aruN postgresql-8.1.2/configure.in pgcluster-1.5.0rc7/configure.in
---- postgresql-8.1.2/configure.in 2006-01-05 05:02:23.000000000 +0100
-+++ pgcluster-1.5.0rc7/configure.in 2006-01-10 17:39:30.000000000 +0100
-@@ -27,6 +27,7 @@
- AC_SUBST(configure_args, [$ac_configure_args])
-
- AC_DEFINE_UNQUOTED(PG_VERSION, "$PACKAGE_VERSION", [PostgreSQL version])
-+AC_DEFINE_UNQUOTED(PGCLUSTER_VERSION, "$PGCLUSTER_VERSION", [PGCluster
version])
-
- AC_CANONICAL_HOST
-
-diff -aruN postgresql-8.1.2/pgcluster.sh.tmpl
pgcluster-1.5.0rc7/pgcluster.sh.tmpl
---- postgresql-8.1.2/pgcluster.sh.tmpl 1970-01-01 01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/pgcluster.sh.tmpl 2006-01-10 17:39:30.000000000
+0100
-@@ -0,0 +1,56 @@
-+#!/bin/sh
-+#
-+# $FreeBSD: ports/databases/pgcluster/files/pgcluster.sh.tmpl,v 1.1
2004/01/26 09:02:45 kuriyama Exp $
-+#
-+# PROVIDE: pgcluster
-+# REQUIRE: DAEMON
-+# BEFORE: pgreplicate
-+# KEYWORD: FreeBSD
-+#
-+# Add the following line to /etc/rc.conf to enable pgcluster:
-+#
-+# pgcluster_enable="YES"
-+# # optional
-+# pgcluster_data="/home/pgsql/data"
-+# pgcluster_flags="-w -s"
-+#
-+
-+pgcluster_enable="NO"
-+pgcluster_data="%%PREFIX%%/pgsql/data"
-+pgcluster_flags="-w -s"
-+
-+. %%RC_SUBR%%
-+
-+load_rc_config pgcluster
-+
-+name=pgcluster
-+command=%%PREFIX%%/bin/pg_ctl
-+pgcluster_user=pgsql
-+extra_commands="initdb recover"
-+initdb_cmd="pgcluster_initdb"
-+recover_cmd="pgcluster_recover"
-+start_cmd="pgcluster_start"
-+stop_cmd="pgcluster_stop"
-+
-+pgcluster_flags="${pgcluster_flags} -D ${pgcluster_data}"
-+pidfile="${pgcluster_data}/postmaster.pid"
-+
-+pgcluster_start()
-+{
-+ su -m ${pgcluster_user} -c "exec ${command} start ${pgcluster_flags} -o
'-i'"
-+}
-+pgcluster_stop()
-+{
-+ su -m ${pgcluster_user} -c "exec ${command} stop ${pgcluster_flags} -m
i"
-+}
-+pgcluster_recover()
-+{
-+ su -m ${pgcluster_user} -c "exec ${command} start ${pgcluster_flags} -o
'-i -R'"
-+}
-+pgcluster_initdb()
-+{
-+ su -m ${pgcluster_user} -c "exec %%PREFIX%%/bin/initdb -D
${pgcluster_data}"
-+}
-+
-+load_rc_config $name
-+run_rc_command "$1"
-diff -aruN postgresql-8.1.2/src/Makefile pgcluster-1.5.0rc7/src/Makefile
---- postgresql-8.1.2/src/Makefile 2005-01-13 19:23:21.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/Makefile 2006-01-10 17:39:48.000000000 +0100
-@@ -16,14 +16,15 @@
- all install installdirs uninstall dep depend distprep:
- $(MAKE) -C port $@
- $(MAKE) -C timezone $@
-+ $(MAKE) -C interfaces $@
- $(MAKE) -C backend $@
- $(MAKE) -C backend/utils/mb/conversion_procs $@
- $(MAKE) -C include $@
-- $(MAKE) -C interfaces $@
- $(MAKE) -C bin $@
- $(MAKE) -C pl $@
- $(MAKE) -C makefiles $@
- $(MAKE) -C utils $@
-+ $(MAKE) -C pgcluster $@
-
- install: install-local
-
-@@ -44,6 +45,7 @@
- rm -f $(addprefix $(DESTDIR)$(pgxsdir)/$(subdir), Makefile.global
Makefile.port Makefile.shlib nls-global.mk)
-
- clean:
-+ $(MAKE) -C pgcluster $@
- $(MAKE) -C port $@
- $(MAKE) -C timezone $@
- $(MAKE) -C backend $@
-@@ -58,6 +60,7 @@
- $(MAKE) -C tools/thread $@
-
- distclean maintainer-clean:
-+ -$(MAKE) -C pgcluster $@
- -$(MAKE) -C port $@
- -$(MAKE) -C timezone $@
- -$(MAKE) -C backend $@
-diff -aruN postgresql-8.1.2/src/Makefile.global.in
pgcluster-1.5.0rc7/src/Makefile.global.in
---- postgresql-8.1.2/src/Makefile.global.in 2005-09-27 19:39:32.000000000
+0200
-+++ pgcluster-1.5.0rc7/src/Makefile.global.in 2006-01-10 17:39:48.000000000
+0100
-@@ -31,6 +31,9 @@
- # PostgreSQL version number
- VERSION = @PACKAGE_VERSION@
-
-+# PGCluster version number
-+PGCLUSTER_VERSION = @PGCLUSTER_VERSION@
-+
- # Support for VPATH builds
- vpath_build = @vpath_build@
- abs_top_srcdir = @abs_top_srcdir@
-@@ -204,6 +207,7 @@
- GCC = @GCC@
- CFLAGS = @CFLAGS@
-
-+CFLAGS += -DUSE_REPLICATION -DPRINT_DEBUG
- # Kind-of compilers
-
- YACC = @YACC@
-diff -aruN postgresql-8.1.2/src/backend/Makefile
pgcluster-1.5.0rc7/src/backend/Makefile
---- postgresql-8.1.2/src/backend/Makefile 2005-10-27 22:45:29.000000000
+0200
-+++ pgcluster-1.5.0rc7/src/backend/Makefile 2006-01-10 17:39:39.000000000
+0100
-@@ -40,7 +40,7 @@
- ifneq ($(PORTNAME), win32)
- ifneq ($(PORTNAME), aix)
-
--postgres: $(OBJS)
-+postgres: $(OBJS) $(libpq_srcdir)/libpq.a
- $(CC) $(CFLAGS) $(LDFLAGS) $(export_dynamic) $^ $(LIBS) -o $@
-
- endif
-@@ -169,6 +169,7 @@
- $(INSTALL_DATA) $(srcdir)/libpq/pg_ident.conf.sample
$(DESTDIR)$(datadir)/pg_ident.conf.sample
- $(INSTALL_DATA) $(srcdir)/utils/misc/postgresql.conf.sample
$(DESTDIR)$(datadir)/postgresql.conf.sample
- $(INSTALL_DATA) $(srcdir)/access/transam/recovery.conf.sample
$(DESTDIR)$(datadir)/recovery.conf.sample
-+ $(INSTALL_DATA) $(srcdir)/libpq/cluster.conf.sample
$(DESTDIR)$(datadir)/cluster.conf.sample
-
- install-bin: postgres $(POSTGRES_IMP) installdirs
- $(INSTALL_PROGRAM) postgres$(X) $(DESTDIR)$(bindir)/postgres$(X)
-@@ -222,7 +223,8 @@
- rm -f $(DESTDIR)$(datadir)/pg_hba.conf.sample \
- $(DESTDIR)$(datadir)/pg_service.conf.sample \
- $(DESTDIR)$(datadir)/pg_ident.conf.sample \
-- $(DESTDIR)$(datadir)/postgresql.conf.sample
-+ $(DESTDIR)$(datadir)/postgresql.conf.sample \
-+ $(DESTDIR)$(datadir)/cluster.conf.sample
-
-
- ##########################################################################
-diff -aruN postgresql-8.1.2/src/backend/access/transam/xact.c
pgcluster-1.5.0rc7/src/backend/access/transam/xact.c
---- postgresql-8.1.2/src/backend/access/transam/xact.c 2005-11-22
19:23:05.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/access/transam/xact.c 2006-01-10
17:39:38.000000000 +0100
-@@ -46,6 +46,9 @@
- #include "utils/resowner.h"
- #include "pgstat.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*
- * User-tweakable parameters
-@@ -4280,3 +4283,11 @@
- else
- strcat(buf, "UNKNOWN");
- }
-+
-+#ifdef USE_REPLICATION
-+void
-+PGR_Reload_Start_Time(void)
-+{
-+ xactStartTimestamp = GetCurrentTimestamp();
-+}
-+#endif /* USE_REPLICATION */
-diff -aruN postgresql-8.1.2/src/backend/catalog/catalog.c
pgcluster-1.5.0rc7/src/backend/catalog/catalog.c
---- postgresql-8.1.2/src/backend/catalog/catalog.c 2005-10-15
04:49:12.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/catalog/catalog.c 2006-01-10
17:39:39.000000000 +0100
-@@ -29,6 +29,9 @@
- #include "utils/fmgroids.h"
- #include "utils/relcache.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- #define OIDCHARS 10 /* max chars printed by %u */
-
-@@ -293,7 +296,7 @@
- Oid
- GetNewOidWithIndex(Relation relation, Relation indexrel)
- {
-- Oid newOid;
-+ Oid newOid = 0;
- IndexScanDesc scan;
- ScanKeyData key;
- bool collides;
-@@ -301,8 +304,18 @@
- /* Generate new OIDs until we find one not in the table */
- do
- {
-+#ifdef USE_REPLICATION
-+ if (PGR_Is_Sync_OID == true)
-+ {
-+ newOid = PGRGetNewObjectId(newOid);
-+ }
-+ else
-+ {
-+ newOid = GetNewObjectId();
-+ }
-+#else
- newOid = GetNewObjectId();
--
-+#endif /* USE_REPLICATION */
- ScanKeyInit(&key,
- (AttrNumber) 1,
- BTEqualStrategyNumber, F_OIDEQ,
-@@ -386,3 +399,4 @@
-
- return rnode.relNode;
- }
-+
-diff -aruN postgresql-8.1.2/src/backend/commands/analyze.c
pgcluster-1.5.0rc7/src/backend/commands/analyze.c
---- postgresql-8.1.2/src/backend/commands/analyze.c 2005-11-22
19:23:06.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/commands/analyze.c 2006-01-10
17:39:34.000000000 +0100
-@@ -39,6 +39,9 @@
- #include "utils/syscache.h"
- #include "utils/tuplesort.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /* Data structure for Algorithm S from Knuth 3.4.2 */
- typedef struct
-@@ -936,7 +939,11 @@
- /* random() can produce endpoint values, try again if so */
- do
- {
-+#ifdef USE_REPLICATION
-+ z = (long) PGR_Random();
-+#else
- z = random();
-+#endif /* USE_REPLICATION */
- } while (z <= 0 || z >= MAX_RANDOM_VALUE);
- return (double) z / (double) MAX_RANDOM_VALUE;
- }
-diff -aruN postgresql-8.1.2/src/backend/commands/copy.c
pgcluster-1.5.0rc7/src/backend/commands/copy.c
---- postgresql-8.1.2/src/backend/commands/copy.c 2005-12-28
06:38:26.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/commands/copy.c 2006-01-10
17:39:34.000000000 +0100
-@@ -48,6 +48,9 @@
- #include "utils/relcache.h"
- #include "utils/syscache.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- #define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
- #define OCTVALUE(c) ((c) - '0')
-@@ -421,6 +424,9 @@
- CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
- {
- int bytesread = 0;
-+#ifdef USE_REPLICATION
-+ char * ptr = (char *)databuf;
-+#endif
-
- switch (cstate->copy_dest)
- {
-@@ -511,6 +517,9 @@
- }
- break;
- }
-+#ifdef USE_REPLICATION
-+ PGR_Set_Copy_Data(PGRCopyData,ptr,bytesread,0);
-+#endif /* USE_REPLICATION */
-
- return bytesread;
- }
-@@ -1921,6 +1930,13 @@
- }
- }
-
-+#ifdef USE_REPLICATION
-+ if (done)
-+ {
-+ PGR_Set_Copy_Data(PGRCopyData,(char *)NULL,0,1);
-+ }
-+#endif /* USE_REPLICATION */
-+
- /* Done, clean up */
- error_context_stack = errcontext.previous;
-
-@@ -2025,6 +2041,11 @@
- break;
- }
- }
-+#ifdef USE_REPLICATION
-+ /*
-+
PGR_Set_Copy_Data(PGRCopyData,cstate->line_buf.data,cstate->line_buf.len,0);
-+ */
-+#endif
-
- /* Done reading the line. Convert it to server encoding. */
- if (cstate->need_transcoding)
-diff -aruN postgresql-8.1.2/src/backend/commands/sequence.c
pgcluster-1.5.0rc7/src/backend/commands/sequence.c
---- postgresql-8.1.2/src/backend/commands/sequence.c 2005-11-22
19:23:07.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/commands/sequence.c 2006-01-10
17:39:34.000000000 +0100
-@@ -26,6 +26,9 @@
- #include "utils/resowner.h"
- #include "utils/syscache.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*
- * We don't want to log each fetching of a value from a sequence,
-@@ -385,6 +388,9 @@
- RangeVar *sequence;
- Oid relid;
-
-+#ifdef USE_REPLICATION
-+ Xlog_Check_Replicate(CMD_UTILITY);
-+#endif /* USE_REPLICATION */
- sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin));
- relid = RangeVarGetRelid(sequence, false);
-
-@@ -610,6 +616,10 @@
- SeqTable elm;
- Relation seqrel;
-
-+#ifdef USE_REPLICATION
-+ Xlog_Check_Replicate(CMD_UTILITY);
-+#endif /* USE_REPLICATION */
-+
- /* open and AccessShareLock sequence */
- init_sequence(relid, &elm, &seqrel);
-
-diff -aruN postgresql-8.1.2/src/backend/executor/functions.c
pgcluster-1.5.0rc7/src/backend/executor/functions.c
---- postgresql-8.1.2/src/backend/executor/functions.c 2005-11-22
19:23:08.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/executor/functions.c 2006-01-10
17:39:38.000000000 +0100
-@@ -32,6 +32,9 @@
- #include "utils/syscache.h"
- #include "utils/typcache.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*
- * We have an execution_state record for each query in a function. Each
-@@ -462,6 +465,13 @@
- Datum value;
- MemoryContext oldcontext;
-
-+#ifdef USE_REPLICATION
-+ if ((es != NULL) && (es->qd != NULL))
-+ {
-+ Xlog_Check_Replicate(es->qd->operation);
-+ }
-+#endif /* USE_REPLICATION */
-+
- if (es->status == F_EXEC_START)
- postquel_start(es, fcache);
-
-diff -aruN postgresql-8.1.2/src/backend/libpq/Makefile
pgcluster-1.5.0rc7/src/backend/libpq/Makefile
---- postgresql-8.1.2/src/backend/libpq/Makefile 2003-11-29
20:51:49.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/libpq/Makefile 2006-01-10
17:39:39.000000000 +0100
-@@ -15,7 +15,8 @@
- # be-fsstubs is here for historical reasons, probably belongs elsewhere
-
- OBJS = be-fsstubs.o be-secure.o auth.o crypt.o hba.o ip.o md5.o pqcomm.o \
-- pqformat.o pqsignal.o
-+ pqformat.o pqsignal.o \
-+ replicate.o replicate_com.o recovery.o
-
-
- all: SUBSYS.o
-diff -aruN postgresql-8.1.2/src/backend/libpq/be-fsstubs.c
pgcluster-1.5.0rc7/src/backend/libpq/be-fsstubs.c
---- postgresql-8.1.2/src/backend/libpq/be-fsstubs.c 2005-11-22
19:23:09.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/libpq/be-fsstubs.c 2006-01-10
17:39:39.000000000 +0100
-@@ -48,6 +48,9 @@
- #include "storage/large_object.h"
- #include "utils/memutils.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*#define FSDB 1*/
- #define BUFSIZE 8192
-@@ -93,6 +96,19 @@
- int fd;
- MemoryContext currentContext;
-
-+#ifdef USE_REPLICATION
-+ if ((PGR_Stand_Alone != NULL) &&
-+ (PGR_lo_open(lobjId,mode) != STATUS_OK))
-+ {
-+ if ((mode & INV_WRITE) &&
-+ (PGR_Is_Stand_Alone() == true) &&
-+ (PGR_Stand_Alone->permit == PERMIT_READ_ONLY) )
-+ {
-+ elog(WARNING, "This query is not permitted when all
replication servers fell down ");
-+ PG_RETURN_INT32(-1);
-+ }
-+ }
-+#endif /* USE_REPLICATION */
- #if FSDB
- elog(DEBUG4, "lo_open(%u,%d)", lobjId, mode);
- #endif
-@@ -132,6 +148,9 @@
- errmsg("invalid large-object descriptor:
%d", fd)));
- PG_RETURN_INT32(-1);
- }
-+#ifdef USE_REPLICATION
-+ PGR_lo_close(fd);
-+#endif
- #if FSDB
- elog(DEBUG4, "lo_close(%d)", fd);
- #endif
-@@ -201,6 +220,18 @@
- errmsg("large object descriptor %d was not opened
for writing",
- fd)));
-
-+#ifdef USE_REPLICATION
-+ if ((PGR_Stand_Alone != NULL) &&
-+ (PGR_lo_write(fd, buf, len) != STATUS_OK))
-+ {
-+ if ((PGR_Is_Stand_Alone() == true) &&
-+ (PGR_Stand_Alone->permit == PERMIT_READ_ONLY) )
-+ {
-+ elog(WARNING, "This query is not permitted when all
replication servers fell down ");
-+ return -1;
-+ }
-+ }
-+#endif
- Assert(fscxt != NULL);
- currentContext = MemoryContextSwitchTo(fscxt);
-
-@@ -229,6 +260,10 @@
- PG_RETURN_INT32(-1);
- }
-
-+#ifdef USE_REPLICATION
-+ PGR_lo_lseek(fd, offset, whence);
-+#endif /* USE_REPLICATION */
-+
- Assert(fscxt != NULL);
- currentContext = MemoryContextSwitchTo(fscxt);
-
-@@ -250,6 +285,18 @@
-
- currentContext = MemoryContextSwitchTo(fscxt);
-
-+#ifdef USE_REPLICATION
-+ if ((PGR_Stand_Alone != NULL) &&
-+ (PGR_lo_create(InvalidOid) != STATUS_OK))
-+ {
-+ if ((PGR_Is_Stand_Alone() == true) &&
-+ (PGR_Stand_Alone->permit == PERMIT_READ_ONLY) )
-+ {
-+ elog(WARNING, "This query is not permitted when all
replication servers fell down ");
-+ PG_RETURN_INT32(-1);
-+ }
-+ }
-+#endif /* USE_REPLICATION */
- lobjId = inv_create(InvalidOid);
-
- MemoryContextSwitchTo(currentContext);
-@@ -263,6 +310,18 @@
- Oid lobjId = PG_GETARG_OID(0);
- MemoryContext currentContext;
-
-+#ifdef USE_REPLICATION
-+ if ((PGR_Stand_Alone != NULL) &&
-+ (PGR_lo_create(lobjId) != STATUS_OK))
-+ {
-+ if ((PGR_Is_Stand_Alone() == true) &&
-+ (PGR_Stand_Alone->permit == PERMIT_READ_ONLY) )
-+ {
-+ elog(WARNING, "This query is not permitted when all
replication servers fell down ");
-+ PG_RETURN_INT32(-1);
-+ }
-+ }
-+#endif /* USE_REPLICATION */
- /* do we actually need fscxt for this? */
- CreateFSContext();
-
-@@ -300,6 +359,18 @@
- {
- Oid lobjId = PG_GETARG_OID(0);
-
-+#ifdef USE_REPLICATION
-+ if ((PGR_Stand_Alone != NULL) &&
-+ (PGR_lo_unlink(lobjId) != STATUS_OK))
-+ {
-+ if ((PGR_Is_Stand_Alone() == true) &&
-+ (PGR_Stand_Alone->permit == PERMIT_READ_ONLY) )
-+ {
-+ elog(WARNING, "This query is not permitted when all
replication servers fell down ");
-+ return -1;
-+ }
-+ }
-+#endif /* USE_REPLICATION */
- /*
- * If there are any open LO FDs referencing that ID, close 'em.
- */
-@@ -391,6 +462,7 @@
- errhint("Anyone can use the client-side
lo_import() provided by libpq.")));
- #endif
-
-+
- /*
- * We don't actually need to switch into fscxt, but create it anyway
to
- * ensure that AtEOXact_LargeObject knows there is state to clean up
-@@ -405,6 +477,20 @@
- nbytes = MAXPGPATH - 1;
- memcpy(fnamebuf, VARDATA(filename), nbytes);
- fnamebuf[nbytes] = '\0';
-+
-+#ifdef USE_REPLICATION
-+ if ((PGR_Stand_Alone != NULL) &&
-+ (PGR_lo_import((char*)fnamebuf) != STATUS_OK))
-+ {
-+ if ((PGR_Is_Stand_Alone() == true) &&
-+ (PGR_Stand_Alone->permit == PERMIT_READ_ONLY) )
-+ {
-+ elog(WARNING, "This query is not permitted when all
replication servers fell down ");
-+ return -1;
-+ }
-+ }
-+#endif
-+
- fd = PathNameOpenFile(fnamebuf, O_RDONLY | PG_BINARY, 0666);
- if (fd < 0)
- ereport(ERROR,
-diff -aruN postgresql-8.1.2/src/backend/libpq/cluster.conf.sample
pgcluster-1.5.0rc7/src/backend/libpq/cluster.conf.sample
---- postgresql-8.1.2/src/backend/libpq/cluster.conf.sample 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/libpq/cluster.conf.sample 2006-01-10
17:39:39.000000000 +0100
-@@ -0,0 +1,57 @@
-+#============================================================
-+# Cluster DB Server configuration file
-+#------------------------------------------------------------
-+# file: cluster.conf
-+#------------------------------------------------------------
-+# This file controls:
-+# o which hosts & port are replication server
-+# o which port use for replication request to replication server
-+# o which command use for recovery function
-+#============================================================
-+#------------------------------------------------------------
-+# set Replication Server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Recovery_Port : connection for recovery process
-+#------------------------------------------------------------
-+<Replicate_Server_Info>
-+ <Host_Name> replicate1.postgres.jp </Host_Name>
-+ <Port> 8001 </Port>
-+ <Recovery_Port> 8101 </Recovery_Port>
-+</Replicate_Server_Info>
-+#<Replicate_Server_Info>
-+# <Host_Name> replicate2.postgres.jp </Host_Name>
-+# <Port> 8002 </Port>
-+# <Recovery_Port> 8102 </Recovery_Port>
-+#</Replicate_Server_Info>
-+#<Replicate_Server_Info>
-+# <Host_Name> replicate3.postgres.jp </Host_Name>
-+# <Port> 8003 </Port>
-+# <Recovery_Port> 8103 </Recovery_Port>
-+#</Replicate_Server_Info>
-+#-------------------------------------------------------------
-+# set Cluster DB Server information
-+# o Recovery_Port : connection for recovery
-+# o Rsync_Path : path of rsync command
-+# o Rsync_Option : file transfer option for rsync
-+# o Rsync_Compress : use compression option for rsync
-+# [yes/no]. default : yes
-+# o When_Stand_Alone : When all replication servers fell,
-+# you can set up two kinds of permittion,
-+# "real_only" or "read_write".
-+#-------------------------------------------------------------
-+<Recovery_Port> 7001 </Recovery_Port>
-+<Rsync_Path> /usr/bin/rsync </Rsync_Path>
-+<Rsync_Option> ssh -1 </Rsync_Option>
-+<Rsync_Compress> yes </Rsync_Compress>
-+<When_Stand_Alone> read_only </When_Stand_Alone>
-+#-------------------------------------------------------------
-+# set partitional replicate control information
-+# set DB name and Table name to stop reprication
-+# o DB_Name : DB name
-+# o Table_Name : table name
-+#-------------------------------------------------------------
-+#<Not_Replicate_Info>
-+# <DB_Name> test_db </DB_Name>
-+# <Table_Name> log_table </Table_Name>
-+#</Not_Replicate_Info>
-diff -aruN postgresql-8.1.2/src/backend/libpq/recovery.c
pgcluster-1.5.0rc7/src/backend/libpq/recovery.c
---- postgresql-8.1.2/src/backend/libpq/recovery.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/libpq/recovery.c 2006-02-08
22:17:50.000000000 +0100
-@@ -0,0 +1,1196 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * recovery.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at backend for the recovery.
-+ * Low level I/O functions that called by in these functions are
-+ * contained in 'replicate_com.c'.
-+ *
-+ *--------------------------------------------------------------------
-+ */
-+
-+/*--------------------------------------
-+ * INTERFACE ROUTINES
-+ *
-+ * I/O call:
-+ * PGR_recovery_finish_send
-+ * master module:
-+ * PGR_Master_Main(void);
-+ * recovery module:
-+ * PGR_Recovery_Main
-+ *-------------------------------------
-+ */
-+#ifdef USE_REPLICATION
-+
-+#include "postgres.h"
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <ctype.h>
-+#include <time.h>
-+#include <pwd.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <sys/param.h>
-+#include <sys/select.h>
-+#include <netinet/tcp.h>
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+#include <dirent.h>
-+
-+#include "libpq/pqsignal.h"
-+#include "utils/guc.h"
-+#include "miscadmin.h"
-+#include "nodes/nodes.h"
-+#include "nodes/parsenodes.h"
-+#include "access/xact.h"
-+#include "access/xlog.h"
-+#include "tcop/tcopprot.h"
-+#include "postmaster/postmaster.h"
-+
-+#include "../interfaces/libpq/libpq-fe.h"
-+#include "../interfaces/libpq/libpq-int.h"
-+#include "../interfaces/libpq/fe-auth.h"
-+
-+#include "replicate.h"
-+
-+#ifdef WIN32
-+#include "win32.h"
-+#else
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+#include <arpa/inet.h>
-+#endif
-+
-+#ifndef HAVE_STRDUP
-+#include "strdup.h"
-+#endif
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+#ifdef MULTIBYTE
-+#include "mb/pg_wchar.h"
-+#endif
-+
-+#define RECOVERY_LOOP_END (0)
-+#define RECOVERY_LOOP_CONTINUE (1)
-+#define RECOVERY_LOOP_FAIL (2)
-+char Local_Host_Name[HOSTNAME_MAX_LENGTH];
-+
-+static int read_packet(int sock,RecoveryPacket * packet);
-+static int send_recovery_packet(int sock, RecoveryPacket * packet);
-+static int send_packet(int * sock, RecoveryPacket * packet );
-+static void master_loop(int fd);
-+static int start_recovery_send(int * sock, ReplicateServerInfo * host);
-+static int stop_recovery_send(int * sock, ReplicateServerInfo * host);
-+static int rsync_pg_data(char * src , char * dest);
-+static int remove_dir(char * dir_name);
-+static int clear_bkup_dir(char * dir_name);
-+static int bkup_dir(char * dir_name);
-+static int restore_dir(char * dir_name);
-+static int rsync_global_dir(char * src, char * dest, int stage);
-+static int first_recovery(char * src, char * dest, char * dir);
-+static int second_recovery(char * src, char * dest, char * dir);
-+static int recovery_rsync(char * src , char * dest, int stage);
-+static int recovery_loop(int fd);
-+static void show_recovery_packet(RecoveryPacket * packet);
-+static int direct_send_packet(int packet_no);
-+static void set_recovery_packet(RecoveryPacket * packet, int packet_no);
-+static int sync_table_space(char * hostName, uint16_t portNum, char *
userName, int stage);
-+static PGresult * get_table_space_location(char * hostName, uint16_t
portNum, char * userName);
-+static int rsync_table_space(char * hostName, char * location, int stage);
-+
-+int PGR_recovery_error_send(void);
-+int PGR_recovery_finish_send(void);
-+int PGR_Master_Main(void);
-+int PGR_Recovery_Main(void);
-+
-+static int
-+read_packet(int sock,RecoveryPacket * packet)
-+{
-+ int r;
-+ char * read_ptr;
-+ int read_size = 0;
-+ int packet_size = 0;
-+
-+ read_ptr = (char*)packet;
-+ packet_size = sizeof(RecoveryPacket);
-+
-+ for (;;){
-+ r = recv(sock,read_ptr + read_size ,packet_size, MSG_WAITALL);
-+ if (r < 0) {
-+ if (errno == EINTR || errno == EAGAIN) {
-+ continue;
-+ } else {
-+ elog(DEBUG1, "read_packet():recv failed");
-+ return -1;
-+ }
-+ } else if (r == 0) {
-+ elog(DEBUG1, "read_packet():unexpected EOF");
-+ return -1;
-+ } else /*if (r > 0)*/ {
-+ read_size += r;
-+ if (read_size == packet_size) {
-+ show_recovery_packet(packet);
-+ return read_size;
-+ }
-+ }
-+ }
-+ return -1;
-+}
-+
-+static int
-+send_recovery_packet(int sock, RecoveryPacket * packet)
-+{
-+ char * send_ptr;
-+ int send_size= 0;
-+ int buf_size = 0;
-+ int s;
-+ int rtn;
-+ fd_set wmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = PGR_SEND_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ rtn = 1;
-+ while (rtn)
-+ {
-+ for (;;)
-+ {
-+ timeout.tv_sec = PGR_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 == EINTR || errno == EAGAIN)
-+ {
-+ continue;
-+ }
-+ else
-+ {
-+ rtn = 0;
-+ break;
-+ }
-+ }
-+ else if (rtn && FD_ISSET(sock, &wmask))
-+ {
-+ send_ptr = (char *)packet;
-+ buf_size = sizeof(RecoveryPacket);
-+
-+ s = send(sock,send_ptr + send_size,buf_size -
send_size ,0);
-+ if (s < 0) {
-+ if (errno == EINTR || errno ==
EAGAIN) {
-+ continue;
-+ }
-+ elog(DEBUG1,
"send_recovery_packet():send error");
-+
-+ /* EPIPE || ENCONNREFUSED || ENSOCK
|| EHOSTUNREACH */
-+ return STATUS_ERROR;
-+ } else if (s == 0) {
-+ elog(DEBUG1,
"send_recovery_packet():unexpected EOF");
-+ return STATUS_ERROR;
-+ } else /*if (s > 0)*/ {
-+ send_size += s;
-+ if (send_size == buf_size)
-+ {
-+ return STATUS_OK;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ return STATUS_ERROR;
-+}
-+
-+static int
-+send_packet(int * sock, RecoveryPacket * packet )
-+{
-+ int count = 0;
-+ ReplicateServerInfo * host = NULL;
-+
-+ host = PGR_get_replicate_server_info();
-+ if (host == (ReplicateServerInfo*)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ count = 0;
-+ while (send_recovery_packet(*sock,packet) != STATUS_OK)
-+ {
-+ if (count < MAX_RETRY_TIMES )
-+ {
-+ count ++;
-+ continue;
-+ }
-+ count = 0;
-+ close(*sock);
-+ PGR_Set_Replication_Server_Status(host,DATA_ERR);
-+ host = PGR_get_replicate_server_info();
-+ if (host == (ReplicateServerInfo*)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ PGR_Set_Replication_Server_Status(host,DATA_USE);
-+ PGR_Create_Socket_Connect(sock, host->hostName ,
host->recoveryPortNumber);
-+ }
-+ return STATUS_OK;
-+}
-+
-+static void
-+master_loop(int fd)
-+{
-+ int count;
-+ int sock;
-+ int status = STATUS_OK;
-+ RecoveryPacket packet;
-+ int r_size = 0;
-+ bool loop_end = false;
-+
-+ count = 0;
-+ while ((status =
PGR_Create_Acception(fd,&sock,"",RecoveryPortNumber)) != STATUS_OK)
-+ {
-+ PGR_Close_Sock(&sock);
-+ sock = -1;
-+ if ( count > MAX_RETRY_TIMES)
-+ {
-+ return;
-+ }
-+ count ++;
-+ }
-+ for(;;)
-+ {
-+ int rtn;
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = PGR_RECV_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(sock,&rmask);
-+ rtn = select(sock+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+ if (rtn && FD_ISSET(sock, &rmask))
-+ {
-+ r_size = read_packet(sock,&packet);
-+ if (r_size == 0)
-+ {
-+ continue;
-+ }
-+ else if (r_size < 0)
-+ {
-+ loop_end=true;
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ continue;
-+ }
-+ switch (ntohs(packet.packet_no))
-+ {
-+ case RECOVERY_PGDATA_REQ :
-+ /*
-+ * PGDATA information request
-+ */
-+ /*
-+ * get master server information
-+ */
-+ memset(&packet,0,sizeof(packet));
-+ set_recovery_packet(&packet,
RECOVERY_PGDATA_ANS) ;
-+ status = send_packet(&sock,&packet);
-+ PGR_Set_Cluster_Status(STATUS_RECOVERY);
-+ break;
-+ case RECOVERY_FSYNC_REQ :
-+ /*
-+ * get master server information
-+ */
-+ memset(&packet,0,sizeof(packet));
-+ set_recovery_packet(&packet,
RECOVERY_FSYNC_ANS );
-+ status = send_packet(&sock,&packet);
-+ PGR_Set_Cluster_Status(STATUS_RECOVERY);
-+ loop_end = true;
-+ break;
-+ case RECOVERY_ERROR_TARGET_ONLY:
-+ memset(&packet,0,sizeof(packet));
-+ set_recovery_packet(&packet,
RECOVERY_ERROR_ANS );
-+ status = send_packet(&sock,&packet);
-+ PGR_Set_Cluster_Status(STATUS_REPLICATE);
-+ break;
-+ case RECOVERY_ERROR_CONNECTION:
-+ memset(&packet,0,sizeof(packet));
-+ set_recovery_packet(&packet,
RECOVERY_ERROR_ANS );
-+ status = send_packet(&sock,&packet);
-+ PGR_Set_Cluster_Status(STATUS_REPLICATE);
-+ /**
-+ * kill broken cluster db.
-+ * FIXME: missing MyProcPid here. It must be
postmaster's pid.
-+ * but here's a bug MyProcPid doesn't
initialized properly , so MyProcPid = postmaster's pid.

-+ * To fix this, define variable to set
posmaster's pid.
-+ */
-+ kill(MyProcPid,SIGQUIT);
-+ loop_end = true;
-+ break;
-+ case RECOVERY_ERROR_ANS:
-+ /* TODO: recovery failed. close this postmaster */
-+ loop_end = true;
-+ break;
-+ case RECOVERY_FINISH:
-+ PGR_Set_Cluster_Status(STATUS_REPLICATE);
-+ loop_end = true;
-+ break;
-+ default:
-+ loop_end = true;
-+ break;
-+ }
-+ if (loop_end)
-+ {
-+ break;
-+ }
-+ }
-+ PGR_Close_Sock(&sock);
-+}
-+
-+int
-+PGR_Master_Main(void)
-+{
-+ int status;
-+ int fd = -1;
-+ int rtn;
-+ int pid;
-+
-+ if ((pid = fork()) != 0 )
-+ {
-+ return pid;
-+ }
-+
-+ memset(Local_Host_Name,0,sizeof(Local_Host_Name));
-+ gethostname(Local_Host_Name,sizeof(Local_Host_Name));
-+ pqsignal(SIGHUP, authdie);
-+ pqsignal(SIGTERM, authdie);
-+ pqsignal(SIGINT, authdie);
-+ pqsignal(SIGQUIT, authdie);
-+ pqsignal(SIGALRM, authdie);
-+ PG_SETMASK(&UnBlockSig);
-+
-+ status = STATUS_ERROR;
-+ status = PGR_Create_Socket_Bind(&fd, "", RecoveryPortNumber);
-+
-+ if (status != STATUS_OK)
-+ {
-+ return pid;
-+ }
-+ for (;;)
-+ {
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = 60;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(fd,&rmask);
-+ rtn = select(fd+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+ if (rtn && FD_ISSET(fd, &rmask))
-+ {
-+ master_loop(fd);
-+ }
-+ }
-+ return pid;
-+}
-+
-+static int
-+start_recovery_send(int * sock, ReplicateServerInfo * host)
-+{
-+ int status;
-+ RecoveryPacket packet;
-+ status = PGR_Create_Socket_Connect(sock, host->hostName,
host->recoveryPortNumber);
-+ if (status != STATUS_OK)
-+ {
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"connection error to replication server");
-+ }
-+ return STATUS_ERROR;
-+ }
-+
-+ memset(&packet,0,sizeof(packet));
-+ set_recovery_packet(&packet, RECOVERY_PREPARE_REQ );
-+ status = send_packet(sock,&packet);
-+
-+ return status;
-+}
-+
-+static int
-+stop_recovery_send(int * sock, ReplicateServerInfo * host)
-+{
-+ int status;
-+ RecoveryPacket packet;
-+
-+ memset(&packet,0,sizeof(packet));
-+ set_recovery_packet(&packet, RECOVERY_ERROR_ANS );
-+ status = send_packet(sock,&packet);
-+ return status;
-+}
-+
-+static int
-+direct_send_packet(int packet_no)
-+{
-+
-+ int status;
-+ int fd = -1;
-+ ReplicateServerInfo * host;
-+ RecoveryPacket packet;
-+
-+ host = PGR_get_replicate_server_info();
-+ if (host == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ status = PGR_Create_Socket_Connect(&fd, host->hostName,
host->recoveryPortNumber);
-+ if (status != STATUS_OK)
-+ {
-+ PGR_Set_Replication_Server_Status(host,DATA_ERR);
-+ return STATUS_ERROR;
-+ }
-+
-+ memset(&packet,0,sizeof(packet));
-+ set_recovery_packet(&packet, packet_no );
-+ status = send_packet(&fd,&packet);
-+
-+ close(fd);
-+
-+ return status;
-+}
-+
-+int
-+PGR_recovery_error_send(void)
-+{
-+ return direct_send_packet(RECOVERY_ERROR_ANS);
-+}
-+
-+int
-+PGR_recovery_finish_send(void)
-+{
-+ return direct_send_packet(RECOVERY_FINISH);
-+}
-+
-+static int
-+rsync_pg_data(char * src, char * dest)
-+{
-+ int status;
-+ char *args[12];
-+ int pid, i = 0;
-+
-+ args[i++] = "rsync";
-+ args[i++] = "-a";
-+ args[i++] = "-r";
-+ if (RsyncCompress)
-+ args[i++] = "-z";
-+ args[i++] = "--delete";
-+ args[i++] = "-e";
-+ args[i++] = RsyncOption;
-+ args[i++] = src;
-+ args[i++] = dest;
-+ args[i++] = NULL;
-+
-+ pid = fork();
-+ if (pid == 0)
-+ {
-+ status = execv(RsyncPath,args);
-+ }
-+ else
-+ {
-+ for (;;)
-+ {
-+ int result;
-+ result = wait(&status);
-+ if (result < 0)
-+ {
-+ if (errno == EINTR)
-+ continue;
-+ return STATUS_ERROR;
-+ }
-+
-+ if (WIFEXITED(status) == 0 || WEXITSTATUS(status) !=
0)
-+ return STATUS_ERROR;
-+ else
-+ break;
-+ }
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+remove_dir(char * dir_name)
-+{
-+ DIR * dp = NULL;
-+ struct dirent *dirp = NULL;
-+ char fname[256];
-+ int status = 0;
-+
-+ if ((dp = opendir(dir_name)) == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ while ((dirp = readdir(dp)) != NULL)
-+ {
-+ if ((!strcmp(dirp->d_name,".")) ||
-+ (!strcmp(dirp->d_name,"..")))
-+ {
-+ continue;
-+ }
-+ sprintf(fname,"%s/%s",dir_name,dirp->d_name);
-+ status = remove(fname);
-+ if (status < 0)
-+ {
-+ remove_dir(fname);
-+ }
-+ }
-+ closedir(dp);
-+ if (remove(dir_name) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+clear_bkup_dir(char * dir_name)
-+{
-+ char bkp_dir[256];
-+ pid_t pid = getpid();
-+
-+ sprintf(bkp_dir,"%s_%d",dir_name,pid);
-+ return (remove_dir(bkp_dir));
-+}
-+
-+static int
-+bkup_dir(char * dir_name)
-+{
-+ int status;
-+ char org_dir[256];
-+ char bkp_dir[256];
-+ pid_t pid = getpid();
-+
-+ sprintf(org_dir,"%s",dir_name);
-+ sprintf(bkp_dir,"%s_%d",dir_name,pid);
-+ status = rename(org_dir,bkp_dir);
-+ if (status < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+restore_dir(char * dir_name)
-+{
-+ int status;
-+ char org_dir[256];
-+ char bkp_dir[256];
-+ pid_t pid = getpid();
-+
-+ sprintf(org_dir,"%s",dir_name);
-+ sprintf(bkp_dir,"%s_%d",dir_name,pid);
-+ status = rename(bkp_dir,org_dir);
-+ if (status < 0)
-+ {
-+ remove_dir(org_dir);
-+ status = rename(bkp_dir,org_dir);
-+ if (status < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+rsync_global_dir(char * src, char * dest, int stage)
-+{
-+ int status;
-+ char control_file[256];
-+ char org_dir[256];
-+ char src_dir[256];
-+ struct stat fstat;
-+ int cnt;
-+
-+ sprintf(org_dir,"%s/global",dest);
-+ sprintf(control_file,"%s/global/pg_control",dest);
-+ if (stage == PGR_1ST_RECOVERY)
-+ {
-+ if (bkup_dir(org_dir) != STATUS_OK)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ sprintf(src_dir,"%s/global",src);
-+ status = rsync_pg_data(src_dir, dest);
-+ if (status != STATUS_OK )
-+ {
-+ restore_dir(org_dir);
-+ return STATUS_ERROR;
-+ }
-+ /* check pg_control file */
-+ cnt = 0;
-+ while (stat(control_file, &fstat) < 0)
-+ {
-+ if (cnt > MAX_RETRY_TIMES )
-+ {
-+ restore_dir(org_dir);
-+ return STATUS_ERROR;
-+ }
-+ cnt ++;
-+ sleep(1);
-+ }
-+ if (stage == PGR_2ND_RECOVERY)
-+ {
-+ clear_bkup_dir(org_dir);
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+first_recovery(char * src, char * dest, char * dir)
-+{
-+ int status = STATUS_OK;
-+ char src_dir[256];
-+ char dest_dir[256];
-+
-+ memset(src_dir,0,sizeof(src_dir));
-+ memset(dest_dir,0,sizeof(dest_dir));
-+ sprintf(src_dir,"%s/%s",src,dir);
-+ sprintf(dest_dir,"%s/%s",dest,dir);
-+ status = bkup_dir(dest_dir);
-+ if (status < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ status = rsync_pg_data(src_dir, dest);
-+ if (status != STATUS_OK )
-+ {
-+ restore_dir(dest_dir);
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+second_recovery(char * src, char * dest, char * dir)
-+{
-+ int status = STATUS_OK;
-+ char src_dir[256];
-+ char dest_dir[256];
-+
-+ memset(src_dir,0,sizeof(src_dir));
-+ memset(dest_dir,0,sizeof(dest_dir));
-+ sprintf(src_dir,"%s/%s",src,dir);
-+ sprintf(dest_dir,"%s/%s",dest,dir);
-+
-+ status = rsync_pg_data(src_dir, dest);
-+ if (status != STATUS_OK )
-+ {
-+ restore_dir(dest_dir);
-+ return STATUS_ERROR;
-+ }
-+ clear_bkup_dir(dest_dir);
-+
-+ return STATUS_OK;
-+}
-+
-+static int
-+recovery_rsync(char * src , char * dest, int stage)
-+{
-+ if ((src== NULL) || ( dest == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ /* recovery step of "global" directory */
-+ fprintf(stderr,"%s recovery step of [global] directory...",
-+ ((stage == 1)?"1st":"2nd"));
-+ if (rsync_global_dir(src, dest, stage) != STATUS_OK)
-+ {
-+ fprintf(stderr,"NG\n");
-+ return STATUS_ERROR;
-+ }
-+ fprintf(stderr,"OK\n");
-+
-+ if (stage == PGR_1ST_RECOVERY)
-+ {
-+ /* 1st recovery step of "base" directory */
-+ fprintf(stderr,"1st recovery step of [base] directory...");
-+ if (first_recovery(src,dest,"base") != STATUS_OK)
-+ {
-+ fprintf(stderr,"NG\n");
-+ return STATUS_ERROR;
-+ }
-+ fprintf(stderr,"OK\n");
-+
-+ fprintf(stderr,"1st recovery step of [pg_clog] directory...");
-+ /* 1st recovery step of "pg_clog" directory */
-+ if (first_recovery(src,dest,"pg_clog") != STATUS_OK)
-+ {
-+ fprintf(stderr,"NG\n");
-+ return STATUS_ERROR;
-+ }
-+ fprintf(stderr,"OK\n");
-+
-+ /* 1st recovery step of "pg_xlog" directory */
-+ fprintf(stderr,"1st recovery step of [pg_xlog] directory...");
-+ if (first_recovery(src,dest,"pg_xlog") != STATUS_OK)
-+ {
-+ fprintf(stderr,"NG\n");
-+ return STATUS_ERROR;
-+ }
-+ fprintf(stderr,"OK\n");
-+ }
-+ else
-+ {
-+ /* 2nd recovery step of "base" directory */
-+ fprintf(stderr,"2nd recovery step of [base] directory...");
-+ if (second_recovery(src,dest,"base") != STATUS_OK)
-+ {
-+ fprintf(stderr,"NG\n");
-+ return STATUS_ERROR;
-+ }
-+ fprintf(stderr,"OK\n");
-+
-+ /* 2nd recovery step of "pg_clog" directory */
-+ fprintf(stderr,"2nd recovery step of [pg_clog] directory...");
-+ if (second_recovery(src,dest,"pg_clog") != STATUS_OK)
-+ {
-+ fprintf(stderr,"NG\n");
-+ return STATUS_ERROR;
-+ }
-+ fprintf(stderr,"OK\n");
-+
-+ /* 2nd recovery step of "pg_xlog" directory */
-+ fprintf(stderr,"2nd recovery step of [pg_xlog] directory...");
-+ if (second_recovery(src,dest,"pg_xlog") != STATUS_OK)
-+ {
-+ fprintf(stderr,"NG\n");
-+ return STATUS_ERROR;
-+ }
-+ fprintf(stderr,"OK\n");
-+ }
-+
-+ return STATUS_OK;
-+}
-+
-+static int
-+recovery_loop(int fd)
-+{
-+
-+ int status = STATUS_OK;
-+ RecoveryPacket packet;
-+ int r_size = 0;
-+ int rtn = RECOVERY_LOOP_END;
-+ char src[256];
-+ bool need_sync_table_space = false;
-+
-+ r_size = read_packet(fd,&packet);
-+ if (r_size <= 0)
-+ {
-+ rtn = RECOVERY_LOOP_FAIL;
-+ }
-+ switch (ntohs(packet.packet_no))
-+ {
-+ case RECOVERY_PREPARE_ANS :
-+ /*
-+ * get master information
-+ */
-+ /*
-+ * rsync master data before recovery
-+ */
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"local host : %s
master:%s",Local_Host_Name,packet.hostName);
-+ }
-+ if
(!memcmp(Local_Host_Name,packet.hostName,strlen(packet.hostName)))
-+ {
-+ strcpy(src,packet.pg_data);
-+ need_sync_table_space = false;
-+ }
-+ else
-+ {
-+
sprintf(src,"%s:%s",packet.hostName,packet.pg_data);
-+ need_sync_table_space = true;
-+ }
-+ status = recovery_rsync(src,DataDir,PGR_1ST_RECOVERY);
-+ if (status != STATUS_OK)
-+ {
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"1st rsync error");
-+ }
-+ rtn = RECOVERY_LOOP_FAIL;
-+ break;
-+ }
-+ if (need_sync_table_space == true)
-+ {
-+ fprintf(stderr,"1st sync_table_space ");
-+ status = sync_table_space(packet.hostName,
ntohs(packet.port), packet.userName, PGR_1ST_RECOVERY);
-+ if (status != STATUS_OK)
-+ {
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"1st sync table
space error");
-+ }
-+ rtn = RECOVERY_LOOP_FAIL;
-+ fprintf(stderr,"NG\n");
-+ break;
-+ }
-+ fprintf(stderr,"OK\n");
-+ }
-+ /*
-+ * send recovery start request
-+ */
-+ PGRset_recovery_packet_no(&packet, RECOVERY_START_REQ
);
-+ status = send_packet(&fd,&packet);
-+ if (status != STATUS_OK)
-+ {
-+ rtn = RECOVERY_LOOP_FAIL;
-+ break;
-+ }
-+ rtn = RECOVERY_LOOP_CONTINUE;
-+ break;
-+ case RECOVERY_START_ANS :
-+ /*
-+ * rsync master data before recovery
-+ */
-+ if
(!memcmp(Local_Host_Name,packet.hostName,strlen(packet.hostName)))
-+ {
-+ strcpy(src,packet.pg_data);
-+ need_sync_table_space = false;
-+ }
-+ else
-+ {
-+
sprintf(src,"%s:%s",packet.hostName,packet.pg_data);
-+ need_sync_table_space = true;
-+ }
-+ status = recovery_rsync(src,DataDir,PGR_2ND_RECOVERY);
-+ if (status != STATUS_OK)
-+ {
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"2nd rsync error");
-+ }
-+ rtn = RECOVERY_LOOP_FAIL;
-+ break;
-+ }
-+ if (need_sync_table_space == true)
-+ {
-+ fprintf(stderr,"2nd sync_table_space ");
-+ status = sync_table_space(packet.hostName,
ntohs(packet.port), packet.userName, PGR_2ND_RECOVERY);
-+ if (status != STATUS_OK)
-+ {
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"2nd sync table
space error");
-+ }
-+ rtn = RECOVERY_LOOP_FAIL;
-+ fprintf(stderr,"NG\n");
-+ break;
-+ }
-+ fprintf(stderr,"OK\n");
-+ }
-+ rtn = RECOVERY_LOOP_END;
-+ break;
-+ case RECOVERY_ERROR_OCCUPIED:
-+ case RECOVERY_ERROR_CONNECTION:
-+ default:
-+ rtn = RECOVERY_LOOP_FAIL;
-+ break;
-+ }
-+
-+ return rtn;
-+}
-+
-+int
-+PGR_Recovery_Main(void)
-+{
-+ int status;
-+ int fd = -1;
-+ int rtn;
-+ ReplicateServerInfo * host;
-+
-+ memset(Local_Host_Name,0,sizeof(Local_Host_Name));
-+ gethostname(Local_Host_Name,sizeof(Local_Host_Name));
-+
-+ status = STATUS_ERROR;
-+
-+Retry_Start_Recovery:
-+ host = PGR_get_replicate_server_info();
-+ if (host == NULL)
-+ {
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"not found replication server");
-+ }
-+ return STATUS_ERROR;
-+ }
-+
-+ status = start_recovery_send(&fd,host);
-+ if (status != STATUS_OK)
-+ {
-+ PGR_Set_Replication_Server_Status(host,DATA_ERR);
-+ close(fd);
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"start recovery packet send error");
-+ }
-+ goto Retry_Start_Recovery;
-+ }
-+
-+ for (;;)
-+ {
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = RECOVERY_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(fd,&rmask);
-+ rtn = select(fd+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+ if (rtn && FD_ISSET(fd, &rmask))
-+ {
-+ status = recovery_loop(fd);
-+ if (status == RECOVERY_LOOP_CONTINUE)
-+ {
-+ continue;
-+ }
-+ else if (status == RECOVERY_LOOP_END)
-+ {
-+ close(fd);
-+ break;
-+ }
-+ else if (status == RECOVERY_LOOP_FAIL)
-+ {
-+ status = stop_recovery_send(&fd,host);
-+ if (status != STATUS_OK)
-+ {
-+ close(fd);
-+ return STATUS_ERROR;
-+ }
-+ close(fd);
-+ return STATUS_ERROR;
-+ }
-+ else
-+ {
-+ close(fd);
-+ return STATUS_ERROR;
-+ }
-+ }
-+ }
-+ return STATUS_OK;
-+}
-+
-+static void
-+show_recovery_packet(RecoveryPacket * packet)
-+{
-+
-+ if (Debug_pretty_print)
-+ {
-+ elog(DEBUG1,"no = %d",ntohs(packet->packet_no));
-+ elog(DEBUG1,"max_connect = %d",ntohs(packet->max_connect));
-+ elog(DEBUG1,"port = %d",ntohs(packet->port));
-+ elog(DEBUG1,"recoveryPort = %d",ntohs(packet->recoveryPort));
-+ if (packet->hostName != NULL)
-+ elog(DEBUG1,"hostName = %s",packet->hostName);
-+ if (packet->pg_data != NULL)
-+ elog(DEBUG1,"pg_data = %s",packet->pg_data);
-+ }
-+}
-+
-+static void
-+set_recovery_packet(RecoveryPacket * packet, int packet_no)
-+{
-+ struct passwd * pw = NULL;
-+
-+ if (packet == NULL)
-+ {
-+ return;
-+ }
-+ PGRset_recovery_packet_no(packet, packet_no );
-+ packet->max_connect = htons(MaxBackends);
-+ packet->port = htons(PostPortNumber);
-+ packet->recoveryPort = htons(RecoveryPortNumber);
-+ gethostname(packet->hostName,sizeof(packet->hostName));
-+ memcpy(packet->pg_data,DataDir,sizeof(packet->pg_data));
-+ memset(packet->userName,0,sizeof(packet->userName));
-+ if ((pw = getpwuid(geteuid())) != NULL)
-+ {
-+
strncpy(packet->userName,pw->pw_name,sizeof(packet->userName));
-+ }
-+ else
-+ {
-+ cuserid(packet->userName);
-+ }
-+}
-+
-+static int
-+sync_table_space(char * hostName, uint16_t portNum, char * userName, int
stage)
-+{
-+ PGresult * res = (PGresult *)NULL;
-+ int i = 0;
-+ int row_num = 0;
-+ char * location = NULL;
-+ int rtn = STATUS_OK;
-+
-+ res = get_table_space_location(hostName, portNum, userName);
-+ if (res == (PGresult *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ row_num = PQntuples(res);
-+ for ( i = 0 ; i < row_num ; i ++)
-+ {
-+ location = PQgetvalue(res,i,0);
-+ if (strlen(location) > 0 )
-+ {
-+ rtn = rsync_table_space(hostName, location, stage);
-+ fprintf(stderr,".");
-+ }
-+ }
-+ if (res != (PGresult *)NULL)
-+ {
-+ PQclear(res);
-+ }
-+
-+ return STATUS_OK;
-+}
-+
-+static PGresult *
-+get_table_space_location(char * hostName, uint16_t portNum, char * userName)
-+{
-+ PGresult * res = (PGresult *)NULL;
-+ int cnt = 0;
-+ PGconn * conn = (PGconn *)NULL;
-+ char port[8];
-+ char *database = "template1";
-+ char * query = "select spclocation from pg_tablespace";
-+
-+ if ( (hostName == NULL) ||
-+ (portNum <= 0) ||
-+ (userName == NULL))
-+ {
-+ return (PGresult *)NULL;
-+ }
-+ snprintf(port,sizeof(port),"%d", portNum);
-+
-+ /* create connection to master */
-+ conn = PQsetdbLogin(hostName, port, NULL, NULL, database, userName,
NULL);
-+ if (conn == NULL)
-+ {
-+ return (PGresult *)NULL;
-+ }
-+ /* check to see that the backend Connection was successfully made */
-+ cnt = 0;
-+ while (PQstatus(conn) == CONNECTION_BAD)
-+ {
-+ if (conn != NULL)
-+ {
-+ PQfinish(conn);
-+ }
-+ if (cnt > MAX_RETRY_TIMES )
-+ {
-+ return (PGresult *)NULL;
-+ }
-+ conn = PQsetdbLogin(hostName, port, NULL, NULL, database,
userName, NULL);
-+ cnt ++;
-+ }
-+ res = PQexec(conn , query);
-+ if ((res == NULL) ||
-+ (PQresultStatus(res) != PGRES_TUPLES_OK))
-+ {
-+ PQclear(res);
-+ res = (PGresult *)NULL;
-+ }
-+ if (conn != NULL)
-+ {
-+ PQfinish(conn);
-+ }
-+
-+ return res;
-+}
-+
-+static int
-+rsync_table_space(char * hostName, char * location, int stage)
-+{
-+ int status = STATUS_OK;
-+ char src_dir[256];
-+ char dest_dir[256];
-+ struct stat fstat;
-+ int cnt = 0;
-+ char * term = NULL;
-+
-+ sprintf(src_dir,"%s:%s",hostName,location);
-+ strncpy(dest_dir,location,sizeof(dest_dir));
-+ term = strrchr(dest_dir,'/');
-+ if (term != NULL)
-+ {
-+ *term = '\0';
-+ }
-+
-+ if (stage == PGR_1ST_RECOVERY)
-+ {
-+ status = bkup_dir(location);
-+ }
-+ status = rsync_pg_data(src_dir, dest_dir);
-+ if (status != STATUS_OK )
-+ {
-+ restore_dir(location);
-+ return STATUS_ERROR;
-+ }
-+ /* check pg_control file */
-+ cnt = 0;
-+ while (stat(location,&fstat) < 0)
-+ {
-+ if (cnt > MAX_RETRY_TIMES )
-+ {
-+ restore_dir(location);
-+ return STATUS_ERROR;
-+ }
-+ cnt ++;
-+ sleep(1);
-+ }
-+ if (stage == PGR_2ND_RECOVERY)
-+ {
-+ clear_bkup_dir(location);
-+ }
-+ return STATUS_OK;
-+}
-+#endif /* USE_REPLICATION */
-diff -aruN postgresql-8.1.2/src/backend/libpq/replicate.c
pgcluster-1.5.0rc7/src/backend/libpq/replicate.c
---- postgresql-8.1.2/src/backend/libpq/replicate.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/libpq/replicate.c 2006-02-09
11:51:50.000000000 +0100
-@@ -0,0 +1,3552 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * replicate.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at backend for the replication.
-+ * Low level I/O functions that called by in these functions are
-+ * contained in 'replicate_com.c'.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+
-+/*--------------------------------------
-+ * INTERFACE ROUTINES
-+ *
-+ * setup/teardown:
-+ * PGR_Init_Replicate_Server_Data
-+ * PGR_Set_Replicate_Server_Socket
-+ * PGR_delete_shm
-+ * I/O call:
-+ * PGR_Send_Replicate_Command
-+ * table handling:
-+ * PGR_get_replicate_server_info
-+ * status distinction:
-+ * PGR_Is_Replicated_Command
-+ * Xlog_Check_Replicatec
-+ * replicateion main:
-+ * PGR_replication
-+ *-------------------------------------
-+ */
-+#ifdef USE_REPLICATION
-+
-+#include "postgres.h"
-+
-+#include <stdio.h>
-+#include <strings.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <grp.h>
-+#include <unistd.h>
-+#include <ctype.h>
-+#include <time.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+#include <netdb.h>
-+
-+#include "libpq/libpq.h"
-+#include "libpq/pqformat.h"
-+#include "miscadmin.h"
-+#include "nodes/nodes.h"
-+#include "nodes/print.h"
-+#include "utils/guc.h"
-+#include "parser/parser.h"
-+#include "access/xact.h"
-+#include "storage/proc.h"
-+#include "postmaster/postmaster.h"
-+
-+#include "replicate.h"
-+
-+/* the source of this value is 'access/transam/varsup.c' */
-+#define VAR_OID_PREFETCH (8192)
-+
-+PGR_ReplicationLog_Info ReplicationLog_Info;
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+static int set_command_args(char argv[PGR_CMD_ARG_NUM][256],char *str);
-+static bool is_same_replication_server(ReplicateServerInfo * sp1,
ReplicateServerInfo * sp2 );
-+static ReplicateServerInfo * search_new_replication_server (
ReplicateServerInfo * sp , int socket_type );
-+
-+static int close_replicate_server_socket ( ReplicateServerInfo * sp , int
socket_type );
-+static int recv_replicate_result(int sock,char * result,int user_timeout);
-+static int recv_message(int sock,char * buf,int flag);
-+static int send_replicate_packet(int sock,ReplicateHeader * header, char *
query_string);
-+static int get_replicate_server_socket ( ReplicateServerInfo * sp , int
socket_type );
-+static bool is_copy_from(char * query);
-+//static int is_session_authorization(char * query);
-+static int get_words( char words[MAX_WORDS][MAX_WORD_LETTERS] ,char *
string,int length,int upper);
-+static int get_table_name(char * table_name, char * query, int position );
-+static bool is_not_replication_query(char * query_string, int query_len,
char cmdType);
-+static int Comp_Not_Replicate(PGR_Not_Replicate_Type *
nrp1,PGR_Not_Replicate_Type* nrp2);
-+static bool is_serial_control_query(char cmdType,char * query);
-+static bool is_select_into_query(char cmdType,char * query);
-+static int send_response_to_replication_server(const char * notice);
-+static bool do_not_replication_command(const char * commandTag);
-+static bool is_create_temp_table(char * query);
-+static int add_replication_server(char * hostname,char * port, char *
recovery_port);
-+static int change_replication_server(char * hostname,char * port, char *
recovery_port);
-+static int get_new_replication_socket( ReplicateServerInfo * base,
ReplicateServerInfo * sp, int socket_type);
-+static char * get_hostName(char * str);
-+static void set_response_mode(char * mode);
-+static void PGR_Set_Current_Replication_Query_ID(char *id);
-+#ifdef CONTROL_LOCK_CONFLICT
-+static int wait_lock_answer(void);
-+static int read_trigger(char * result, int buf_size);
-+#endif /* CONTROL_LOCK_CONFLICT */
-+
-+
-+static unsigned int get_next_request_id(void);
-+static bool is_this_query_replicated(char * id);
-+static int set_replication_id(char * id);
-+static int return_current_oid(void);
-+static int sync_oid(char * oid);
-+
-+extern ssize_t secure_read(Port *, void *, size_t);
-+
-+bool autocommit = true;
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGR_Init_Replicate_Server_Data()
-+ * NOTES
-+ * Read Configuration file and create ReplicateServerData table
-+ * ARGS
-+ * void
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGR_Init_Replicate_Server_Data(void)
-+{
-+ int table_size,str_size;
-+ ReplicateServerInfo *sp;
-+ PGR_Not_Replicate_Type * nrp;
-+ ConfDataType * conf;
-+ int rec_no,cnt;
-+ unsigned int ip;
-+ char HostName[128];
-+
-+
-+ if (ConfData_Top == (ConfDataType *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ /* allocate replication server information table */
-+ table_size = sizeof(ReplicateServerInfo) * MAX_SERVER_NUM;
-+ ReplicateServerShmid = shmget(IPC_PRIVATE,table_size,IPC_CREAT |
IPC_EXCL | 0600);
-+ if (ReplicateServerShmid < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ ReplicateServerData = (ReplicateServerInfo
*)shmat(ReplicateServerShmid,0,0);
-+ if (ReplicateServerData == (ReplicateServerInfo *)-1)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(ReplicateServerData,0,table_size);
-+ sp = ReplicateServerData;
-+
-+ /* allocate cluster db information table */
-+ ClusterDBShmid = shmget(IPC_PRIVATE,sizeof(ClusterDBInfo),IPC_CREAT |
IPC_EXCL | 0600);
-+ if (ClusterDBShmid < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ ClusterDBData = (ClusterDBInfo *)shmat(ClusterDBShmid,0,0);
-+ if (ClusterDBData == (ClusterDBInfo *)-1)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(ClusterDBData,0,sizeof(ClusterDBInfo));
-+ PGR_Set_Cluster_Status(STATUS_REPLICATE);
-+
-+ /* allocate partial replicate table */
-+ table_size = sizeof(PGR_Not_Replicate_Type) * MAX_SERVER_NUM;
-+ PGR_Not_Replicate = malloc(table_size);
-+ if (PGR_Not_Replicate == (PGR_Not_Replicate_Type*)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(PGR_Not_Replicate, 0, table_size);
-+ nrp = PGR_Not_Replicate;
-+ cnt = 0;
-+ conf = ConfData_Top;
-+ while ((conf != (ConfDataType *)NULL) && (cnt < MAX_SERVER_NUM))
-+ {
-+ /* set replication server table */
-+ if (!strcmp(conf->table,REPLICATION_SERVER_INFO_TAG))
-+ {
-+ rec_no = conf->rec_no;
-+ cnt = rec_no;
-+ if (!strcmp(conf->key,HOST_NAME_TAG))
-+ {
-+ strncpy((sp +
rec_no)->hostName,conf->value,sizeof(sp->hostName));
-+ conf = (ConfDataType *)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,PORT_TAG))
-+ {
-+ (sp + rec_no)->portNumber = atoi(conf->value);
-+ (sp + rec_no)->sock = -1;
-+ if ((sp + rec_no)->useFlag != DATA_USE)
-+ {
-+
PGR_Set_Replication_Server_Status((sp+rec_no), DATA_INIT);
-+ }
-+ memset((sp + rec_no +
1)->hostName,0,sizeof(sp->hostName));
-+ (sp + rec_no + 1)->useFlag = DATA_END;
-+ conf = (ConfDataType *)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,RECOVERY_PORT_TAG))
-+ {
-+ (sp + rec_no)->recoveryPortNumber =
atoi(conf->value);
-+ if ((sp + rec_no)->useFlag != DATA_USE)
-+ {
-+
PGR_Set_Replication_Server_Status((sp+rec_no), DATA_INIT);
-+ }
-+ memset((sp + rec_no +
1)->hostName,0,sizeof(sp->hostName));
-+ (sp + rec_no + 1)->useFlag = DATA_END;
-+ conf = (ConfDataType *)conf->next;
-+ continue;
-+ }
-+ }
-+ /* set part replication table */
-+ if (!strcmp(conf->table,NOT_REPLICATE_INFO_TAG))
-+ {
-+ rec_no = conf->rec_no;
-+ cnt = rec_no;
-+ if (PGR_Not_Replicate_Rec_Num < rec_no +1)
-+ {
-+ PGR_Not_Replicate_Rec_Num = rec_no +1;
-+ }
-+ if (!strcmp(conf->key,DB_NAME_TAG))
-+ {
-+ strncpy((nrp +
rec_no)->db_name,conf->value,sizeof(nrp->db_name));
-+ conf = (ConfDataType *)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,TABLE_NAME_TAG))
-+ {
-+ strncpy((nrp +
rec_no)->table_name,conf->value,sizeof(nrp->table_name));
-+ conf = (ConfDataType *)conf->next;
-+ continue;
-+ }
-+ }
-+ if (!strcmp(conf->key,RECOVERY_PORT_TAG))
-+ {
-+ RecoveryPortNumber = atoi(conf->value);
-+ }
-+ if (!strcmp(conf->key,RSYNC_PATH_TAG))
-+ {
-+ str_size = strlen(conf->value) ;
-+ RsyncPath = malloc(str_size + 1);
-+ if (RsyncPath == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(RsyncPath,0,str_size + 1);
-+ strncpy(RsyncPath,conf->value,str_size);
-+ }
-+ if (!strcmp(conf->key,RSYNC_OPTION_TAG))
-+ {
-+ str_size = strlen(conf->value) ;
-+ RsyncOption = malloc(str_size + 1);
-+ if (RsyncOption == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(RsyncOption,0,str_size + 1);
-+ strncpy(RsyncOption,conf->value,str_size);
-+ }
-+ if (!strcmp(conf->key,RSYNC_COMPRESS_TAG))
-+ {
-+ if (!strcmp(conf->value, "yes"))
-+ RsyncCompress = true;
-+ else if (!strcmp(conf->value, "no"))
-+ RsyncCompress = false;
-+ }
-+ if (!strcmp(conf->key,STAND_ALONE_TAG))
-+ {
-+ PGR_Stand_Alone =
(PGR_Stand_Alone_Type*)malloc(sizeof(PGR_Stand_Alone_Type));
-+ if (PGR_Stand_Alone == (PGR_Stand_Alone_Type *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ PGR_Stand_Alone->is_stand_alone = false;
-+ if (!strcmp(conf->value,READ_WRITE_IF_STAND_ALONE))
-+ {
-+ PGR_Stand_Alone->permit = PERMIT_READ_WRITE;
-+ }
-+ else
-+ {
-+ PGR_Stand_Alone->permit = PERMIT_READ_ONLY;
-+ }
-+ }
-+ conf = (ConfDataType *)conf->next;
-+ }
-+ TransactionSock = -1;
-+ ReplicateCurrentTime = (ReplicateNow *)malloc(sizeof(ReplicateNow));
-+ if (ReplicateCurrentTime == (ReplicateNow *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(ReplicateCurrentTime,0,sizeof(ReplicateNow));
-+
-+ PGRCopyData = (CopyData *)malloc(sizeof(CopyData));
-+ if (PGRCopyData == (CopyData *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(PGRCopyData,0,sizeof(CopyData));
-+
-+ if (PGR_Not_Replicate_Rec_Num == 0)
-+ {
-+ free(PGR_Not_Replicate);
-+ PGR_Not_Replicate = NULL;
-+ }
-+ else
-+ {
-+ qsort((char
*)PGR_Not_Replicate,PGR_Not_Replicate_Rec_Num,sizeof(PGR_Not_Replicate_Type),
(int (*)(const void*,const void*))Comp_Not_Replicate);
-+ }
-+
-+ PGRSelfHostName = malloc(HOSTNAME_MAX_LENGTH);
-+ if (PGRSelfHostName == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(PGRSelfHostName,0,HOSTNAME_MAX_LENGTH);
-+ if (gethostname(HostName,HOSTNAME_MAX_LENGTH) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ ip=PGRget_ip_by_name(HostName);
-+
-+ sprintf(PGRSelfHostName,
-+ "%d.%d.%d.%d",
-+ (ip ) & 0xff ,
-+ (ip >> 8) & 0xff ,
-+ (ip >> 16) & 0xff ,
-+ (ip >> 24) & 0xff );
-+
-+ return STATUS_OK;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGR_Set_Replicate_Server_Socket()
-+ * NOTES
-+ * Create new socket and set ReplicateServerData table
-+ * ARGS
-+ * void
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGR_Set_Replicate_Server_Socket(void)
-+{
-+ ReplicateServerInfo * sp;
-+ if (ReplicateServerData == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ sp = ReplicateServerData;
-+ while (sp->useFlag != DATA_END){
-+ sp->sock = -1;
-+
PGR_Create_Socket_Connect(&(sp->sock),sp->hostName,sp->portNumber);
-+ sp ++;
-+ }
-+ return STATUS_OK;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * get_replicate_server_socket()
-+ * NOTES
-+ * search or create a socket to connect with the replication server
-+ * ARGS
-+ * ReplicateServerInfo * sp: replication server data (I)
-+ * int socket_type: socket type (I)
-+ * -PGR_TRANSACTION_SOCKET:
-+ * -PGR_QUERY_SOCKET:
-+ * RETURN
-+ * OK: >0(socket)
-+ * NG: -1
-+ *--------------------------------------------------------------------
-+ */
-+static int
-+get_replicate_server_socket ( ReplicateServerInfo * sp , int socket_type )
-+{
-+ ReplicateServerInfo * tmp;
-+ tmp = sp;
-+ if (tmp == (ReplicateServerInfo *) NULL)
-+ {
-+ return -1;
-+ }
-+ if (tmp->hostName[0] == '\0')
-+ {
-+ return -1;
-+ }
-+
-+ if (TransactionSock != -1)
-+ {
-+ return TransactionSock;
-+ }
-+
-+
while(PGR_Create_Socket_Connect(&TransactionSock,tmp->hostName,tmp->portNumber)
!= STATUS_OK)
-+ {
-+ close(TransactionSock);
-+ TransactionSock = -1;
-+ PGR_Set_Replication_Server_Status(tmp, DATA_ERR);
-+ usleep(20);
-+ tmp = PGR_get_replicate_server_info();
-+ if (tmp == (ReplicateServerInfo *)NULL)
-+ {
-+ return -1;
-+ }
-+ PGR_Set_Replication_Server_Status(tmp, DATA_USE);
-+ usleep(10);
-+ }
-+ return TransactionSock;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * close_replicate_server_socket()
-+ * NOTES
-+ * close the socket connected with the replication server
-+ * ARGS
-+ * ReplicateServerInfo * sp: replication server data (I)
-+ * int socket_type: socket type (I)
-+ * -PGR_TRANSACTION_SOCKET:
-+ * -PGR_QUERY_SOCKET:
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+static int
-+close_replicate_server_socket ( ReplicateServerInfo * sp , int socket_type )
-+{
-+ if (sp == (ReplicateServerInfo *)NULL )
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (sp->hostName[0] == '\0')
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (TransactionSock != -1)
-+ {
-+ PGR_Close_Sock(&(TransactionSock));
-+ TransactionSock = -1;
-+ }
-+ switch (socket_type)
-+ {
-+ case PGR_TRANSACTION_SOCKET:
-+ if (TransactionSock != -1)
-+ {
-+ PGR_Close_Sock(&(TransactionSock));
-+ }
-+ TransactionSock = -1;
-+ sp->sock = -1;
-+ break;
-+ case PGR_QUERY_SOCKET:
-+ if (sp->sock != -1)
-+ {
-+ PGR_Close_Sock(&(sp->sock));
-+ }
-+ sp->sock = -1;
-+ break;
-+ }
-+ PGR_Set_Replication_Server_Status(sp, DATA_INIT);
-+ return STATUS_OK;
-+}
-+
-+static bool
-+is_same_replication_server(ReplicateServerInfo * sp1, ReplicateServerInfo *
sp2 )
-+{
-+ if ((sp1 == NULL) || (sp2 == NULL))
-+ {
-+ return false;
-+ }
-+ if ((!strcmp(sp1->hostName,sp2->hostName)) &&
-+ (sp1->portNumber == sp2->portNumber) &&
-+ (sp1->recoveryPortNumber == sp2->recoveryPortNumber))
-+ {
-+ return true;
-+ }
-+ return false;
-+}
-+
-+static ReplicateServerInfo *
-+search_new_replication_server ( ReplicateServerInfo * sp , int socket_type )
-+{
-+ ReplicateHeader dummy_header;
-+ ReplicateServerInfo * rs_tbl;
-+ char command[256];
-+ int sock = -1;
-+ int cnt = 0;
-+
-+ if ((ReplicateServerData == NULL) || ( sp == NULL))
-+ {
-+ return NULL;
-+ }
-+ rs_tbl = sp;
-+ close_replicate_server_socket ( sp , socket_type);
-+ sp ++;
-+ while (is_same_replication_server(sp,rs_tbl) != true)
-+ {
-+ if (sp->useFlag == DATA_END)
-+ {
-+ sp = ReplicateServerData;
-+ }
-+ sock = get_replicate_server_socket( sp , socket_type);
-+ if (sock < 0 )
-+ {
-+ if (is_same_replication_server(sp,rs_tbl) == true)
-+ {
-+ return NULL;
-+ }
-+ else
-+ {
-+ sp++;
-+ }
-+ continue;
-+ }
-+ memset(&dummy_header, 0, sizeof(ReplicateHeader));
-+ memset(command,0,sizeof(command));
-+ snprintf(command,sizeof(command)-1,"SELECT %s(%d,%s,%d,%d)",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_CHANGE_REPLICATION_SERVER_FUNC_NO,
-+ sp->hostName,
-+ sp->portNumber,
-+ sp->recoveryPortNumber);
-+ dummy_header.cmdSys = CMD_SYS_CALL;
-+ dummy_header.cmdSts = CMD_STS_NOTICE;
-+ dummy_header.query_size = htonl(strlen(command));
-+ if (send_replicate_packet(sock,&dummy_header,command) !=
STATUS_OK)
-+ {
-+ cnt ++;
-+ close_replicate_server_socket ( sp , socket_type);
-+ PGR_Set_Replication_Server_Status(sp, DATA_ERR);
-+ }
-+ else
-+ {
-+ PGR_Set_Replication_Server_Status(sp, DATA_USE);
-+ return sp;
-+ }
-+ if (cnt > MAX_RETRY_TIMES )
-+ {
-+ sp++;
-+ cnt = 0;
-+ }
-+ else
-+ {
-+ continue;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+static int
-+get_table_name(char * table_name, char * query, int position )
-+{
-+
-+ int i,wc;
-+ char * p;
-+ char * sp;
-+ int length;
-+
-+ if ((table_name == NULL) || (query == NULL) || (position < 1))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ length = strlen(query);
-+ p = query;
-+ wc = 1;
-+ sp = table_name;
-+ for (i = 0 ; i < length ; i ++)
-+ {
-+ while(isspace(*p))
-+ {
-+ p++;
-+ i++;
-+ }
-+ while((*p != '\0') && (! isspace(*p)))
-+ {
-+ if ((*p == ';') || (*p == '('))
-+ break;
-+ if (wc == position)
-+ {
-+ *sp = *p;
-+ sp++;
-+ }
-+ p++;
-+ i++;
-+ }
-+ if (wc == position)
-+ {
-+ *sp = '\0';
-+ break;
-+ }
-+ wc++;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static bool
-+is_not_replication_query(char * query_string, int query_len, char cmdType)
-+{
-+ PGR_Not_Replicate_Type key;
-+ PGR_Not_Replicate_Type * ptr = NULL;
-+
-+ if (PGR_Not_Replicate_Rec_Num <= 0)
-+ return false;
-+ if (query_string == NULL)
-+ return true;
-+ memset(&key,0,sizeof(PGR_Not_Replicate_Type));
-+ strncpy(key.db_name ,(char
*)(MyProcPort->database_name),sizeof(key.db_name)-1);
-+ switch (cmdType)
-+ {
-+ case CMD_TYPE_INSERT:
-+ get_table_name(key.table_name,query_string,3);
-+ break;
-+ case CMD_TYPE_UPDATE:
-+ get_table_name(key.table_name,query_string,2);
-+ break;
-+ case CMD_TYPE_DELETE:
-+ get_table_name(key.table_name,query_string,3);
-+ break;
-+ case CMD_TYPE_COPY:
-+ get_table_name(key.table_name,query_string,2);
-+ break;
-+ default:
-+ return false;
-+ }
-+ ptr =
(PGR_Not_Replicate_Type*)bsearch((void*)&key,(void*)PGR_Not_Replicate,PGR_Not_Replicate_Rec_Num,sizeof(PGR_Not_Replicate_Type),
(int (*)(const void*,const void*))Comp_Not_Replicate);
-+ if (ptr == NULL)
-+ {
-+ return false;
-+ }
-+ return true;
-+
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGR_Send_Replicate_Command()
-+ * NOTES
-+ * create new socket
-+ * ARGS
-+ * char * query_string: query strings (I)
-+ * char cmdSts:
-+ * char cmdType:
-+ * RETURN
-+ * OK: result
-+ * NG: NULL
-+ *--------------------------------------------------------------------
-+ */
-+char *
-+PGR_Send_Replicate_Command(char * query_string, int query_len, char cmdSts
,char cmdType)
-+{
-+ int sock = -1;
-+ int cnt = 0;
-+ ReplicateHeader header;
-+ char * serverName = NULL;
-+ int portNumber=0;
-+ char * result = NULL;
-+ ReplicateServerInfo * sp = NULL;
-+ ReplicateServerInfo * base = NULL;
-+ int socket_type = 0;
-+ char argv[ PGR_CMD_ARG_NUM ][256];
-+ int argc = 0;
-+ int func_no = 0;
-+ int check_flag =0;
-+
-+
-+ /*
-+ * check query string
-+ */
-+ if ((query_string == NULL) ||
-+ (query_len < 0))
-+ {
-+ return NULL;
-+ }
-+ /* check not replication query */
-+ if (is_not_replication_query(query_string, query_len, cmdType) ==
true)
-+ {
-+ PGR_Copy_Data_Need_Replicate = false;
-+ return NULL;
-+ }
-+
-+ if ((cmdSts == CMD_STS_TRANSACTION ) ||
-+ (cmdSts == CMD_STS_SET_SESSION_AUTHORIZATION ) ||
-+ (cmdSts == CMD_STS_TEMP_TABLE ))
-+ {
-+ socket_type = PGR_TRANSACTION_SOCKET ;
-+ }
-+ else
-+ {
-+ socket_type = PGR_QUERY_SOCKET ;
-+ }
-+ sp = PGR_get_replicate_server_info();
-+ if (sp == NULL)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"PGR_get_replicate_server_info get
error");
-+ return NULL;
-+ }
-+ sock = get_replicate_server_socket( sp , socket_type);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"get_replicate_server_socket fail");
-+ return NULL;
-+ }
-+ result = malloc(PGR_MESSAGE_BUFSIZE + 4);
-+ if (result == NULL)
-+ {
-+ return NULL;
-+ }
-+
-+ serverName = sp->hostName;
-+ portNumber = (int)sp->portNumber;
-+ memset(&header,0,sizeof(ReplicateHeader));
-+
-+ header.cmdSts = cmdSts;
-+ header.cmdType = cmdType;
-+ header.port = htons(PostPortNumber);
-+ header.pid = htons(getpid());
-+ header.query_size = htonl(query_len);
-+
-+ strncpy(header.dbName ,(char
*)(MyProcPort->database_name),sizeof(header.dbName)-1);
-+ strncpy(header.userName , (char
*)(MyProcPort->user_name),sizeof(header.userName)-1);
-+ header.request_id = htonl(get_next_request_id());
-+ header.rlog = 0;
-+
-+ if (PGRSelfHostName != NULL)
-+ {
-+ strncpy(header.from_host, PGRSelfHostName,
HOSTNAME_MAX_LENGTH);
-+ }
-+
-+ base = sp;
-+ PGR_Sock_To_Replication_Server = sock;
-+
-+retry_send_prereplicate_packet:
-+
-+ memset(result,0,PGR_MESSAGE_BUFSIZE + 4);
-+ cnt = 0;
-+ header.cmdSys=CMD_SYS_PREREPLICATE;
-+
-+ while (send_replicate_packet(sock,&header,query_string) != STATUS_OK)
-+ {
-+ cnt++;
-+ if (cnt >= MAX_RETRY_TIMES )
-+ {
-+ sock = get_new_replication_socket( base, sp,
socket_type);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"all replication servers
may be down");
-+ PGR_Stand_Alone->is_stand_alone = true;
-+ if (cmdSts == CMD_STS_TRANSACTION )
-+ {
-+
strcpy(result,PGR_REPLICATION_ABORT_MSG);
-+ return result;
-+ }
-+ free(result);
-+ result = NULL;
-+ return NULL;
-+
-+ }
-+ if(cmdSts==CMD_STS_TRANSACTION )
-+ {
-+ if (cmdType!=CMD_TYPE_BEGIN
-+ && cmdType!=CMD_TYPE_ROLLBACK)
-+ {

-+ elog(ERROR,"replicate server down
during replicating transaction. aborted.");
-+ free(result);
-+ return NULL;
-+ }
-+ }
-+ PGR_Sock_To_Replication_Server = sock;
-+ cnt = 0;
-+ }
-+ }
-+
-+ memset(result,0,PGR_MESSAGE_BUFSIZE);
-+ if (recv_replicate_result(sock,result,0) < 0)
-+ {
-+
-+ sock = get_new_replication_socket( base, sp,
socket_type);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"all
replication servers may be down");
-+ PGR_Stand_Alone->is_stand_alone =
true;
-+
-+ if (cmdSts == CMD_STS_TRANSACTION )
-+ {
-+
strcpy(result,PGR_REPLICATION_ABORT_MSG);
-+ return result;
-+ }
-+ if(result!=NULL) {
-+ free(result);
-+ result = NULL;
-+ }
-+ return NULL;
-+ }
-+ PGR_Sock_To_Replication_Server = sock;
-+ /* replication server should be down */
-+
-+ if(cmdSts==CMD_STS_TRANSACTION
-+ && (cmdType!=CMD_TYPE_BEGIN &&
cmdType!=CMD_TYPE_ROLLBACK))
-+ {
-+ elog(ERROR,"replicate server down
during replicating transaction. aborted.");
-+ free(result);
-+ return NULL;
-+ }
-+
-+ goto retry_send_prereplicate_packet;
-+ }
-+
-+
-+ argc = set_command_args(argv,result);
-+ func_no=atoi(argv[0]);
-+ if(func_no==0) {
-+ /* this server is not primary replicate server*/
-+ sock=-1;
-+ goto retry_send_prereplicate_packet;
-+ }
-+retry_send_replicate_packet:
-+
-+ memset(result,0,PGR_MESSAGE_BUFSIZE + 4);
-+ cnt = 0;
-+ header.cmdSys = CMD_SYS_REPLICATE;
-+ while (send_replicate_packet(sock,&header,query_string) != STATUS_OK)
-+ {
-+ if (cnt > MAX_RETRY_TIMES )
-+ {
-+ sock = get_new_replication_socket( base, sp,
socket_type);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"all replication servers may be
down");
-+ PGR_Stand_Alone->is_stand_alone = true;
-+ if (cmdSts == CMD_STS_TRANSACTION )
-+ {
-+
strcpy(result,PGR_REPLICATION_ABORT_MSG);
-+ return result;
-+ }
-+ free(result);
-+ result = NULL;
-+ return NULL;
-+
-+ }
-+ PGR_Sock_To_Replication_Server = sock;
-+ header.rlog = CONNECTION_SUSPENDED_TYPE;
-+ cnt = 0;
-+ }
-+ cnt ++;
-+ }
-+
-+ memset(result,0,PGR_MESSAGE_BUFSIZE);
-+ if (recv_replicate_result(sock,result,0) < 0)
-+ {
-+ /* replication server should be down */
-+ sock = get_new_replication_socket( base, sp, socket_type);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"all replication servers may be
down");
-+ PGR_Stand_Alone->is_stand_alone = true;
-+
-+ if (cmdSts == CMD_STS_TRANSACTION )
-+ {
-+ strcpy(result,PGR_REPLICATION_ABORT_MSG);
-+ return result;
-+ }
-+ if(result!=NULL) {
-+ free(result);
-+ result = NULL;
-+ }
-+ return NULL;
-+ }
-+ PGR_Sock_To_Replication_Server = sock;
-+ header.rlog = CONNECTION_SUSPENDED_TYPE;
-+
-+ goto retry_send_replicate_packet;
-+ }
-+
-+ argc = set_command_args(argv,result);
-+ if (argc >= 1)
-+ {
-+ func_no = atoi(argv[0]);
-+ if (func_no == PGR_SET_CURRENT_TIME_FUNC_NO)
-+ {
-+ PGR_Set_Current_Time(argv[1],argv[2]);
-+ set_replication_id(argv[3]);
-+ set_response_mode(argv[4]);
-+ PGR_Set_Current_Replication_Query_ID(argv[5]);
-+ }
-+ else if (func_no == PGR_NOTICE_DEADLOCK_DETECTION_FUNC_NO)
-+ {
-+ memset(result,0,PGR_MESSAGE_BUFSIZE);
-+ strcpy(result,PGR_DEADLOCK_DETECTION_MSG);
-+ }
-+ else if (func_no ==
PGR_SET_CURRENT_REPLICATION_QUERY_ID_NO)
-+ {
-+ PGR_Set_Current_Replication_Query_ID(argv[1]);
-+ }
-+ else if (func_no == PGR_QUERY_CONFIRM_ANSWER_FUNC_NO)
-+ {
-+ check_flag = atoi(argv[1]);
-+ if (check_flag == PGR_ALREADY_COMMITTED )
-+ {
-+ PGR_Set_Current_Time(argv[2],argv[3]);
-+ set_replication_id(argv[4]);
-+ }
-+ else
-+ {
-+ PGR_Set_Current_Time(argv[1],argv[2]);
-+ set_replication_id(argv[3]);
-+ /* this query is not replicated */
-+ /*
-+ free(result);
-+ return NULL;
-+ */
-+ }
-+ }
-+ }
-+ return result;
-+}
-+
-+uint32_t
-+PGRget_replication_id(void)
-+{
-+ return (ReplicationLog_Info.PGR_Replicate_ID);
-+}
-+
-+static int
-+set_replication_id(char * id)
-+{
-+ uint32_t rid=0;
-+ uint32_t saved_id;
-+ if (id == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ rid=(uint32_t)atol(id);
-+ if(rid==0)
-+ return STATUS_OK;
-+
-+ needToUpdateReplicateIdOnNextQueryIsDone=true;
-+ saved_id=ReplicationLog_Info.PGR_Replicate_ID;
-+
-+ ReplicationLog_Info.PGR_Replicate_ID =rid;
-+
-+
-+ /*set replicate id in this process */
-+
-+
-+ if (CurrentReplicateServer == NULL)
-+ {
-+ PGR_get_replicate_server_info();
-+ }
-+ if (CurrentReplicateServer != NULL)
-+ {
-+ /* set replicate id in this system */
-+ saved_id=CurrentReplicateServer->replicate_id;
-+ elog(DEBUG1, "replication id set from %d to
%d", saved_id, rid);
-+
-+ CurrentReplicateServer->replicate_id =
(uint32_t)(atol(id));
-+ }
-+
-+ return STATUS_OK;
-+}
-+
-+
-+static unsigned int
-+get_next_request_id(void)
-+{
-+ if (ReplicationLog_Info.PGR_Request_ID +1 < PGR_MAX_COUNTER)
-+ {
-+ ReplicationLog_Info.PGR_Request_ID ++;
-+ }
-+ else
-+ {
-+ ReplicationLog_Info.PGR_Request_ID = 0;
-+ }
-+ return ReplicationLog_Info.PGR_Request_ID ;
-+
-+}
-+
-+static bool
-+is_this_query_replicated(char * id)
-+{
-+ uint32_t replicate_id = 0;
-+ uint32_t saved_id = 0;
-+ int32_t diff=0;
-+ ReplicateServerInfo * replicate_server_info = NULL;
-+
-+ if (id == NULL)
-+ {
-+ return false;
-+ }
-+ replicate_id = (uint32_t)atol(id);
-+ elog(DEBUG1, "check for replication id , input=%u", replicate_id);
-+
-+ if (CurrentReplicateServer == NULL)
-+ {
-+ PGR_get_replicate_server_info();
-+ }
-+
-+ if (CurrentReplicateServer != NULL)
-+ {
-+ replicate_server_info = CurrentReplicateServer;
-+ }
-+ else if (LastReplicateServer != NULL)
-+ {
-+ replicate_server_info = LastReplicateServer;
-+ }
-+ if (replicate_server_info != NULL)
-+ {
-+
-+ saved_id=replicate_server_info->replicate_id;
-+ saved_id = saved_id < ReplicationLog_Info.PGR_Replicate_ID
-+ ? ReplicationLog_Info.PGR_Replicate_ID
-+ : saved_id;
-+
-+ elog(DEBUG1, "check for replication id , now=%u", saved_id);
-+ /* check replicate_id < saved_id logically
-+ *
-+ * see also:
-+ * backend/transam/transam.c#TransactionIdPrecedes
-+ */
-+ diff = (int32) ( replicate_id - saved_id );
-+ return (diff < 0);
-+ }
-+ elog(DEBUG1, "check for replication id check failed. no replication
server");
-+ return false;
-+}
-+
-+
-+static int
-+get_new_replication_socket( ReplicateServerInfo * base, ReplicateServerInfo
* sp, int socket_type)
-+{
-+ int sock = -1;
-+
-+ if (( base == NULL) ||
-+ ( sp == NULL))
-+ {
-+ return -1;
-+ }
-+ close_replicate_server_socket ( sp , socket_type);
-+ PGR_Set_Replication_Server_Status(sp, DATA_ERR);
-+ sp = search_new_replication_server(base, socket_type);
-+ if (sp == NULL)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"all replication servers may be down");
-+ PGR_Stand_Alone->is_stand_alone = true;
-+ return -1;
-+ }
-+ sock = get_replicate_server_socket( sp , socket_type);
-+ return sock;
-+}
-+
-+
-+static int
-+recv_replicate_result(int sock,char * result,int user_timeout)
-+{
-+ fd_set rmask;
-+ struct timeval timeout;
-+ int rtn;
-+
-+ if (result == NULL)
-+ {
-+ return -1;
-+ }
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ for (;;)
-+ {
-+ if (user_timeout == 0)
-+ timeout.tv_sec = PGR_RECV_TIMEOUT * 3;
-+ else
-+ timeout.tv_sec = user_timeout;
-+
-+ timeout.tv_usec = 0;
-+
-+ FD_ZERO(&rmask);
-+ FD_SET(sock,&rmask);
-+ rtn = select(sock+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+ if (rtn < 0)
-+ {
-+ if (errno != EINTR)
-+ return -1;
-+ }
-+
-+ else if ((rtn > 0) && (FD_ISSET(sock, &rmask)))
-+ {
-+ return (recv_message(sock, result,0));
-+ }
-+ }
-+ return -1;
-+}
-+
-+static int
-+recv_message(int sock,char * buf,int flag)
-+{
-+ int cnt = 0;
-+ int r = 0;
-+ char * read_ptr;
-+ int read_size = 0;
-+ cnt = 0;
-+ read_ptr = buf;
-+
-+ for (;;)
-+ {
-+ r = recv(sock,read_ptr + read_size ,PGR_MESSAGE_BUFSIZE -
read_size, flag);
-+ if (r < 0) {
-+ if (errno == EINTR || errno == EAGAIN) {
-+ continue;
-+ } else {
-+ elog(DEBUG1, "recv_message():recv failed");
-+ return -1;
-+ }
-+ } else if (r == 0) {
-+ elog(DEBUG1, "recv_message():unexpected EOF");
-+ return -1;
-+ } else /*if (r > 0)*/ {
-+ read_size += r;
-+ if (read_size == PGR_MESSAGE_BUFSIZE)
-+ {
-+ return read_size;
-+ }
-+ }
-+ }
-+ return -1;
-+}
-+
-+static int
-+send_replicate_packet(int sock,ReplicateHeader * header, char *
query_string)
-+{
-+ int s = 0;
-+ char * send_ptr = NULL;
-+ char * buf = NULL;
-+ int send_size = 0;
-+ int buf_size = 0;
-+ int header_size = 0;
-+ int rtn = 0;
-+ fd_set wmask;
-+ struct timeval timeout;
-+ int query_size = 0;
-+
-+ /* check parameter */
-+ if ((sock < 0) || (header == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ query_size = ntohl(header->query_size);
-+ header_size = sizeof(ReplicateHeader);
-+ buf_size = header_size + query_size + 4;
-+ buf = malloc(buf_size);
-+ if (buf == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(buf,0,buf_size);
-+ buf_size -= 4;
-+ memcpy(buf,header,header_size);
-+ if (query_string != NULL)
-+ {
-+ memcpy((char *)(buf+header_size),query_string,query_size+1);
-+ }
-+ send_ptr = buf;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ rtn = 1;
-+ for (;;)
-+ {
-+ timeout.tv_sec = PGR_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 == EINTR)
-+ continue;
-+ else
-+ {
-+ elog(DEBUG1,
"send_replicate_packet():select() failed");
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else if (rtn && FD_ISSET(sock, &wmask))
-+ {
-+
-+
-+ s = send(sock,send_ptr + send_size,buf_size -
send_size ,0);
-+ if (s < 0){
-+ if (errno == EINTR || errno == EAGAIN)
-+ {
-+ continue;
-+ }
-+ elog(DEBUG1, "send_replicate_packet():send
error");
-+
-+ /* EPIPE || ENCONNREFUSED || ENSOCK ||
EHOSTUNREACH */
-+ return STATUS_ERROR;
-+ } else if (s == 0) {
-+ free(buf);
-+ buf = NULL;
-+ elog(DEBUG1,
"send_replicate_packet():unexpected EOF");
-+ return STATUS_ERROR;
-+ } else /*if (s > 0)*/ {
-+ send_size += s;
-+ if (send_size == buf_size)
-+ {
-+ free(buf);
-+ buf = NULL;
-+ return STATUS_OK;
-+ }
-+ }
-+ }
-+ }
-+ if (buf != NULL)
-+ {
-+ free(buf);
-+ buf = NULL;
-+ }
-+ return STATUS_ERROR;
-+}
-+
-+bool
-+PGR_Is_Replicated_Command(char * query)
-+{
-+
-+ return (PGR_Is_System_Command(query));
-+}
-+
-+int
-+Xlog_Check_Replicate(int operation)
-+{
-+ if ((PGR_Get_Cluster_Status() == STATUS_RECOVERY) &&
-+ (Transaction_Mode == 0 ) )
-+ {
-+ elog(WARNING, "This query is not permitted while recovery db
");
-+ }
-+ else if ((operation == CMD_UTILITY ) ||
-+ (operation == CMD_INSERT ) ||
-+ (operation == CMD_UPDATE ) ||
-+ (operation == CMD_DELETE ))
-+ {
-+ return (PGR_Replicate_Function_Call());
-+ }
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_Replicate_Function_Call(void)
-+{
-+ char *result = NULL;
-+ int status = STATUS_OK;
-+
-+ if (PGR_Stand_Alone == NULL)
-+ {
-+ return STATUS_OK;
-+ }
-+ if (Query_String != NULL)
-+ {
-+ if (PGR_Is_Stand_Alone() == true)
-+ {
-+ if (PGR_Stand_Alone->permit == PERMIT_READ_ONLY)
-+ {
-+ Query_String = NULL;
-+ return STATUS_ERROR;
-+ }
-+ }
-+ PGR_Need_Notice = true;
-+ PGR_Check_Lock.check_lock_conflict = true;
-+ result =
PGR_Send_Replicate_Command(Query_String,strlen(Query_String),
CMD_STS_QUERY,CMD_TYPE_SELECT);
-+ if (result != NULL)
-+ {
-+ PGR_Reload_Start_Time();
-+ if
(!strncmp(result,PGR_DEADLOCK_DETECTION_MSG,strlen(PGR_DEADLOCK_DETECTION_MSG)))
-+ {
-+ status = STATUS_DEADLOCK_DETECT;
-+ }
-+ free(result);
-+ result = NULL;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ Query_String = NULL;
-+ }
-+ return status;
-+}
-+
-+void
-+PGR_delete_shm(void)
-+{
-+
-+ if (ReplicateServerData != NULL)
-+ {
-+ shmdt(ReplicateServerData);
-+ ReplicateServerData = NULL;
-+ shmctl(ReplicateServerShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ }
-+ if (ClusterDBData != NULL)
-+ {
-+ shmdt(ClusterDBData);
-+ ClusterDBData = NULL;
-+ shmctl(ClusterDBShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ }
-+
-+ if (TransactionSock != -1)
-+ {
-+ close(TransactionSock);
-+ }
-+
-+ if (RsyncPath != NULL)
-+ {
-+ free(RsyncPath);
-+ RsyncPath = NULL;
-+ }
-+ if (RsyncOption != NULL)
-+ {
-+ free(RsyncOption);
-+ RsyncOption = NULL;
-+ }
-+
-+ if (ReplicateCurrentTime != NULL)
-+ {
-+ free(ReplicateCurrentTime);
-+ ReplicateCurrentTime = NULL;
-+ }
-+
-+ if (PGRCopyData != NULL)
-+ {
-+ free (PGRCopyData);
-+ PGRCopyData = NULL;
-+ }
-+
-+ if (PGR_Stand_Alone != NULL)
-+ {
-+ free(PGR_Stand_Alone);
-+ PGR_Stand_Alone = NULL;
-+ }
-+
-+ if (PGR_Not_Replicate != NULL)
-+ {
-+ free(PGR_Not_Replicate);
-+ PGR_Not_Replicate = NULL;
-+ }
-+ if (PGRSelfHostName != NULL)
-+ {
-+ free(PGRSelfHostName);
-+ PGRSelfHostName = NULL;
-+ }
-+}
-+
-+ReplicateServerInfo *
-+PGR_get_replicate_server_info(void)
-+{
-+
-+ ReplicateServerInfo * sp;
-+
-+ if (ReplicateServerData == NULL)
-+ {
-+ return (ReplicateServerInfo *)NULL;
-+ }
-+ sp = ReplicateServerData;
-+ while (sp->useFlag != DATA_END)
-+ {
-+ if (sp->useFlag == DATA_USE )
-+ {
-+ if (CurrentReplicateServer != NULL)
-+ {
-+ LastReplicateServer = CurrentReplicateServer;
-+ CurrentReplicateServer->replicate_id =
LastReplicateServer->replicate_id;
-+ }
-+ CurrentReplicateServer = sp;
-+ return sp;
-+ }
-+ sp++;
-+ }
-+ sp = ReplicateServerData;
-+ while (sp->useFlag != DATA_END)
-+ {
-+ if (sp->useFlag != DATA_ERR )
-+ {
-+ if (CurrentReplicateServer != NULL)
-+ {
-+ LastReplicateServer = CurrentReplicateServer;
-+ CurrentReplicateServer->replicate_id =
LastReplicateServer-> replicate_id;
-+ }
-+ CurrentReplicateServer = sp;
-+ PGR_Set_Replication_Server_Status(sp, DATA_USE);
-+ return sp;
-+ }
-+ sp++;
-+ }
-+ PGR_Stand_Alone->is_stand_alone = true;
-+ if (CurrentReplicateServer != NULL)
-+ {
-+ LastReplicateServer = CurrentReplicateServer;
-+ CurrentReplicateServer->replicate_id = LastReplicateServer->
replicate_id;
-+ }
-+ CurrentReplicateServer = NULL;
-+ return (ReplicateServerInfo *)NULL;
-+}
-+
-+int
-+PGR_Send_Copy(CopyData * copy,int end )
-+{
-+ char cmdSts,cmdType;
-+ char * p = NULL;
-+ char *result = NULL;
-+ char term[8];
-+
-+ if (copy == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ cmdSts = CMD_STS_COPY;
-+
-+ if (Transaction_Mode)
-+ {
-+ cmdSts = CMD_STS_TRANSACTION ;
-+ }
-+ if (Session_Authorization_Mode)
-+ {
-+ cmdSts = CMD_STS_SET_SESSION_AUTHORIZATION ;
-+ }
-+ cmdType = CMD_TYPE_COPY_DATA;
-+
-+ copy->copy_data[copy->cnt] = '\0';
-+ if (end)
-+ {
-+ memset(term,0,sizeof(term));
-+ term[0]='\\';
-+ term[1]='.';
-+ term[2]='\n';
-+ cmdType = CMD_TYPE_COPY_DATA_END;
-+ p = NULL;
-+ if (copy->cnt > 0)
-+ {
-+ copy->copy_data[copy->cnt] = '\0';
-+ p = strstr(copy->copy_data,term);
-+ if (p == NULL)
-+ {
-+ p = &(copy->copy_data[copy->cnt-1]);
-+ copy->cnt--;
-+ }
-+ else
-+ {
-+ p = NULL;
-+ }
-+ }
-+ if (p != NULL)
-+ {
-+ strncpy(p,term,sizeof(term));
-+ copy->cnt += 4;
-+ }
-+ }
-+
-+ result = PGR_Send_Replicate_Command(copy->copy_data, copy->cnt,
cmdSts, cmdType);
-+
-+ if (result != NULL)
-+ {
-+ PGR_Reload_Start_Time();
-+ free(result);
-+ result = NULL;
-+ return STATUS_OK;
-+ }
-+ else
-+ {
-+ return STATUS_ERROR;
-+ }
-+}
-+
-+CopyData *
-+PGR_Set_Copy_Data(CopyData * copy, char *str, int len,int end)
-+{
-+ CopyData save;
-+ int save_len = 0;
-+ int read_index = 0;
-+ int send_size = 0;
-+ int buf_size = 0;
-+ int rest_len = 0;
-+ int rest_buf_size = 0;
-+ int status = STATUS_OK;
-+ char * ep = NULL;
-+ char term[4];
-+
-+ #define BUFF_OFFSET (8)
-+
-+ if ((PGR_Copy_Data_Need_Replicate == false) ||
-+ (copy == NULL))
-+ {
-+ return (CopyData *)NULL;
-+ }
-+ memset(term,0,sizeof(term));
-+ term[0]='\n';
-+ term[1]='\\';
-+ term[2]='.';
-+ buf_size = COPYBUFSIZ - BUFF_OFFSET;
-+ read_index = 0;
-+ rest_len = len;
-+ rest_buf_size = buf_size - copy->cnt;
-+ while ((rest_len > 0) && (rest_buf_size > 0))
-+ {
-+ if (rest_buf_size < rest_len)
-+ {
-+ send_size = rest_buf_size;
-+ rest_len -= send_size;
-+ }
-+ else
-+ {
-+ send_size = rest_len;
-+ rest_len = 0;
-+ }
-+ memcpy(&(copy->copy_data[copy->cnt]) ,str + read_index
,send_size);
-+ copy->cnt += send_size;
-+ read_index += send_size;
-+ rest_buf_size = buf_size - copy->cnt;
-+ if (strstr(copy->copy_data,term) != NULL)
-+ {
-+ break;
-+ }
-+ if (rest_buf_size <= 0)
-+ {
-+ ep = strrchr(copy->copy_data,'\n');
-+ if (ep != NULL)
-+ {
-+ *ep = '\0';
-+ save_len = copy->cnt -
strlen(copy->copy_data) -1;
-+ copy->cnt -= save_len ;
-+ memset(&save,0,sizeof(CopyData));
-+ memcpy(save.copy_data,(ep+1),save_len+1);
-+ save.cnt = save_len;
-+ *ep = '\n';
-+ *(ep+1) = '\0';
-+ status = PGR_Send_Copy(copy,0);
-+ memset(copy,0,sizeof(CopyData));
-+ if (save_len > 0)
-+ {
-+ memcpy(copy,&save,sizeof(CopyData));
-+ }
-+ rest_buf_size = buf_size - copy->cnt;
-+
-+ }
-+ else
-+ {
-+ /* one record is bigger than COPYBUFSIZ */
-+ /* buffer would be over flow*/
-+ status = PGR_Send_Copy(copy,0);
-+ memset(copy,0,sizeof(CopyData));
-+ rest_buf_size = buf_size - copy->cnt;
-+ }
-+ }
-+ }
-+ if (end)
-+ {
-+ status = PGR_Send_Copy(copy,end);
-+ memset(copy,0,sizeof(CopyData));
-+ }
-+ if (status != STATUS_OK)
-+ {
-+ return (CopyData *)NULL;
-+ }
-+ return copy;
-+}
-+
-+int
-+PGR_replication(char * query_string, CommandDest dest, Node *parsetree,
const char * commandTag)
-+{
-+ char *result = NULL;
-+ char cmdSts = CMD_STS_OTHER;
-+ char cmdType = CMD_TYPE_OTHER;
-+ int query_len = 0;
-+
-+ if ((query_string == NULL) ||
-+ (commandTag == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ Query_String = NULL;
-+ query_len = strlen(query_string);
-+
-+ /* save query data for retry */
-+ PGR_Retry_Query.query_string = query_string;
-+ PGR_Retry_Query.query_len = query_len;
-+ PGR_Retry_Query.cmdSts = cmdSts;
-+ PGR_Retry_Query.cmdType = cmdType;
-+ PGR_Retry_Query.useFlag = DATA_USE;
-+ /* set cmdType */
-+ if (!strcmp(commandTag,"BEGIN")) cmdType = CMD_TYPE_BEGIN ;
-+ else if (!strcmp(commandTag,"COMMIT")) cmdType = CMD_TYPE_COMMIT ;
-+ else if (!strcmp(commandTag,"SELECT")) cmdType = CMD_TYPE_SELECT ;
-+ else if (!strcmp(commandTag,"INSERT")) cmdType = CMD_TYPE_INSERT ;
-+ else if (!strcmp(commandTag,"UPDATE")) cmdType = CMD_TYPE_UPDATE ;
-+ else if (!strcmp(commandTag,"DELETE")) cmdType = CMD_TYPE_DELETE ;
-+ else if (!strcmp(commandTag,"VACUUM")) cmdType = CMD_TYPE_VACUUM ;
-+ else if (!strcmp(commandTag,"ANALYZE")) cmdType = CMD_TYPE_ANALYZE ;
-+ else if (!strcmp(commandTag,"REINDEX")) cmdType = CMD_TYPE_REINDEX ;
-+ else if (!strcmp(commandTag,"ROLLBACK")) cmdType = CMD_TYPE_ROLLBACK ;
-+ else if (!strcmp(commandTag,"RESET")) cmdType = CMD_TYPE_RESET ;
-+ else if (!strcmp(commandTag,"START TRANSACTION")) cmdType =
CMD_TYPE_BEGIN ;
-+
-+ /* only "replication_server" statement-name is replicated for SHOW. */
-+ /* see CreateCommandTag() @ backend/tcop/postgres.c */
-+ /*
-+ else if (!strcmp(commandTag,"SHOW"))
-+ {
-+ }
-+ */
-+
-+ else if (!strcmp(commandTag,"COPY"))
-+ {
-+ cmdType = CMD_TYPE_COPY ;
-+ if (is_copy_from(query_string))
-+ {
-+ PGR_Copy_Data_Need_Replicate = true;
-+ }
-+ else
-+ {
-+ PGR_Copy_Data_Need_Replicate = false;
-+ return STATUS_NOT_REPLICATE;
-+ }
-+ }
-+ else if (!strcmp(commandTag,"SET"))
-+ {
-+ /* set pgr_force_loadbalance to on */
-+ if (strstr(query_string,SYS_QUERY_1) != NULL)
-+ {
-+ return STATUS_NOT_REPLICATE;
-+ }
-+ cmdType = CMD_TYPE_SET;
-+ }
-+ else if (!strcmp(commandTag,"CREATE TABLE"))
-+ {
-+ if (is_create_temp_table(query_string))
-+ {
-+ Create_Temp_Table_Mode = true;
-+ }
-+ }
-+ if (Create_Temp_Table_Mode)
-+ {
-+ cmdSts = CMD_STS_TEMP_TABLE ;
-+ }
-+ if (Transaction_Mode > 0)
-+ {
-+ cmdSts = CMD_STS_TRANSACTION ;
-+ }
-+ else if ((cmdType == CMD_TYPE_COMMIT ) ||
-+ (cmdType == CMD_TYPE_ROLLBACK ))
-+ {
-+ cmdSts = CMD_STS_TRANSACTION ;
-+ if (ReplicateCurrentTime != NULL)
-+ {
-+ ReplicateCurrentTime->useFlag = DATA_INIT;
-+ ReplicateCurrentTime->use_seed = 0;
-+ }
-+ }
-+ if (Session_Authorization_Mode)
-+ {
-+ cmdSts = CMD_STS_SET_SESSION_AUTHORIZATION ;
-+ if (cmdType == CMD_TYPE_SESSION_AUTHORIZATION_END)
-+ {
-+ Session_Authorization_Mode = false;
-+ }
-+ }
-+ if ((cmdSts == CMD_STS_TRANSACTION ) ||
-+ (cmdSts == CMD_STS_SET_SESSION_AUTHORIZATION ) ||
-+ (cmdSts == CMD_STS_TEMP_TABLE ))
-+ {
-+ /* check partitional replication table */
-+ if (is_not_replication_query(query_string, query_len,
cmdType)== true )
-+ {
-+ PGR_Copy_Data_Need_Replicate = false;
-+ return STATUS_NOT_REPLICATE;
-+ }
-+ Query_String = NULL;
-+ if (( do_not_replication_command(commandTag) == true) &&
-+ (strcmp(commandTag,"SELECT")))
-+ {
-+ return STATUS_NOT_REPLICATE;
-+ }
-+
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"transaction query send :%s",(char
*)query_string);
-+ PGR_Retry_Query.cmdSts = cmdSts;
-+ PGR_Retry_Query.cmdType = cmdType;
-+ result = PGR_Send_Replicate_Command(query_string,query_len,
cmdSts,cmdType);
-+ if (result != NULL)
-+ {
-+ if
(!strncmp(result,PGR_DEADLOCK_DETECTION_MSG,strlen(PGR_DEADLOCK_DETECTION_MSG)))
-+ {
-+ /*
-+ PGR_Send_Message_To_Frontend(result);
-+ */
-+ free(result);
-+ result = NULL;
-+ return STATUS_DEADLOCK_DETECT;
-+ }
-+ else if
(!strncmp(result,PGR_REPLICATION_ABORT_MSG,strlen(PGR_REPLICATION_ABORT_MSG)))
-+ {
-+ free(result);
-+ result = NULL;
-+ return STATUS_REPLICATION_ABORT;
-+ }
-+ free(result);
-+ result = NULL;
-+ return STATUS_CONTINUE;
-+ }
-+ else
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else
-+ {
-+ cmdSts = CMD_STS_QUERY ;
-+ if ( do_not_replication_command(commandTag) == false)
-+ {
-+ Query_String = NULL;
-+ /* check partitional replication table */
-+ if (is_not_replication_query(query_string, query_len,
cmdType)== true )
-+ {
-+ PGR_Copy_Data_Need_Replicate = false;
-+ return STATUS_NOT_REPLICATE;
-+ }
-+ result =
PGR_Send_Replicate_Command(query_string,query_len,cmdSts,cmdType);
-+ if (result != NULL)
-+ {
-+ if
(!strncmp(result,PGR_DEADLOCK_DETECTION_MSG,strlen(PGR_DEADLOCK_DETECTION_MSG)))
-+ {
-+ free(result);
-+ result = NULL;
-+ return STATUS_DEADLOCK_DETECT;
-+ }
-+ else if
(!strncmp(result,PGR_REPLICATION_ABORT_MSG,strlen(PGR_REPLICATION_ABORT_MSG)))
-+ {
-+ free(result);
-+ result = NULL;
-+ return STATUS_REPLICATION_ABORT;
-+ }
-+ /*
-+ PGR_Send_Message_To_Frontend(result);
-+ */
-+ free(result);
-+ result = NULL;
-+ return STATUS_CONTINUE;
-+ }
-+ else
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else
-+ {
-+ if (( is_serial_control_query(cmdType,query_string)
== true) ||
-+ ( is_select_into_query(cmdType,query_string)
== true))
-+ {
-+ Query_String = NULL;
-+ PGR_Need_Notice = true;
-+ PGR_Check_Lock.check_lock_conflict = true;
-+ result =
PGR_Send_Replicate_Command(query_string,query_len,cmdSts,cmdType);
-+ if (result != NULL)
-+ {
-+ /*
-+ PGR_Send_Message_To_Frontend(result);
-+ */
-+ if
(!strncmp(result,PGR_DEADLOCK_DETECTION_MSG,strlen(PGR_DEADLOCK_DETECTION_MSG)))
-+ {
-+ free(result);
-+ return STATUS_DEADLOCK_DETECT;
-+ }
-+ free(result);
-+ result = NULL;
-+ return STATUS_CONTINUE;
-+ }
-+ else
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else
-+ {
-+ Query_String = query_string;
-+ /*PGR_Sock_To_Replication_Server = -1;*/
-+ }
-+ return STATUS_CONTINUE_SELECT;
-+ }
-+ }
-+ return STATUS_CONTINUE;
-+}
-+
-+
-+bool
-+PGR_Is_System_Command(char * query)
-+{
-+ char * ptr;
-+
-+ if (query == NULL)
-+ {
-+ return false;
-+ }
-+ ptr = strstr(query,PGR_SYSTEM_COMMAND_FUNC);
-+ if (ptr != NULL)
-+ {
-+ ptr = strchr(ptr,'(');
-+ if (ptr == NULL)
-+ return false;
-+ return true;
-+ }
-+ return false;
-+}
-+
-+static int
-+set_command_args(char argv[ PGR_CMD_ARG_NUM ][256],char *str)
-+{
-+ int i,j,cnt,len;
-+ char * ptr = str;
-+
-+ if (str == NULL)
-+ {
-+ return 0;
-+ }
-+ len = strlen(str);
-+ cnt = j = 0;
-+ for ( i = 0 ; i < len ; i++,ptr++)
-+ {
-+ if (cnt >= PGR_CMD_ARG_NUM)
-+ break;
-+ if (( *ptr == ',') || (*ptr == ')'))
-+ {
-+ argv[cnt][j] = '\0';
-+ cnt ++;
-+ j = 0;
-+ continue;
-+ }
-+ argv[cnt][j] = *ptr;
-+ j++;
-+ }
-+ if (cnt < PGR_CMD_ARG_NUM)
-+ argv[cnt][j] = '\0';
-+ cnt ++;
-+
-+ return cnt;
-+}
-+
-+static int
-+add_replication_server(char * hostname,char * port, char * recovery_port)
-+{
-+ int cnt;
-+ int portNumber;
-+ int recoveryPortNumber;
-+ ReplicateServerInfo * sp;
-+
-+ if ((hostname == NULL) ||
-+ (port == NULL ) ||
-+ (recovery_port == NULL ))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (ReplicateServerData == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ portNumber = atoi(port);
-+ recoveryPortNumber = atoi(recovery_port);
-+ cnt = 0;
-+ sp = ReplicateServerData;
-+ while (sp->useFlag != DATA_END){
-+ if((!strncmp(sp->hostName,hostname,sizeof(sp->hostName))) &&
-+ (sp->portNumber == portNumber) &&
-+ (sp->recoveryPortNumber == recoveryPortNumber))
-+ {
-+ if (sp->useFlag != DATA_USE)
-+ {
-+ PGR_Set_Replication_Server_Status(sp,
DATA_INIT);
-+ }
-+ return STATUS_OK;
-+ }
-+ sp ++;
-+ cnt ++;
-+ }
-+ if (cnt < MAX_SERVER_NUM)
-+ {
-+ strncpy(sp->hostName,hostname,sizeof(sp->hostName));
-+ sp->portNumber = portNumber;
-+ sp->recoveryPortNumber = recoveryPortNumber;
-+ PGR_Set_Replication_Server_Status(sp, DATA_INIT);
-+ memset((sp+1),0,sizeof(ReplicateServerInfo));
-+ (sp + 1)->useFlag = DATA_END;
-+ }
-+ else
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+change_replication_server(char * hostname,char * port, char * recovery_port)
-+{
-+ int cnt;
-+ int portNumber;
-+ int recoveryPortNumber;
-+ ReplicateServerInfo * sp;
-+
-+ if ((hostname == NULL) ||
-+ (port == NULL ) ||
-+ (recovery_port == NULL ))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (ReplicateServerData == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ portNumber = atoi(port);
-+ recoveryPortNumber = atoi(recovery_port);
-+ cnt = 0;
-+ sp = ReplicateServerData;
-+ while (sp->useFlag != DATA_END){
-+ if((!strcmp(sp->hostName,hostname)) &&
-+ (sp->portNumber == portNumber) &&
-+ (sp->recoveryPortNumber == recoveryPortNumber))
-+ {
-+ PGR_Set_Replication_Server_Status(sp, DATA_USE);
-+ }
-+ else
-+ {
-+ if (sp->useFlag == DATA_USE)
-+ {
-+ PGR_Set_Replication_Server_Status(sp,
DATA_INIT);
-+ }
-+ }
-+ sp ++;
-+ cnt ++;
-+ }
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_Set_Current_Time(char * sec, char * usec)
-+{
-+ int rtn = 0;
-+ struct timeval local_tp;
-+ struct timezone local_tpz;
-+ struct timeval tv;
-+
-+ if ((sec == NULL) ||
-+ (usec == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ rtn = gettimeofday(&local_tp, &local_tpz);
-+ tv.tv_sec = atol(sec);
-+ tv.tv_usec = atol(usec);
-+ ReplicateCurrentTime->offset_sec = local_tp.tv_sec - tv.tv_sec;
-+ ReplicateCurrentTime->offset_usec = local_tp.tv_usec - tv.tv_usec;
-+ ReplicateCurrentTime->tp.tv_sec = tv.tv_sec;
-+ ReplicateCurrentTime->tp.tv_usec = tv.tv_usec;
-+ ReplicateCurrentTime->useFlag = DATA_USE;
-+ ReplicateCurrentTime->use_seed = 0;
-+
-+ return STATUS_OK;
-+}
-+
-+static void
-+PGR_Set_Current_Replication_Query_ID(char *id) {
-+ MyProc->replicationId=atol(id);
-+ return;
-+}
-+
-+static void
-+set_response_mode(char * mode)
-+{
-+ int response_mode = 0;
-+
-+ if (mode == NULL)
-+ return;
-+ response_mode = atoi(mode);
-+ if (response_mode < 0)
-+ return;
-+ if (CurrentReplicateServer == NULL)
-+ {
-+ PGR_get_replicate_server_info();
-+ if (CurrentReplicateServer == NULL)
-+ {
-+ return;
-+ }
-+ }
-+ if (CurrentReplicateServer->response_mode != response_mode)
-+ {
-+ CurrentReplicateServer->response_mode = response_mode;
-+ }
-+}
-+
-+int
-+PGR_Call_System_Command(char * command)
-+{
-+ char * ptr;
-+ char * args;
-+ char argv[ PGR_CMD_ARG_NUM ][256];
-+ int argc = 0;
-+ int func_no;
-+ char * hostName = NULL;
-+
-+ if ((command == NULL) || (ReplicateCurrentTime == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ ptr = strstr(command,PGR_SYSTEM_COMMAND_FUNC);
-+ if (ptr == NULL)
-+ return STATUS_ERROR;
-+ ptr = strchr(ptr,'(');
-+ if (ptr == NULL)
-+ return STATUS_ERROR;
-+ args = ptr+1;
-+ ptr = strchr(ptr,')');
-+ if (ptr == NULL)
-+ return STATUS_ERROR;
-+ *ptr = '\0';
-+ argc = set_command_args(argv,args);
-+ if (argc < 1)
-+ return STATUS_ERROR;
-+ func_no = atoi(argv[0]);
-+ switch (func_no)
-+ {
-+ /* set current system time */
-+ case PGR_SET_CURRENT_TIME_FUNC_NO:
-+ if (atol(argv[1]) == 0)
-+ {
-+ CreateCheckPoint(false,true);
-+ }
-+ else
-+ {
-+ /*
-+ if ((atoi(argv[3]) > 0) &&
-+ (is_this_query_replicated(argv[3]) == true))
-+ {
-+ return STATUS_SKIP_QUERY;
-+ }
-+ */
-+ PGR_Set_Current_Time(argv[1],argv[2]);
-+ set_replication_id(argv[3]);
-+ set_response_mode(argv[4]);
-+ PGR_Set_Current_Replication_Query_ID(argv[5]);
-+
-+ }
-+ break;
-+ /* add new replication server data */
-+ case PGR_STARTUP_REPLICATION_SERVER_FUNC_NO:
-+ hostName = get_hostName(argv[1]);
-+ add_replication_server(hostName,argv[2],argv[3]);
-+ break;
-+ /* change new replication server */
-+ case PGR_CHANGE_REPLICATION_SERVER_FUNC_NO:
-+ hostName = get_hostName(argv[1]);
-+ change_replication_server(hostName,argv[2],argv[3]);
-+ break;
-+ case PGR_SET_CURRENT_REPLICATION_QUERY_ID_NO:
-+ PGR_Set_Current_Replication_Query_ID(argv[1]);
-+ break;
-+ /* check replication id */
-+ case PGR_QUERY_CONFIRM_ANSWER_FUNC_NO:
-+ if ((atoi(argv[3]) > 0) &&
-+ (is_this_query_replicated(argv[3]) == true))
-+ {
-+ /* skip this query */
-+ return STATUS_SKIP_QUERY;
-+ }
-+ else
-+ {
-+ PGR_Set_Current_Time(argv[1],argv[2]);
-+ set_replication_id(argv[3]);
-+ }
-+ break;
-+ /* get current oid */
-+ case PGR_GET_OID_FUNC_NO:
-+ return_current_oid();
-+ break;
-+ /* set current oid */
-+ case PGR_SET_OID_FUNC_NO:
-+ sync_oid(argv[1]);
-+ break;
-+ /* set noticed session abort */
-+ case PGR_NOTICE_ABORT_FUNC_NO:
-+ PGR_Noticed_Abort = 1;
-+ break;
-+ }
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_GetTimeOfDay(struct timeval *tp, struct timezone *tpz)
-+{
-+
-+ int rtn;
-+
-+ rtn = gettimeofday(tp, tpz);
-+ if (ReplicateCurrentTime == NULL)
-+ {
-+ return rtn;
-+ }
-+ if (ReplicateCurrentTime->useFlag == DATA_USE)
-+ {
-+ if (ReplicateCurrentTime->use_seed != 0)
-+ {
-+ tp->tv_sec -= ReplicateCurrentTime->offset_sec;
-+ if (tp->tv_usec < ReplicateCurrentTime->offset_usec)
-+ {
-+ tp->tv_usec += (1000000 -
ReplicateCurrentTime->offset_usec);
-+ tp->tv_sec -= 1;
-+ }
-+ else
-+ {
-+ tp->tv_usec -=
ReplicateCurrentTime->offset_usec;
-+ }
-+ }
-+ else
-+ {
-+ tp->tv_sec = ReplicateCurrentTime->tp.tv_sec;
-+ tp->tv_usec = ReplicateCurrentTime->tp.tv_usec;
-+ }
-+ rtn = 0;
-+ }
-+ return rtn;
-+}
-+
-+long
-+PGR_Random(void)
-+{
-+ double rtn;
-+ if (ReplicateCurrentTime != NULL)
-+ {
-+ if ( ReplicateCurrentTime->use_seed == 0)
-+ {
-+ srand( ReplicateCurrentTime->tp.tv_usec );
-+ }
-+ }
-+ rtn = random();
-+ return rtn;
-+}
-+
-+char *
-+PGR_scan_terminate( char * str)
-+{
-+ char * p;
-+ int sflag = 0;
-+ int dflag = 0;
-+ int lflag = 0;
-+ int i = 0;
-+ char tag[256];
-+
-+ if (str == NULL)
-+ return NULL;
-+ p = str;
-+ memset(tag,0,sizeof(tag));
-+ while ( *p != '\0' )
-+ {
-+ if ((!strncmp(p,"--",2)) ||
-+ (!strncmp(p,"//",2)))
-+ {
-+ while (( *p != '\n') && (*p != '\0'))
-+ {
-+ p++;
-+ }
-+ continue;
-+ }
-+
-+ switch (*p)
-+ {
-+ case '\'':
-+ sflag ^= 1;
-+ break;
-+ case '\"':
-+ dflag ^= 1;
-+ break;
-+ case '$':
-+ i = 0;
-+ p++;
-+ while (( *p != '\n') && (*p != '\0'))
-+ {
-+ if (isalnum(*p) == 0)
-+ {
-+ if (*p == '$')
-+ {
-+ lflag ^= 1;
-+ }
-+ break;
-+ }
-+ else
-+ {
-+ if (i >= sizeof(tag))
-+ break;
-+ if (lflag == 0)
-+ {
-+ tag[i] = *p;
-+ }
-+ else
-+ {
-+ if (tag[i] != *p)
-+ {
-+ break;
-+ }
-+ }
-+ i++;
-+ }
-+ p++;
-+ }
-+ break;
-+ case '\\':
-+ p +=2;
-+ continue;
-+ break;
-+ case ';':
-+ if ((!sflag) && (!dflag) && (!lflag))
-+ return p;
-+ break;
-+ }
-+ p++;
-+ }
-+ return NULL;
-+}
-+
-+static bool
-+is_copy_from(char * query)
-+{
-+ char * p;
-+ int i;
-+ char buf[12];
-+ int c_flag = 0;
-+ if (query == NULL)
-+ return false;
-+ p = query;
-+ for ( i = 0 ; i <= 1 ; i ++)
-+ {
-+ /* get 'copy table_name' string */
-+ while(isspace(*p))
-+ p++;
-+ while ((*p != '\0') && (*p != '(') && (!isspace(*p)))
-+ p++;
-+ }
-+ while(isspace(*p))
-+ p++;
-+ /* skip table column */
-+ if (*p == '(')
-+ {
-+ c_flag = 1;
-+ p++;
-+ while (*p != '\0')
-+ {
-+ if (*p == '(')
-+ c_flag ++;
-+ if (*p == ')')
-+ c_flag --;
-+ if (c_flag == 0)
-+ {
-+ p++;
-+ break;
-+ }
-+ p++;
-+ }
-+ while(isspace(*p))
-+ p++;
-+ }
-+ /* get 'from' or 'to' */
-+ i = 0;
-+ memset(buf,0,sizeof(buf));
-+ while ((*p != '\0') && (!isspace(*p)) && ( i < sizeof(buf)-1))
-+ {
-+ buf[i] = (char)toupper(*p);
-+ p++;
-+ i++;
-+ }
-+ if (!strcmp(buf,"FROM"))
-+ {
-+ return true;
-+ }
-+ else
-+ {
-+ return false;
-+ }
-+}
-+
-+static bool
-+is_create_temp_table(char * query)
-+{
-+ int len,wc;
-+ char buf[MAX_WORDS][MAX_WORD_LETTERS];
-+
-+ if (query == NULL)
-+ return false;
-+ len = strlen(query);
-+ wc = get_words(buf,query,len,1);
-+ if (wc < 4)
-+ return false;
-+ if ((!strncmp(buf[0],"CREATE", strlen("CREATE"))) &&
-+ (!strncmp(buf[1],"TEMP",strlen("TEMP"))) &&
-+ (!strncmp(buf[2],"TABLE",strlen("TABLE"))))
-+ {
-+ return true;
-+ }
-+ return false;
-+}
-+
-+static int
-+get_words( char words[MAX_WORDS][MAX_WORD_LETTERS] ,char * string,int
length,int upper)
-+{
-+ int i,wc,lc;
-+ char * p = NULL;
-+ char * buf = NULL;
-+
-+ if (string == NULL)
-+ return STATUS_ERROR;
-+ buf = malloc(length);
-+ if (buf == NULL)
-+ return STATUS_ERROR;
-+
-+ memset(buf,0,length);
-+ p = string;
-+ wc = 0;
-+ for (i = 0 ; i < length ; i ++)
-+ {
-+ if ((*p == '\0') || (wc >= MAX_WORDS))
-+ break;
-+ while (isspace(*p))
-+ {
-+ p++;
-+ i++;
-+ }
-+ lc = 0;
-+ while ((*p != '\0') && (! isspace(*p)))
-+ {
-+ if (upper)
-+ *(buf+lc) = (char)toupper(*p);
-+ else
-+ *(buf+lc) = *p;
-+
-+ p++;
-+ i++;
-+ lc++;
-+ }
-+ memset(words[wc],0,MAX_WORD_LETTERS);
-+ memcpy(words[wc],buf,lc);
-+ memset(buf,0,length);
-+ wc++;
-+ }
-+ free(buf);
-+ buf = NULL;
-+ return wc;
-+}
-+
-+static int
-+Comp_Not_Replicate(PGR_Not_Replicate_Type * nrp1,PGR_Not_Replicate_Type*
nrp2)
-+{
-+ int rtn;
-+
-+ if ((nrp1 == NULL) ||
-+ (nrp2 == NULL))
-+ {
-+ return 0;
-+ }
-+ rtn = strcasecmp(nrp1->table_name,nrp2->table_name);
-+ if (rtn == 0)
-+ {
-+ rtn = strcasecmp(nrp1->db_name,nrp2->db_name);
-+ }
-+ return rtn;
-+}
-+
-+bool
-+PGR_Is_Stand_Alone(void)
-+{
-+ ReplicateServerInfo * sp = NULL;
-+
-+ if (PGR_Stand_Alone == NULL)
-+ return true;
-+ if (PGR_Stand_Alone->is_stand_alone == true)
-+ {
-+ sp = PGR_get_replicate_server_info();
-+ if (sp == NULL)
-+ {
-+ return true;
-+ }
-+ }
-+ return false;
-+}
-+
-+void
-+PGR_Send_Message_To_Frontend(const char * msg)
-+{
-+ StringInfoData msgbuf;
-+
-+ pq_beginmessage(&msgbuf, 'N');
-+
-+ if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
-+ {
-+ /* New style with separate fields */
-+ char tbuf[12];
-+ int ssval;
-+ int i;
-+
-+ pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY);
-+ pq_sendstring(&msgbuf, "NOTICE" );
-+
-+ /* unpack MAKE_SQLSTATE code */
-+ ssval = ERRCODE_WARNING ;
-+ for (i = 0; i < 5; i++)
-+ {
-+ tbuf[i] = PGUNSIXBIT(ssval);
-+ ssval >>= 6;
-+ }
-+ tbuf[i] = '\0';
-+
-+ pq_sendbyte(&msgbuf, PG_DIAG_SQLSTATE);
-+ pq_sendstring(&msgbuf, tbuf);
-+
-+ /* M field is required per protocol, so always send something
*/
-+ pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY);
-+ if (msg)
-+ pq_sendstring(&msgbuf, msg);
-+ else
-+ pq_sendstring(&msgbuf, _("missing error text"));
-+
-+ pq_sendbyte(&msgbuf, '\0'); /* terminator */
-+ }
-+ else
-+ {
-+ /* Old style --- gin up a backwards-compatible message */
-+ StringInfoData buf;
-+
-+ initStringInfo(&buf);
-+
-+ appendStringInfo(&buf, "%s: ", "NOTICE");
-+
-+ if (msg)
-+ appendStringInfoString(&buf, msg);
-+ else
-+ appendStringInfoString(&buf, _("missing error text"));
-+
-+ appendStringInfoChar(&buf, '\n');
-+
-+ pq_sendstring(&msgbuf, buf.data);
-+
-+ pfree(buf.data);
-+ }
-+
-+ pq_endmessage(&msgbuf);
-+
-+ /*
-+ * This flush is normally not necessary, since postgres.c will flush
out
-+ * waiting data when control returns to the main loop. But it seems
best
-+ * to leave it here, so that the client has some clue what happened
if the
-+ * backend dies before getting back to the main loop ... error/notice
-+ * messages should not be a performance-critical path anyway, so an
extra
-+ * flush won't hurt much ...
-+ */
-+ pq_flush();
-+}
-+
-+static bool
-+is_serial_control_query(char cmdType,char * query)
-+{
-+ char * buf = NULL;
-+ int len = 0;
-+ int i = 0;
-+ char * p = NULL;
-+
-+ if ((cmdType != CMD_TYPE_SELECT ) ||
-+ ( query == NULL))
-+ {
-+ return false;
-+ }
-+
-+ p = query;
-+ len = strlen(query) +1;
-+ buf = malloc(len);
-+ if (buf == NULL)
-+ return false;
-+
-+ memset(buf,0,len);
-+ for ( i = 0 ; i < len ; i ++)
-+ {
-+ *(buf+i) = toupper(*(query+i));
-+ }
-+ if ((strstr(buf,"NEXTVAL") != NULL) ||
-+ (strstr(buf,"SETVAL") != NULL))
-+ {
-+ free(buf);
-+ buf = NULL;
-+ return true;
-+ }
-+ free(buf);
-+ buf = NULL;
-+ return false;
-+}
-+
-+static bool
-+is_select_into_query(char cmdType,char * query)
-+{
-+ char * buf = NULL;
-+ int len = 0;
-+ int i = 0;
-+ char * p = NULL;
-+
-+ if ((cmdType != CMD_TYPE_SELECT ) ||
-+ ( query == NULL))
-+ {
-+ return false;
-+ }
-+
-+ p = query;
-+ len = strlen(query) +1;
-+ buf = malloc(len);
-+ if (buf == NULL)
-+ return false;
-+
-+ memset(buf,0,len);
-+ for ( i = 0 ; i < len ; i ++)
-+ {
-+ *(buf+i) = toupper(*(query+i));
-+ }
-+ if (strstr(buf,"INTO") != NULL)
-+ {
-+ free(buf);
-+ buf = NULL;
-+ return true;
-+ }
-+ if (strstr(buf,"CREATE") != NULL)
-+ {
-+ free(buf);
-+ buf = NULL;
-+ return true;
-+ }
-+ free(buf);
-+ buf = NULL;
-+ return false;
-+}
-+
-+static int
-+send_response_to_replication_server(const char * notice)
-+{
-+ ReplicateHeader header;
-+ int status;
-+ if (PGR_Lock_Noticed)
-+ {
-+ return STATUS_OK;
-+ }
-+ if ((notice == NULL) ||
-+ (PGR_Sock_To_Replication_Server < 0))
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ header.cmdSys = CMD_SYS_CALL;
-+ header.cmdSts = CMD_STS_RESPONSE;
-+ if (!strcmp(notice,PGR_QUERY_ABORTED_NOTICE_CMD))
-+ {
-+ header.cmdType = CMD_TYPE_FRONTEND_CLOSED;
-+ }
-+ header.query_size = htonl(strlen(notice));
-+ status =
send_replicate_packet(PGR_Sock_To_Replication_Server,&header,(char *)notice);
-+ return status;
-+}
-+
-+void
-+PGR_Notice_Transaction_Query_Done(void)
-+{
-+ send_response_to_replication_server(PGR_QUERY_DONE_NOTICE_CMD);
-+}
-+
-+void
-+PGR_Notice_Transaction_Query_Aborted(void)
-+{
-+ send_response_to_replication_server(PGR_QUERY_ABORTED_NOTICE_CMD);
-+}
-+
-+int
-+PGR_Notice_Conflict(void)
-+{
-+ const char * msg = NULL ;
-+ int rtn = STATUS_OK;
-+
-+ msg = PGR_LOCK_CONFLICT_NOTICE_CMD ;
-+ if (PGR_Check_Lock.deadlock == true)
-+ {
-+ msg = PGR_DEADLOCK_DETECT_NOTICE_CMD ;
-+ }
-+ if (PGR_Check_Lock.dest == TO_FRONTEND)
-+ {
-+ ReadyForQuery(DestRemote);
-+ EndCommand(msg,DestRemote);
-+#ifdef CONTROL_LOCK_CONFLICT
-+ rtn = wait_lock_answer();
-+#endif /* CONTROL_LOCK_CONFLICT */
-+ }
-+ else
-+ {
-+ send_response_to_replication_server(msg);
-+#ifdef CONTROL_LOCK_CONFLICT
-+ rtn = PGR_Recv_Trigger (PGR_RECV_TIMEOUT);
-+#endif /* CONTROL_LOCK_CONFLICT */
-+ }
-+ return rtn;
-+}
-+
-+#ifdef CONTROL_LOCK_CONFLICT
-+static int
-+wait_lock_answer(void)
-+{
-+ char result[PGR_MESSAGE_BUFSIZE+4];
-+ int rtn = 0;
-+
-+ memset(result,0,sizeof(result));
-+ rtn = read_trigger(result, PGR_MESSAGE_BUFSIZE);
-+ if (rtn < 0)
-+ return STATUS_ERROR;
-+ return STATUS_OK;
-+}
-+
-+static int
-+read_trigger(char * result, int buf_size)
-+{
-+ int i = 0;
-+ char c;
-+ int r = 0;
-+
-+ if ((result == NULL) || (buf_size <= 0 ))
-+ {
-+ return EOF;
-+ }
-+ while ((r = pq_getbytes(&c,1)) == 0)
-+ {
-+ if (i < buf_size -1)
-+ {
-+ *(result + i) = c;
-+ }
-+ else
-+ {
-+ break;
-+ }
-+ if (c == '\0')
-+ break;
-+ i++;
-+ }
-+
-+ return r;
-+}
-+#endif /* CONTROL_LOCK_CONFLICT */
-+
-+int
-+PGR_Recv_Trigger (int user_timeout)
-+{
-+ char result[PGR_MESSAGE_BUFSIZE];
-+ int rtn = 0;
-+ int func_no = 0;
-+
-+
-+ if (PGR_Lock_Noticed)
-+ {
-+ return STATUS_OK;
-+ }
-+ if (PGR_Sock_To_Replication_Server < 0)
-+ return STATUS_ERROR;
-+ memset(result,0,sizeof(result));
-+ rtn =
recv_replicate_result(PGR_Sock_To_Replication_Server,result,user_timeout);
-+ if (rtn > 0)
-+ {
-+ func_no = atoi(result);
-+ if (func_no <= 0)
-+ {
-+ func_no = STATUS_OK;
-+ }
-+ return func_no;
-+ }
-+ else
-+ {
-+ if (user_timeout == 0)
-+ {
-+
PGR_Set_Replication_Server_Status(CurrentReplicateServer, DATA_ERR);
-+ }
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_Set_Transaction_Mode(int mode,const char * commandTag)
-+{
-+ if (commandTag == NULL)
-+ {
-+ return mode;
-+ }
-+ if ((!strcmp(commandTag,"BEGIN")) ||
-+ (!strcmp(commandTag,"START TRANSACTION")) )
-+ {
-+ return (++mode);
-+ }
-+ if (mode > 0)
-+ {
-+ if ((!strncmp(commandTag,"COMMIT",strlen("COMMIT"))) ||
-+ (!strncmp(commandTag,"ROLLBACK",strlen("ROLLBACK"))))
-+ {
-+ return (--mode);
-+ }
-+ }
-+ /*
-+ if (autocommit == false)
-+ {
-+ return mode;
-+ }
-+ */
-+ return mode;
-+}
-+
-+
-+
-+static bool
-+do_not_replication_command(const char * commandTag)
-+{
-+ if (commandTag == NULL)
-+ {
-+ return true;
-+ }
-+ if ((!strcmp(commandTag,"SELECT")) ||
-+ (!strcmp(commandTag,"CLOSE CURSOR")) ||
-+ (!strcmp(commandTag,"MOVE")) ||
-+ (!strcmp(commandTag,"FETCH")) ||
-+ (!strcmp(commandTag,"EXPLAIN")))
-+ {
-+ return true;
-+ }
-+ else
-+ {
-+ return false;
-+ }
-+}
-+
-+void
-+PGR_Set_Replication_Server_Status( ReplicateServerInfo * sp, int status)
-+{
-+ if (sp == NULL)
-+ {
-+ return;
-+ }
-+ if (sp->useFlag != status)
-+ {
-+ sp->useFlag = status;
-+ }
-+}
-+
-+int
-+PGR_Is_Skip_Replication(char * query)
-+{
-+ char skip_2[256];
-+
-+ if ((query == NULL) ||
-+ (MyProcPort == NULL))
-+ {
-+ return -1;
-+ }
-+ snprintf(skip_2,sizeof(skip_2),SKIP_QUERY_2,MyProcPort->user_name);
-+ if ((strncmp(query,SKIP_QUERY_1,strlen(SKIP_QUERY_1)) == 0) ||
-+ (strncmp(query,skip_2,strlen(skip_2)) == 0))
-+ {
-+ return 3;
-+ }
-+ if ((strncmp(query,SKIP_QUERY_3,strlen(SKIP_QUERY_3)) == 0) ||
-+ (strncmp(query,SKIP_QUERY_4,strlen(SKIP_QUERY_4)) == 0))
-+ {
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+bool
-+PGR_Did_Commit_Transaction(void)
-+{
-+ int sock = -1;
-+ int cnt = 0;
-+ ReplicateHeader header;
-+ char * serverName = NULL;
-+ int portNumber=0;
-+ char * result = NULL;
-+ ReplicateServerInfo * sp = NULL;
-+ ReplicateServerInfo * base = NULL;
-+ int socket_type = 0;
-+ char argv[ PGR_CMD_ARG_NUM ][256];
-+ int argc = 0;
-+ int func_no = 0;
-+
-+ if (ReplicateCurrentTime->useFlag != DATA_USE)
-+ {
-+ return false;
-+ }
-+ sp = PGR_get_replicate_server_info();
-+ if (sp == NULL)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"PGR_get_replicate_server_info get
error");
-+ return false;
-+ }
-+ sock = get_replicate_server_socket( sp , PGR_QUERY_SOCKET);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"get_replicate_server_socket fail");
-+ return false;
-+ }
-+ result = malloc(PGR_MESSAGE_BUFSIZE);
-+ if (result == NULL)
-+ {
-+ return false;
-+ }
-+ memset(result,0,PGR_MESSAGE_BUFSIZE);
-+
-+ serverName = sp->hostName;
-+ portNumber = (int)sp->portNumber;
-+ header.cmdSys = CMD_SYS_CALL;
-+ header.cmdSts = CMD_STS_TRANSACTION_ABORT;
-+ header.cmdType = CMD_TYPE_COMMIT_CONFIRM;
-+ header.port = htons(PostPortNumber);
-+ header.pid = htons(getpid());
-+ header.tv.tv_sec = htonl(ReplicateCurrentTime->tp.tv_sec);
-+ header.tv.tv_usec = htonl(ReplicateCurrentTime->tp.tv_usec);
-+ header.query_size = htonl(0);
-+ strncpy(header.dbName ,(char
*)(MyProcPort->database_name),sizeof(header.dbName)-1);
-+ strncpy(header.userName , (char
*)(MyProcPort->user_name),sizeof(header.userName)-1);
-+ if (PGRSelfHostName != NULL)
-+ {
-+ strncpy(header.from_host, PGRSelfHostName,
HOSTNAME_MAX_LENGTH);
-+ }
-+ header.replicate_id = htonl(ReplicationLog_Info.PGR_Replicate_ID);
-+ header.request_id = 0;
-+
-+ base = sp;
-+ PGR_Sock_To_Replication_Server = sock;
-+
-+retry_send_confirm_packet:
-+
-+ cnt = 0;
-+ while (send_replicate_packet(sock,&header,"") != STATUS_OK)
-+ {
-+ if (cnt > MAX_RETRY_TIMES )
-+ {
-+ sock = get_new_replication_socket( base, sp,
socket_type);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"all replication servers
may be down");
-+ PGR_Stand_Alone->is_stand_alone = true;
-+ free(result);
-+ result = NULL;
-+ return false;
-+ }
-+ PGR_Sock_To_Replication_Server = sock;
-+ cnt = 0;
-+ }
-+ cnt ++;
-+ }
-+
-+ if (recv_replicate_result(sock,result,0) < 0)
-+ {
-+ /* replication server should be down */
-+ sock = get_new_replication_socket( base, sp, socket_type);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"all replication servers may be
down");
-+ PGR_Stand_Alone->is_stand_alone = true;
-+ free(result);
-+ result = NULL;
-+ return false;
-+ }
-+ PGR_Sock_To_Replication_Server = sock;
-+ goto retry_send_confirm_packet;
-+ }
-+ /* read answer */
-+ argc = set_command_args(argv,result);
-+ if (argc >= 1)
-+ {
-+ func_no = atoi(argv[0]);
-+ if (func_no == PGR_TRANSACTION_CONFIRM_ANSWER_FUNC_NO)
-+ {
-+ /* the transaction was commited in other server */
-+ if (atoi(argv[1]) == PGR_ALREADY_COMMITTED)
-+ {
-+ free(result);
-+ result = NULL;
-+ return true;
-+ }
-+ }
-+ }
-+ free(result);
-+ result = NULL;
-+ return false;
-+}
-+
-+int
-+PGRsend_system_command(char cmdSts, char cmdType)
-+{
-+ ReplicateServerInfo * sp = NULL;
-+ int sock = -1;
-+ int socket_type = 0;
-+ char * result = NULL;
-+ char * serverName = NULL;
-+ int portNumber=0;
-+ ReplicateHeader header;
-+ int cnt = 0;
-+ ReplicateServerInfo * base = NULL;
-+
-+ sp = PGR_get_replicate_server_info();
-+ if (sp == NULL)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"PGR_get_replicate_server_info get
error");
-+ return STATUS_ERROR;
-+ }
-+ sock = get_replicate_server_socket( sp , PGR_QUERY_SOCKET);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"get_replicate_server_socket fail");
-+ return STATUS_ERROR;
-+ }
-+ result = malloc(PGR_MESSAGE_BUFSIZE);
-+ if (result == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(result,0,PGR_MESSAGE_BUFSIZE);
-+
-+ serverName = sp->hostName;
-+ portNumber = (int)sp->portNumber;
-+ header.cmdSys = CMD_SYS_CALL;
-+ header.cmdSts = cmdSts;
-+ header.cmdType = cmdType;
-+ header.port = htons(PostPortNumber);
-+ header.pid = htons(getpid());
-+ header.tv.tv_sec = htonl(ReplicateCurrentTime->tp.tv_sec);
-+ header.tv.tv_usec = htonl(ReplicateCurrentTime->tp.tv_usec);
-+ header.query_size = htonl(0);
-+ strncpy(header.dbName ,(char
*)(MyProcPort->database_name),sizeof(header.dbName)-1);
-+ strncpy(header.userName , (char
*)(MyProcPort->user_name),sizeof(header.userName)-1);
-+ if (PGRSelfHostName != NULL)
-+ {
-+ strncpy(header.from_host, PGRSelfHostName,
HOSTNAME_MAX_LENGTH);
-+ }
-+ header.replicate_id = htonl(ReplicationLog_Info.PGR_Replicate_ID);
-+ header.request_id = 0;
-+
-+ base = sp;
-+ PGR_Sock_To_Replication_Server = sock;
-+ cnt = 0;
-+ while (send_replicate_packet(sock,&header,"") != STATUS_OK)
-+ {
-+ if (cnt > MAX_RETRY_TIMES )
-+ {
-+ sock = get_new_replication_socket( base, sp,
socket_type);
-+ if (sock < 0)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"all replication servers
may be down");
-+ PGR_Stand_Alone->is_stand_alone = true;
-+ free(result);
-+ result = NULL;
-+ return STATUS_ERROR;
-+ }
-+ PGR_Sock_To_Replication_Server = sock;
-+ cnt = 0;
-+ }
-+ cnt ++;
-+ }
-+ free(result);
-+ result = NULL;
-+ return STATUS_OK;
-+}
-+
-+static char *
-+get_hostName(char * str)
-+{
-+ char * top = NULL;
-+ char * p = NULL;
-+
-+ p = str;
-+ while ( *p != '\0')
-+ {
-+ if (*p == '\'')
-+ {
-+ *p = '\0';
-+ p++;
-+ if (top == NULL)
-+ {
-+ top = p;
-+ }
-+ }
-+ p++;
-+ }
-+ return top;
-+}
-+
-+char *
-+PGR_Remove_Comment(char * str)
-+{
-+ char * p = NULL;
-+ p = str;
-+ while( *p != '\0')
-+ {
-+ while(isspace(*p))
-+ {
-+ p++;
-+ }
-+ if ((!memcmp(p,"--",2)) ||
-+ (!memcmp(p,"//",2)))
-+ {
-+ while((*p != '\n') && (*p != '\0'))
-+ {
-+ p++;
-+ }
-+ continue;
-+ }
-+ break;
-+ }
-+ return p;
-+}
-+
-+void
-+PGR_Force_Replicate_Query(void)
-+{
-+ if (PGR_Retry_Query.useFlag == DATA_USE)
-+ {
-+ PGR_Send_Replicate_Command(PGR_Retry_Query.query_string,
-+ PGR_Retry_Query.query_len,
-+ PGR_Retry_Query.cmdSts,
-+ PGR_Retry_Query.cmdType);
-+ }
-+}
-+
-+void
-+PGR_Notice_DeadLock(void)
-+{
-+ ReplicateHeader header;
-+
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ header.cmdSys = CMD_SYS_CALL;
-+ header.cmdSts = CMD_STS_NOTICE;
-+ header.cmdType = CMD_TYPE_DEADLOCK_DETECT;
-+ header.query_size = 0;
-+ send_replicate_packet(PGR_Sock_To_Replication_Server,&header,(char
*)NULL);
-+}
-+
-+void
-+PGR_Set_Cluster_Status(int status)
-+{
-+ if (ClusterDBData != NULL)
-+ {
-+ if (ClusterDBData->status != status)
-+ {
-+ ClusterDBData->status = status;
-+ }
-+ }
-+}
-+
-+int
-+PGR_Get_Cluster_Status(void)
-+{
-+ if (ClusterDBData != NULL)
-+ {
-+ return (ClusterDBData->status);
-+ }
-+ return 0;
-+}
-+
-+int
-+PGR_Check_Replicate_Server_Status(ReplicateServerInfo * sp)
-+{
-+ ReplicateHeader header;
-+ char * result = NULL;
-+ int status;
-+ int fdP;
-+
-+ result = malloc(PGR_MESSAGE_BUFSIZE + 4);
-+ if (result == NULL)
-+ {
-+ if (Debug_pretty_print)
-+ elog(DEBUG1,"malloc failed in
PGR_Check_Replicate_Server_Status()");
-+ return STATUS_ERROR;
-+ }
-+
-+ memset(&header, 0, sizeof(ReplicateHeader));
-+ memset(result, 0, PGR_MESSAGE_BUFSIZE + 4);
-+
-+ header.cmdSys = CMD_SYS_PREREPLICATE;
-+ header.cmdSts = CMD_STS_OTHER;
-+ header.cmdType = CMD_TYPE_OTHER;
-+ header.port = htons(PostPortNumber);
-+ header.pid = htons(getpid());
-+ header.query_size = 0;
-+ strncpy(header.dbName ,(char
*)(MyProcPort->database_name),sizeof(header.dbName)-1);
-+ strncpy(header.userName , (char
*)(MyProcPort->user_name),sizeof(header.userName)-1);
-+ header.request_id = htonl(get_next_request_id());
-+ header.rlog = 0;
-+ if (PGRSelfHostName != NULL) {
-+ strncpy(header.from_host, PGRSelfHostName,
HOSTNAME_MAX_LENGTH);
-+ }
-+
-+ /* open a new socket for lifecheck */
-+ if ((status = PGR_Create_Socket_Connect(&fdP, sp->hostName,
sp->portNumber)) == STATUS_ERROR) {
-+ if (Debug_pretty_print) {
-+ elog(DEBUG1,"create socket failed in
PGR_Create_Socket_Connect()");
-+ }
-+
-+ /* status = STATUS_OK */
-+ } else {
-+ if ((status = send_replicate_packet(fdP, &header, (char
*)NULL)) == STATUS_OK) {
-+ /* receive result to check for possible deadlock */
-+ status = (0 < recv_replicate_result(fdP, result ,0))
-+ ? STATUS_OK : STATUS_ERROR;
-+ }
-+ }
-+
-+ free(result);
-+ PGR_Close_Sock(&fdP);
-+
-+ return status;
-+}
-+
-+static int
-+return_current_oid(void)
-+{
-+ char msg[PGR_MESSAGE_BUFSIZE];
-+
-+ LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
-+
-+ if (ShmemVariableCache->nextOid < ((Oid) FirstBootstrapObjectId))
-+ {
-+ ShmemVariableCache->nextOid = FirstBootstrapObjectId;
-+ ShmemVariableCache->oidCount = 0;
-+ }
-+
-+ if (ShmemVariableCache->oidCount == 0)
-+ {
-+ XLogPutNextOid(ShmemVariableCache->nextOid +
VAR_OID_PREFETCH);
-+ ShmemVariableCache->oidCount = VAR_OID_PREFETCH;
-+ }
-+ LWLockRelease(OidGenLock);
-+
-+ memset(msg,0,sizeof(msg));
-+ snprintf(msg, sizeof(msg), "%u", ShmemVariableCache->nextOid);
-+ if (PGR_Check_Lock.dest == TO_FRONTEND)
-+ {
-+ /*
-+ PGR_Send_Message_To_Frontend(msg);
-+ */
-+ pq_puttextmessage('C',msg);
-+ pq_flush();
-+ }
-+ else
-+ {
-+ send_response_to_replication_server(msg);
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+sync_oid(char * oid)
-+{
-+ uint32_t next_oid = 0;
-+ int offset = 0;
-+ char msg[PGR_MESSAGE_BUFSIZE];
-+
-+ LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
-+
-+ next_oid = strtoul(oid, NULL, 10);
-+ if (next_oid <= 0)
-+ return STATUS_ERROR;
-+ next_oid ++;
-+ offset = next_oid - ShmemVariableCache->nextOid ;
-+ if (offset <= 0)
-+ return STATUS_ERROR;
-+
-+ if (next_oid < FirstBootstrapObjectId)
-+ {
-+ ShmemVariableCache->nextOid = FirstBootstrapObjectId;
-+ ShmemVariableCache->oidCount = 0;
-+ }
-+
-+ /* If we run out of logged for use oids then we must log more */
-+ while (ShmemVariableCache->oidCount - offset <= 0)
-+ {
-+ offset -= (ShmemVariableCache->oidCount) ;
-+ (ShmemVariableCache->nextOid) +=
(ShmemVariableCache->oidCount);
-+ XLogPutNextOid(ShmemVariableCache->nextOid +
VAR_OID_PREFETCH);
-+ ShmemVariableCache->oidCount = VAR_OID_PREFETCH;
-+ }
-+
-+ (ShmemVariableCache->nextOid) += offset;
-+ (ShmemVariableCache->oidCount) -= offset;
-+
-+ LWLockRelease(OidGenLock);
-+
-+ memset(msg,0,sizeof(msg));
-+ snprintf(msg, sizeof(msg), "%u", ShmemVariableCache->nextOid);
-+ if (PGR_Check_Lock.dest == TO_FRONTEND)
-+ {
-+ /*
-+ PGR_Send_Message_To_Frontend(msg);
-+ */
-+ pq_puttextmessage('C',msg);
-+ pq_flush();
-+ }
-+ else
-+ {
-+ send_response_to_replication_server(msg);
-+ }
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_lo_import(char * filename)
-+{
-+ char * result = NULL;
-+ LOArgs *lo_args;
-+ int len = 0;
-+ int buf_size = 0;
-+
-+ if ((PGR_Is_Replicated_Query == true) ||
-+ (PGR_Retry_Query.cmdSts == CMD_STS_TRANSACTION))
-+ {
-+ return STATUS_OK;
-+ }
-+ if ((PGR_Retry_Query.cmdSts != CMD_STS_QUERY) ||
-+ (PGR_Retry_Query.cmdType != CMD_TYPE_SELECT))
-+ {
-+ return STATUS_OK;
-+ }
-+
-+ len = strlen(filename);
-+ buf_size = sizeof(LOArgs) + len;
-+ lo_args = (LOArgs *)malloc(buf_size + 4);
-+ if (lo_args == (LOArgs *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(lo_args, 0, buf_size + 4);
-+ lo_args->arg1 = htonl((uint32_t)len);
-+ memcpy(lo_args->buf, filename, len);
-+
-+ result = PGR_Send_Replicate_Command((char *)lo_args,
-+ buf_size,
-+ CMD_STS_LARGE_OBJECT,
-+ CMD_TYPE_LO_IMPORT);
-+
-+ free(lo_args);
-+ if (result != NULL)
-+ {
-+ free(result);
-+ return STATUS_OK;
-+ }
-+
-+ return STATUS_ERROR;
-+}
-+
-+int
-+PGR_lo_create(int flags)
-+{
-+ char * result = NULL;
-+ LOArgs lo_args;
-+
-+ if ((PGR_Is_Replicated_Query == true) ||
-+ (PGR_Retry_Query.cmdSts == CMD_STS_TRANSACTION))
-+ {
-+ return STATUS_OK;
-+ }
-+ if ((PGR_Retry_Query.cmdSts != CMD_STS_QUERY) ||
-+ (PGR_Retry_Query.cmdType != CMD_TYPE_SELECT))
-+ {
-+ return STATUS_OK;
-+ }
-+ memset(&lo_args, 0, sizeof(LOArgs));
-+ lo_args.arg1 = htonl(flags);
-+
-+ result = PGR_Send_Replicate_Command((char *)&lo_args,
-+ sizeof(LOArgs),
-+ CMD_STS_LARGE_OBJECT,
-+ CMD_TYPE_LO_CREATE);
-+
-+ if (result != NULL)
-+ {
-+ free(result);
-+ return STATUS_OK;
-+ }
-+
-+ return STATUS_ERROR;
-+}
-+
-+int
-+PGR_lo_open(Oid lobjId,int32 mode)
-+{
-+ char * result = NULL;
-+ LOArgs lo_args;
-+
-+ if ((PGR_Is_Replicated_Query == true) ||
-+ (PGR_Retry_Query.cmdSts == CMD_STS_TRANSACTION))
-+ {
-+ return STATUS_OK;
-+ }
-+ if ((PGR_Retry_Query.cmdSts != CMD_STS_QUERY) ||
-+ (PGR_Retry_Query.cmdType != CMD_TYPE_SELECT))
-+ {
-+ return STATUS_OK;
-+ }
-+ memset(&lo_args, 0, sizeof(LOArgs));
-+ lo_args.arg1 = htonl((uint32_t)lobjId);
-+ lo_args.arg2 = htonl((uint32_t)mode);
-+
-+ result = PGR_Send_Replicate_Command((char *)&lo_args,
-+ sizeof(LOArgs),
-+ CMD_STS_LARGE_OBJECT,
-+ CMD_TYPE_LO_OPEN);
-+
-+ if (result != NULL)
-+ {
-+ free(result);
-+ return STATUS_OK;
-+ }
-+
-+ return STATUS_ERROR;
-+}
-+
-+int
-+PGR_lo_close(int32 fd)
-+{
-+ char * result = NULL;
-+ LOArgs lo_args;
-+
-+ if ((PGR_Is_Replicated_Query == true) ||
-+ (PGR_Retry_Query.cmdSts == CMD_STS_TRANSACTION))
-+ {
-+ return STATUS_OK;
-+ }
-+ if ((PGR_Retry_Query.cmdSts != CMD_STS_QUERY) ||
-+ (PGR_Retry_Query.cmdType != CMD_TYPE_SELECT))
-+ {
-+ return STATUS_OK;
-+ }
-+ memset(&lo_args, 0, sizeof(LOArgs));
-+ lo_args.arg1 = htonl((uint32_t)fd);
-+
-+ result = PGR_Send_Replicate_Command((char *)&lo_args,
-+ sizeof(LOArgs),
-+ CMD_STS_LARGE_OBJECT,
-+ CMD_TYPE_LO_CLOSE);
-+
-+ if (result != NULL)
-+ {
-+ free(result);
-+ return STATUS_OK;
-+ }
-+
-+ return STATUS_ERROR;
-+}
-+
-+int
-+PGR_lo_write(int fd, char *buf, int len)
-+{
-+ char * result = NULL;
-+ LOArgs *lo_args = NULL;
-+ int buf_size = 0;
-+
-+ if ((PGR_Is_Replicated_Query == true) ||
-+ (PGR_Retry_Query.cmdSts == CMD_STS_TRANSACTION))
-+ {
-+ return STATUS_OK;
-+ }
-+ if ((PGR_Retry_Query.cmdSts != CMD_STS_QUERY) ||
-+ (PGR_Retry_Query.cmdType != CMD_TYPE_SELECT))
-+ {
-+ return STATUS_OK;
-+ }
-+ buf_size = sizeof(LOArgs) + len;
-+ lo_args = malloc(buf_size + 4);
-+ if (lo_args == (LOArgs *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(lo_args, 0, buf_size + 4);
-+ lo_args->arg1 = htonl((uint32_t)fd);
-+ lo_args->arg2 = htonl((uint32_t)len);
-+ memcpy(lo_args->buf, buf, len);
-+ result = PGR_Send_Replicate_Command((char *)lo_args,
-+ buf_size,
-+ CMD_STS_LARGE_OBJECT,
-+ CMD_TYPE_LO_WRITE);
-+
-+ free(lo_args);
-+ if (result != NULL)
-+ {
-+ free(result);
-+ return STATUS_OK;
-+ }
-+
-+ return STATUS_ERROR;
-+}
-+
-+int
-+PGR_lo_lseek(int32 fd, int32 offset, int32 whence)
-+{
-+ char * result = NULL;
-+ LOArgs lo_args;
-+
-+ if ((PGR_Is_Replicated_Query == true) ||
-+ (PGR_Retry_Query.cmdSts == CMD_STS_TRANSACTION))
-+ {
-+ return STATUS_OK;
-+ }
-+ if ((PGR_Retry_Query.cmdSts != CMD_STS_QUERY) ||
-+ (PGR_Retry_Query.cmdType != CMD_TYPE_SELECT))
-+ {
-+ return STATUS_OK;
-+ }
-+ memset(&lo_args, 0, sizeof(LOArgs));
-+ lo_args.arg1 = htonl((uint32_t)fd);
-+ lo_args.arg2 = htonl((uint32_t)offset);
-+ lo_args.arg3 = htonl((uint32_t)whence);
-+
-+ result = PGR_Send_Replicate_Command((char *)&lo_args,
-+ sizeof(LOArgs),
-+ CMD_STS_LARGE_OBJECT,
-+ CMD_TYPE_LO_LSEEK);
-+
-+ if (result != NULL)
-+ {
-+ free(result);
-+ return STATUS_OK;
-+ }
-+
-+ return STATUS_ERROR;
-+}
-+
-+int
-+PGR_lo_unlink(Oid lobjId)
-+{
-+ char * result = NULL;
-+ LOArgs lo_args;
-+
-+ if ((PGR_Is_Replicated_Query == true) ||
-+ (PGR_Retry_Query.cmdSts == CMD_STS_TRANSACTION))
-+ {
-+ return STATUS_OK;
-+ }
-+ if ((PGR_Retry_Query.cmdSts != CMD_STS_QUERY) ||
-+ (PGR_Retry_Query.cmdType != CMD_TYPE_SELECT))
-+ {
-+ return STATUS_OK;
-+ }
-+ memset(&lo_args, 0, sizeof(LOArgs));
-+ lo_args.arg1 = htonl((uint32_t)lobjId);
-+
-+ result = PGR_Send_Replicate_Command((char *)&lo_args,
-+ sizeof(LOArgs),
-+ CMD_STS_LARGE_OBJECT,
-+ CMD_TYPE_LO_UNLINK);
-+
-+ if (result != NULL)
-+ {
-+ free(result);
-+ return STATUS_OK;
-+ }
-+
-+ return STATUS_ERROR;
-+}
-+
-+Oid
-+PGRGetNewObjectId(Oid last_id)
-+{
-+ Oid newId = 0;
-+
-+ if (last_id == 0)
-+ {
-+ newId = (Oid)PGRget_replication_id();
-+ }
-+ else
-+ {
-+ newId = last_id + 1;
-+ }
-+ return newId;
-+}
-+
-+int
-+PGR_Send_Input_Message(char cmdType,StringInfo input_message)
-+{
-+ int len = 0;
-+ char * ptr = NULL;
-+ char * result = NULL;
-+
-+ if (input_message == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (PGR_Is_Replicated_Query == true)
-+ {
-+ return STATUS_OK;
-+ }
-+ len = input_message->len+1;
-+ ptr = input_message->data;
-+ result = PGR_Send_Replicate_Command(ptr,len, CMD_STS_PREPARE,cmdType);
-+ if (result != NULL)
-+ {
-+ PGR_Reload_Start_Time();
-+ free(result);
-+ result = NULL;
-+ return STATUS_OK;
-+ }
-+ else
-+ {
-+ return STATUS_ERROR;
-+ }
-+}
-+
-+#endif /* USE_REPLICATION */
-diff -aruN postgresql-8.1.2/src/backend/libpq/replicate_com.c
pgcluster-1.5.0rc7/src/backend/libpq/replicate_com.c
---- postgresql-8.1.2/src/backend/libpq/replicate_com.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/libpq/replicate_com.c 2006-01-10
17:39:39.000000000 +0100
-@@ -0,0 +1,671 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * replicate_com.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at backend for the replication.
-+ * Low level I/O functions that called by in these functions are
-+ * contained in 'replicate_com.c'.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+
-+/*--------------------------------------
-+ * INTERFACE ROUTINES
-+ *
-+ * setup/teardown:
-+ * PGR_Close_Sock
-+ * PGR_Free_Conf_Data
-+ * I/O call:
-+ * PGR_Create_Socket_Connect
-+ * PGR_Create_Socket_Bind
-+ * PGR_Create_Acception
-+ * table handling:
-+ * PGR_Get_Conf_Data
-+ *-------------------------------------
-+ */
-+#ifdef USE_REPLICATION
-+
-+#include "postgres.h"
-+
-+#include <signal.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <grp.h>
-+#include <unistd.h>
-+#include <ctype.h>
-+#include <time.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+#include <netdb.h>
-+
-+#include "libpq/libpq.h"
-+#include "miscadmin.h"
-+#include "nodes/print.h"
-+#include "utils/guc.h"
-+#include "parser/parser.h"
-+#include "access/xact.h"
-+#include "replicate_com.h"
-+
-+int PGR_Create_Socket_Connect(int * fdP, char * hostName , unsigned short
portNumber);
-+void PGR_Close_Sock(int * sock);
-+int PGR_Create_Socket_Bind(int * fdP, char * hostName , unsigned short
portNumber);
-+int PGR_Create_Acception(int fd, int * sockP, char * hostName , unsigned
short portNumber);
-+int PGR_Free_Conf_Data(void);
-+int PGR_Get_Conf_Data(char * dir , char * fname);
-+void PGRset_recovery_packet_no(RecoveryPacket * packet, int packet_no);
-+unsigned int PGRget_ip_by_name(char * host);
-+
-+static char * get_string(char * buf);
-+static bool is_start_tag(char * ptr);
-+static bool is_end_tag(char * ptr);
-+static void init_conf_data(ConfDataType *conf);
-+static int get_key(char * key, char * str);
-+static int get_conf_key_value(char * key, char * value , char * str);
-+static int add_conf_data(char *table,int rec_no, char *key,char * value);
-+static int get_table_data(FILE * fp,char * table, int rec_no);
-+static int get_single_data(char * str);
-+static int get_conf_file(char * fname);
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGR_Create_Socket_Connect()
-+ * NOTES
-+ * create new socket
-+ * ARGS
-+ * int * fdP:
-+ * char * hostName:
-+ * unsigned short portNumber:
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGR_Create_Socket_Connect(int * fdP, char * hostName , unsigned short
portNumber)
-+{
-+
-+ int sock;
-+ size_t len = 0;
-+ struct sockaddr_in addr;
-+ int one = 1;
-+
-+ if ((*hostName == '\0') || (portNumber < 1000))
-+ {
-+ * fdP = -1;
-+ return STATUS_ERROR;
-+ }
-+ if ((*fdP = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-+ {
-+ * fdP = -1;
-+ return STATUS_ERROR;
-+ }
-+ if ((setsockopt(*fdP, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one))) == -1)
-+ {
-+ PGR_Close_Sock(fdP);
-+ return STATUS_ERROR;
-+ }
-+ if (setsockopt(*fdP, IPPROTO_TCP, TCP_NODELAY, (char *) &one,
sizeof(one)) < 0)
-+ {
-+ PGR_Close_Sock(fdP);
-+ return STATUS_ERROR;
-+ }
-+
-+ addr.sin_family = AF_INET;
-+ if (hostName[0] == '\0')
-+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
-+ else
-+ {
-+ struct hostent *hp;
-+
-+ hp = gethostbyname(hostName);
-+ if ((hp == NULL) || (hp->h_addrtype != AF_INET))
-+ {
-+ PGR_Close_Sock(fdP);
-+ return STATUS_ERROR;
-+ }
-+ memmove((char *) &(addr.sin_addr), (char *) hp->h_addr,
hp->h_length);
-+ }
-+
-+ addr.sin_port = htons(portNumber);
-+ len = sizeof(struct sockaddr_in);
-+
-+ if ((sock = connect(*fdP,(struct sockaddr*)&addr,len)) < 0)
-+ {
-+ PGR_Close_Sock(fdP);
-+ return STATUS_ERROR;
-+ }
-+
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_Create_Socket_Bind(int * fdP, char * hostName , unsigned short
portNumber)
-+{
-+
-+ int err;
-+ size_t len = 0;
-+ struct sockaddr_in addr;
-+ int one = 1;
-+
-+ if ((*fdP = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if ((setsockopt(*fdP, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one))) == -1)
-+ {
-+ PGR_Close_Sock(fdP);
-+ return STATUS_ERROR;
-+ }
-+ addr.sin_family = AF_INET;
-+ if (hostName[0] == '\0')
-+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
-+ else
-+ {
-+ struct hostent *hp;
-+
-+ hp = gethostbyname(hostName);
-+ if ((hp == NULL) || (hp->h_addrtype != AF_INET))
-+ {
-+ PGR_Close_Sock(fdP);
-+ return STATUS_ERROR;
-+ }
-+ memmove((char *) &(addr.sin_addr), (char *) hp->h_addr,
hp->h_length);
-+ }
-+
-+ addr.sin_port = htons(portNumber);
-+ len = sizeof(struct sockaddr_in);
-+
-+ err = bind(*fdP, (struct sockaddr *) & addr, len);
-+ if (err < 0)
-+ {
-+ PGR_Close_Sock(fdP);
-+ return STATUS_ERROR;
-+ }
-+ err = listen(*fdP, MAX_SOCKET_QUEUE );
-+ if (err < 0)
-+ {
-+ PGR_Close_Sock(fdP);
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_Create_Acception(int fd, int * sockP, char * hostName , unsigned short
portNumber)
-+{
-+ int sock;
-+ struct sockaddr addr;
-+ size_t len = 0;
-+ int one = 1;
-+
-+ len = sizeof(struct sockaddr);
-+ if ((sock = accept(fd, &addr, &len)) < 0)
-+ {
-+ *sockP = -1;
-+ return STATUS_ERROR;
-+ }
-+
-+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &one,
sizeof(one)) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
sizeof(one)) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ *sockP = sock;
-+
-+ return STATUS_OK;
-+}
-+
-+void
-+PGR_Close_Sock(int * sock)
-+{
-+ close( (int)*sock);
-+ *sock = -1;
-+}
-+
-+static char *
-+get_string(char * buf)
-+{
-+ int i,len1,len2,start_flag;
-+ char *readp, *writep;
-+
-+ writep = readp = buf;
-+ i = len1 = 0;
-+ while (*(readp +i) != '\0')
-+ {
-+ if (!isspace(*(readp+ i)))
-+ {
-+ len1 ++;
-+ }
-+ i++;
-+ }
-+ start_flag = len2 = 0;
-+ while (*readp != '\0')
-+ {
-+ if (*readp == '#')
-+ {
-+ *writep = '\0';
-+ break;
-+ }
-+ if (isspace(*readp))
-+ {
-+ if ((len2 >= len1) || (!start_flag))
-+ {
-+ readp++;
-+ continue;
-+ }
-+ *writep = *readp;
-+ }
-+ else
-+ {
-+ start_flag = 1;
-+ *writep = *readp;
-+ len2 ++;
-+ }
-+ readp ++;
-+ writep ++;
-+ }
-+ *writep = '\0';
-+ return buf;
-+}
-+
-+static bool
-+is_start_tag(char * ptr)
-+{
-+ if ((*ptr == '<') && (*(ptr+1) != '/'))
-+ {
-+ return true;
-+ }
-+ return false;
-+}
-+
-+static bool
-+is_end_tag(char * ptr)
-+{
-+ if ((*ptr == '<') && (*(ptr+1) == '/'))
-+ {
-+ return true;
-+ }
-+ return false;
-+}
-+
-+static void
-+init_conf_data(ConfDataType *conf)
-+{
-+ memset(conf->table,0,sizeof(conf->table));
-+ memset(conf->key,0,sizeof(conf->key));
-+ memset(conf->value,0,sizeof(conf->value));
-+ conf->rec_no = 0;
-+ conf->last = NULL;
-+ conf->next = NULL;
-+}
-+
-+static int
-+get_key(char * key, char * str)
-+{
-+ int offset = 1;
-+ char * ptr_s,*ptr_e;
-+
-+ ptr_s = strchr(str,'<');
-+ if (ptr_s == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (*(ptr_s+1) == '/')
-+ {
-+ offset = 2;
-+ }
-+ ptr_e = strchr(str,'>');
-+ if (ptr_e == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ *ptr_e = '\0';
-+ strcpy(key,ptr_s + offset);
-+ *ptr_e = '>';
-+ return STATUS_OK;
-+}
-+
-+static int
-+get_conf_key_value(char * key, char * value , char * str)
-+{
-+ int i;
-+ int len1,len2,start_flag;
-+ char * ptr_s,*ptr_e;
-+
-+ if(get_key(key,str) == STATUS_ERROR)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ ptr_e = strchr(str,'>');
-+ if (ptr_e == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ ptr_s = ptr_e + 1;
-+
-+ len1 = 0;
-+ while ((*ptr_s != '<') && (*ptr_s != '\0'))
-+ {
-+ if (! isspace(*ptr_s))
-+ {
-+ len1 ++;
-+ }
-+ ptr_s ++;
-+ }
-+ ptr_s = ptr_e + 1;
-+ i = len2 = start_flag = 0;
-+ while ((*ptr_s != '<') && (*ptr_s != '\0'))
-+ {
-+ if (isspace(*ptr_s))
-+ {
-+ if ((len2 >= len1) || (!start_flag))
-+ {
-+ ptr_s ++;
-+ continue;
-+ }
-+ *(value + i) = *ptr_s;
-+ }
-+ else
-+ {
-+ start_flag = 1;
-+ *(value + i) = *ptr_s;
-+ len2 ++;
-+ }
-+ i++;
-+ ptr_s ++;
-+ }
-+ *(value + i) = '\0';
-+ return STATUS_OK;
-+}
-+
-+static int
-+add_conf_data(char *table,int rec_no, char *key,char * value)
-+{
-+ ConfDataType * conf_data;
-+
-+ conf_data = (ConfDataType *)malloc(sizeof(ConfDataType));
-+ if (conf_data == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ init_conf_data(conf_data);
-+ if (table != NULL)
-+ {
-+ memcpy(conf_data->table,table,sizeof(conf_data->table));
-+ }
-+ else
-+ {
-+ memset(conf_data->table,0,sizeof(conf_data->table));
-+ }
-+ memcpy(conf_data->key,key,sizeof(conf_data->key));
-+ memcpy(conf_data->value,value,sizeof(conf_data->value));
-+ conf_data->rec_no = rec_no;
-+ if (ConfData_Top == (ConfDataType *)NULL)
-+ {
-+ ConfData_Top = conf_data;
-+ conf_data->last = (char *)NULL;
-+ }
-+ if (ConfData_End == (ConfDataType *)NULL)
-+ {
-+ conf_data->last = (char *)NULL;
-+ }
-+ else
-+ {
-+ conf_data->last = (char *)ConfData_End;
-+ ConfData_End->next = (char *)conf_data;
-+ }
-+ ConfData_End = conf_data;
-+ conf_data->next = (char *)NULL;
-+ return STATUS_OK;
-+}
-+
-+static int
-+get_table_data(FILE * fp,char * table, int rec_no)
-+{
-+ char buf[1024];
-+ char key_buf[1024];
-+ char value_buf[1024];
-+ int len = 0;
-+ char * ptr;
-+
-+ while (fgets(buf,sizeof(buf),fp) != NULL)
-+ {
-+ /*
-+ * pic up a data string
-+ */
-+ ptr = get_string(buf);
-+ len = strlen(ptr);
-+ if (len == 0)
-+ {
-+ continue;
-+ }
-+ if (is_end_tag(ptr))
-+ {
-+ if(get_key(key_buf,ptr) == STATUS_ERROR)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (!strcmp(key_buf,table))
-+ {
-+ return STATUS_OK;
-+ }
-+ }
-+ if (is_start_tag(ptr))
-+ {
-+ if(get_conf_key_value(key_buf,value_buf,ptr) ==
STATUS_ERROR)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ add_conf_data(table,rec_no,key_buf,value_buf);
-+ }
-+ }
-+ return STATUS_ERROR;
-+}
-+
-+static int
-+get_single_data(char * str)
-+{
-+ char key_buf[1024];
-+ char value_buf[1024];
-+ if(get_conf_key_value(key_buf,value_buf,str) == STATUS_ERROR)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ add_conf_data(NULL,0,key_buf,value_buf);
-+ return STATUS_OK;
-+}
-+
-+
-+static int
-+get_conf_file(char * fname)
-+{
-+ FILE * fp = NULL;
-+ int len;
-+ char buf[1024];
-+ char key_buf[1024];
-+ char last_key_buf[1024];
-+ char *ptr;
-+ int rec_no = 0;
-+
-+ /*
-+ * configuration file open
-+ */
-+ if ((fp = fopen(fname,"r")) == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ /*
-+ * configuration file read
-+ */
-+ memset(last_key_buf,0,sizeof(last_key_buf));
-+ memset(key_buf,0,sizeof(key_buf));
-+ while (fgets(buf,sizeof(buf),fp) != NULL)
-+ {
-+ /*
-+ * pic up a data string
-+ */
-+ ptr = get_string(buf);
-+ len = strlen(ptr);
-+ if (len == 0)
-+ {
-+ continue;
-+ }
-+ if (is_start_tag(ptr))
-+ {
-+ if(get_key(key_buf,ptr) == STATUS_ERROR)
-+ {
-+ fclose(fp);
-+ return STATUS_ERROR;
-+ }
-+ if (strstr(ptr,"</") == NULL)
-+ {
-+ if (strcmp(last_key_buf,key_buf))
-+ {
-+ rec_no = 0;
-+ strcpy(last_key_buf,key_buf);
-+ }
-+ get_table_data(fp,key_buf,rec_no);
-+ rec_no ++;
-+ }
-+ else
-+ {
-+ get_single_data(ptr);
-+ }
-+ }
-+ }
-+ fclose(fp);
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_Free_Conf_Data(void)
-+{
-+ ConfDataType * conf, *nextp;
-+
-+ if (ConfData_Top == (ConfDataType *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ conf = ConfData_Top;
-+
-+ while (conf != (ConfDataType *)NULL)
-+ {
-+ nextp = (ConfDataType*)conf->next;
-+ free (conf);
-+ conf = nextp;
-+ }
-+ ConfData_Top = ConfData_End = (ConfDataType *)NULL;
-+ return STATUS_OK;
-+}
-+
-+int
-+PGR_Get_Conf_Data(char * dir , char * fname)
-+{
-+
-+ int status;
-+
-+ char * conf_file;
-+ if ((dir == NULL) || ( fname == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ conf_file = malloc(strlen(dir) + strlen(fname) + 2);
-+ if (conf_file == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ sprintf(conf_file,"%s/%s",dir,fname);
-+
-+ ConfData_Top = ConfData_End = (ConfDataType * )NULL;
-+ status = get_conf_file(conf_file);
-+ free (conf_file);
-+ conf_file = NULL;
-+
-+ return status;
-+}
-+
-+void
-+PGRset_recovery_packet_no(RecoveryPacket * packet, int packet_no)
-+{
-+ if (packet == NULL)
-+ {
-+ return;
-+ }
-+ packet->packet_no = htons(packet_no) ;
-+
-+}
-+
-+unsigned int
-+PGRget_ip_by_name(char * host)
-+{
-+ struct hostent *hp = NULL;
-+ unsigned int ip = 0;
-+ unsigned char uc = 0;
-+ int i;
-+
-+ if ((host == NULL) || (*host == '\0'))
-+ {
-+ return 0;
-+ }
-+ hp = gethostbyname( host );
-+ if (hp == NULL)
-+ {
-+ return 0;
-+ }
-+ for (i = 3 ; i>= 0 ; i --)
-+ {
-+ uc = (unsigned char)hp->h_addr_list[0][i];
-+ ip = ip | uc;
-+ if (i > 0)
-+ ip = ip << 8;
-+ }
-+ return ip;
-+}
-+
-+#if 0
-+void
-+PGR_Init_Com_Info(PGR_Com_Info * p)
-+{
-+ if (p != (PGR_Com_Info *)NULL)
-+ {
-+ /* init PGR_ConfData_Info data */
-+ ConfData_Info = &(p->ConfData_Info);
-+ ConfData_Info->ConfData_Top = (ConfDataType*)NULL;
-+ ConfData_Info->ConfData_End = (ConfDataType*)NULL;
-+ ConfData_Info->LifeCheck_Port_Number = 0;
-+ ConfData_Info->Recovery_Port_Number = 0;
-+
-+ /* init PGR_Log_Info data */
-+ Log_Info = &(p->Log_Info);
-+ Log_Info->StatusFp = (FILE *)NULL;
-+ Log_Info->LogFp = (FILE *)NULL;
-+ Log_Info->PGRStatusFileName = NULL;
-+ Log_Info->PGRLogFileName = NULL;
-+ Log_Info->Log_Print = 0;
-+ Log_Info->Debug_Print = 0;
-+ }
-+ else
-+ {
-+ ConfData_Info = (PGR_ConfData_Info *)NULL;
-+ Log_Info = (PGR_Log_Info *)NULL;
-+ }
-+}
-+#endif
-+
-+#endif /* USE_REPLICATION */
-diff -aruN postgresql-8.1.2/src/backend/parser/parse_clause.c
pgcluster-1.5.0rc7/src/backend/parser/parse_clause.c
---- postgresql-8.1.2/src/backend/parser/parse_clause.c 2005-11-22
19:23:13.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/parser/parse_clause.c 2006-01-23
07:10:23.000000000 +0100
-@@ -34,6 +34,10 @@
- #include "utils/builtins.h"
- #include "utils/guc.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+extern bool auto_lock_table;
-+#endif /* USE_REPLICATION */
-
- #define ORDER_CLAUSE 0
- #define GROUP_CLAUSE 1
-@@ -154,7 +158,18 @@
- * analyze.c will eventually do the corresponding heap_close(), but
*not*
- * release the lock.
- */
-+#ifdef USE_REPLICATION
-+ if ((auto_lock_table == true) && (Transaction_Mode < 1))
-+ {
-+ pstate->p_target_relation = heap_openrv(relation,
ShareRowExclusiveLock);
-+ }
-+ else
-+ {
-+ pstate->p_target_relation = heap_openrv(relation,
RowExclusiveLock);
-+ }
-+#else
- pstate->p_target_relation = heap_openrv(relation, RowExclusiveLock);
-+#endif /* USE_REPLICATION */
-
- /*
- * Now build an RTE.
-diff -aruN postgresql-8.1.2/src/backend/parser/parse_relation.c
pgcluster-1.5.0rc7/src/backend/parser/parse_relation.c
---- postgresql-8.1.2/src/backend/parser/parse_relation.c 2005-11-22
19:23:14.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/parser/parse_relation.c 2006-01-23
07:12:19.000000000 +0100
-@@ -30,6 +30,10 @@
- #include "utils/lsyscache.h"
- #include "utils/syscache.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+extern bool auto_lock_table;
-+#endif /* USE_REPLICATION */
-
- /* GUC parameter */
- bool add_missing_from;
-@@ -587,7 +591,14 @@
- * to a rel in a statement, be careful to get the right access level
- * depending on whether we're doing SELECT FOR UPDATE/SHARE.
- */
-+#ifdef USE_REPLICATION
-+ if ((auto_lock_table == true) && (Transaction_Mode < 2))
-+ lockmode = isLockedRel(pstate, refname) ?
ShareRowExclusiveLock : AccessShareLock;
-+ else
-+ lockmode = isLockedRel(pstate, refname) ? RowShareLock :
AccessShareLock;
-+#else
- lockmode = isLockedRel(pstate, refname) ? RowShareLock :
AccessShareLock;
-+#endif /* USE_REPLICATION */
- rel = heap_openrv(relation, lockmode);
- rte->relid = RelationGetRelid(rel);
-
-diff -aruN postgresql-8.1.2/src/backend/postmaster/postmaster.c
pgcluster-1.5.0rc7/src/backend/postmaster/postmaster.c
---- postgresql-8.1.2/src/backend/postmaster/postmaster.c 2006-01-06
03:58:32.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/postmaster/postmaster.c 2006-01-31
13:12:17.000000000 +0100
-@@ -128,6 +128,9 @@
- #include "storage/spin.h"
- #endif
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*
- * List of active backends (or child processes anyway; we don't actually
-@@ -370,6 +373,49 @@
- #define StartupDataBase() StartChildProcess(BS_XLOG_STARTUP)
- #define StartBackgroundWriter() StartChildProcess(BS_XLOG_BGWRITER)
-
-+#ifdef USE_REPLICATION
-+char * Query_String = NULL;
-+ReplicateServerInfo * ReplicateServerData = NULL;
-+ReplicateServerInfo * CurrentReplicateServer = NULL;
-+ReplicateServerInfo * LastReplicateServer = NULL;
-+int ReplicateServerShmid = -1;
-+int TransactionQuery = 0;
-+int TransactionSock = -1;
-+int Transaction_Mode = 0;
-+int PGR_Noticed_Abort = 0;
-+bool Session_Authorization_Mode = false;
-+bool Create_Temp_Table_Mode = false;
-+ConfDataType * ConfData_Top = (ConfDataType *)NULL;
-+ConfDataType * ConfData_End = (ConfDataType *)NULL;
-+int RecoveryPortNumber = 0;
-+int Master_Pid = 0;
-+char * RsyncPath = NULL;
-+char * RsyncOption = NULL;
-+bool RsyncCompress = true;
-+ReplicateNow * ReplicateCurrentTime = NULL;
-+CopyData * PGRCopyData = NULL;
-+bool PGR_Copy_Data_Need_Replicate = false;
-+PGR_Stand_Alone_Type * PGR_Stand_Alone = NULL;
-+PGR_Not_Replicate_Type * PGR_Not_Replicate = NULL;
-+int PGR_Not_Replicate_Rec_Num = 0;
-+bool PGR_Is_Replicated_Query = false;
-+PGR_Check_Lock_Type PGR_Check_Lock;
-+int PGR_Sock_To_Replication_Server = -1;
-+bool PGR_Need_Notice = false;
-+bool PGR_Lock_Noticed = false;
-+bool PGR_Recovery_Option = false;
-+char * PGRSelfHostName = NULL;
-+int PGR_Pending_Sem_Num = 0;
-+bool PGR_Reliable_Mode_Wait = true;
-+PGR_Retry_Query_Type PGR_Retry_Query;
-+int ClusterDBShmid = -1;
-+ClusterDBInfo * ClusterDBData = NULL;
-+bool PGRforceLoadBalance=false;
-+
-+bool needToUpdateReplicateIdOnNextQueryIsDone=false;
-+bool PGR_Is_Sync_OID = false;
-+
-+#endif /* USE_REPLICATION */
-
- /*
- * Postmaster main entry point
-@@ -382,6 +428,11 @@
- char *userDoption = NULL;
- int i;
-
-+#ifdef USE_REPLICATION
-+ PGR_Check_Lock.check_lock_conflict = false;
-+ PGR_Check_Lock.status_lock_conflict = STATUS_OK;
-+#endif /* USE REPLICATION */
-+
- /* This will call exit() if strdup() fails. */
- progname = get_progname(argv[0]);
-
-@@ -450,10 +501,15 @@
-
- opterr = 1;
-
-- while ((opt = getopt(argc, argv,
"A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:Ss-:")) != -1)
-+ while ((opt = getopt(argc, argv,
"A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:Ss-:R")) != -1)
- {
- switch (opt)
- {
-+ case 'R':
-+#ifdef USE_REPLICATION
-+ PGR_Recovery_Option = true;
-+ break;
-+#endif /* USE_REPLICATION */
- case 'A':
- #ifdef USE_ASSERT_CHECKING
- SetConfigOption("debug_assertions", optarg,
PGC_POSTMASTER, PGC_S_ARGV);
-@@ -685,6 +741,23 @@
- */
- CreateDataDirLockFile(true);
-
-+#ifdef USE_REPLICATION
-+ if (PGR_Get_Conf_Data( DataDir, CLUSTER_CONF_FILE ) == STATUS_OK)
-+ {
-+ PGR_Init_Replicate_Server_Data();
-+ PGR_Set_Replicate_Server_Socket();
-+ PGR_Free_Conf_Data();
-+ if (PGR_Recovery_Option)
-+ {
-+ fprintf(stderr,"Start in recovery mode! \n");
-+ fprintf(stderr,"Please wait until a data
synchronization finishes from Master DB... \n");
-+ if (PGR_Recovery_Main() != STATUS_OK)
-+ {
-+ ExitPostmaster(1);
-+ }
-+ }
-+ }
-+#endif /* USE_REPLICATION */
- /*
- * If timezone is not set, determine what the OS uses. (In theory
this
- * should be done during GUC initialization, but because it can take
as
-@@ -944,6 +1017,21 @@
- */
- autovac_init();
-
-+#ifdef USE_REPLICATION
-+ Master_Pid = PGR_Master_Main();
-+ if (Master_Pid < 0)
-+ {
-+ elog(DEBUG1,"PGR_Master_Main failed");
-+ ExitPostmaster(1);
-+ }
-+ if (PGR_Recovery_Option)
-+ {
-+ PGR_recovery_finish_send();
-+ PGR_Recovery_Option = false;
-+ fprintf(stderr,"OK! The data synchronization with Master DB
was finished. \n");
-+ }
-+#endif /* USE_REPLICATION */
-+
- status = ServerLoop();
-
- /*
-@@ -1607,7 +1695,10 @@
- case CAC_TOOMANY:
- ereport(FATAL,
-
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
-- errmsg("sorry, too many clients
already")));
-+ errmsg("sorry, too many clients already")));
-+#ifdef USE_REPLICATION
-+ return STATUS_ERROR;
-+#endif
- break;
- case CAC_OK:
- default:
-@@ -1875,6 +1966,19 @@
- (errmsg_internal("postmaster received signal %d",
-
postgres_signal_arg)));
-
-+#ifdef USE_REPLICATION
-+ if (PGR_Recovery_Option)
-+ {
-+ PGR_recovery_error_send();
-+ PGR_Recovery_Option = false;
-+ }
-+ if (Master_Pid > 0)
-+ {
-+ kill (Master_Pid,postgres_signal_arg);
-+ }
-+ PGR_delete_shm();
-+#endif /* USE_REPLICATION */
-+
- switch (postgres_signal_arg)
- {
- case SIGTERM:
-@@ -3348,6 +3452,16 @@
- * MUST -- vadim 05-10-1999
- */
-
-+#ifdef USE_REPLICATION
-+ if (PGR_Recovery_Option)
-+ {
-+ write_stderr("sorry, recovery failed.");
-+ PGR_recovery_error_send();
-+ PGR_Recovery_Option = false;
-+ }
-+ PGR_delete_shm();
-+#endif /* USE_REPLICATION */
-+
- proc_exit(status);
- }
-
-diff -aruN postgresql-8.1.2/src/backend/storage/large_object/inv_api.c
pgcluster-1.5.0rc7/src/backend/storage/large_object/inv_api.c
---- postgresql-8.1.2/src/backend/storage/large_object/inv_api.c
2005-10-15 04:49:26.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/storage/large_object/inv_api.c
2006-01-10 17:39:39.000000000 +0100
-@@ -28,6 +28,10 @@
- #include "utils/lsyscache.h"
- #include "utils/resowner.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-+
-
- /*
- * All accesses to pg_largeobject and its index make use of a single
Relation
-@@ -39,7 +43,6 @@
- static Relation lo_heap_r = NULL;
- static Relation lo_index_r = NULL;
-
--
- /*
- * Open pg_largeobject and its index, if not already done in current xact
- */
-@@ -180,6 +183,9 @@
- * use. We can use the index on pg_largeobject for checking OID
- * uniqueness, even though it has additional columns besides OID.
- */
-+#ifdef USE_REPLICATION
-+ PGR_Is_Sync_OID = true;
-+#endif /* USE_REPLICATION */
- if (!OidIsValid(lobjId))
- {
- open_lo_relation();
-@@ -198,6 +204,9 @@
- */
- CommandCounterIncrement();
-
-+#ifdef USE_REPLICATION
-+ PGR_Is_Sync_OID = false;
-+#endif /* USE_REPLICATION */
- return lobjId;
- }
-
-diff -aruN postgresql-8.1.2/src/backend/storage/lmgr/deadlock.c
pgcluster-1.5.0rc7/src/backend/storage/lmgr/deadlock.c
---- postgresql-8.1.2/src/backend/storage/lmgr/deadlock.c 2005-10-29
02:31:51.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/storage/lmgr/deadlock.c 2006-01-10
17:39:39.000000000 +0100
-@@ -31,6 +31,9 @@
- #include "storage/proc.h"
- #include "utils/memutils.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /* One edge in the waits-for graph */
- typedef struct
-@@ -226,6 +229,13 @@
- if (!FindLockCycle(proc, possibleConstraints, &nSoftEdges))
- elog(FATAL, "deadlock seems to have disappeared");
-
-+#ifdef USE_REPLICATION
-+ if (PGR_Notice_Conflict() == STATUS_ERROR)
-+ {
-+ return FALSE;
-+ }
-+ PGR_Lock_Noticed =true;
-+#endif
- return true; /* cannot find a
non-deadlocked state */
- }
-
-diff -aruN postgresql-8.1.2/src/backend/storage/lmgr/lmgr.c
pgcluster-1.5.0rc7/src/backend/storage/lmgr/lmgr.c
---- postgresql-8.1.2/src/backend/storage/lmgr/lmgr.c 2005-10-15
04:49:26.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/storage/lmgr/lmgr.c 2006-01-10
17:39:39.000000000 +0100
-@@ -24,6 +24,9 @@
- #include "storage/procarray.h"
- #include "utils/inval.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*
- * This conflict table defines the semantics of the various lock modes.
-@@ -466,10 +469,18 @@
-
- SET_LOCKTAG_TRANSACTION(tag, xid);
-
-+#ifdef USE_REPLICATION
-+ if (!LockAcquire(LockTableId, &tag, false,
-+ ExclusiveLock, false,false))
-+ elog(ERROR, "XactLockTableWait: LockAcquire failed");
-+
-+ LockRelease(LockTableId, &tag, ExclusiveLock,false);
-+#else
- (void) LockAcquire(LockTableId, &tag, false,
- ShareLock, false, false);
-
- LockRelease(LockTableId, &tag, ShareLock, false);
-+#endif /* USE_REPLICATION */
-
- if (!TransactionIdIsInProgress(xid))
- break;
-@@ -605,3 +616,38 @@
-
- LockRelease(LockTableId, &tag, lockmode, false);
- }
-+
-+#ifdef USE_REPLICATION
-+/*
-+ * XactLockTableWait
-+ *
-+ * Wait for the specified transaction to commit or abort.
-+ */
-+void
-+XactLockTableWaitForCluster(TransactionId xid,Buffer buffer)
-+{
-+ LOCKTAG tag;
-+ TransactionId myxid = GetCurrentTransactionId();
-+
-+ Assert(!TransactionIdEquals( xid, myxid ));
-+
-+ LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-+
-+ SET_LOCKTAG_TRANSACTION(tag, xid);
-+
-+ if (!LockAcquire(LockTableId, &tag, false,
-+ ExclusiveLock, false,false))
-+ elog(ERROR, "XactLockTableWait: LockAcquire failed");
-+
-+ LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
-+
-+ LockRelease(LockTableId, &tag, ExclusiveLock,false);
-+
-+ /*
-+ * Transaction was committed/aborted/crashed - we have to update
-+ * pg_clog if transaction is still marked as running.
-+ */
-+ if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
-+ TransactionIdAbort(xid);
-+}
-+#endif /*USE_REPLICATION*/
-diff -aruN postgresql-8.1.2/src/backend/storage/lmgr/lock.c
pgcluster-1.5.0rc7/src/backend/storage/lmgr/lock.c
---- postgresql-8.1.2/src/backend/storage/lmgr/lock.c 2005-11-22
19:23:18.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/storage/lmgr/lock.c 2006-01-10
17:39:39.000000000 +0100
-@@ -42,6 +42,10 @@
- #include "utils/ps_status.h"
- #include "utils/resowner.h"
-
-+#ifdef USE_REPLICATION
-+#include "storage/lmgr.h"
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /* This configuration variable is used to set the lock table size */
- int max_locks_per_xact; /* set by guc.c */
-@@ -697,6 +701,10 @@
- status = LockCheckConflicts(lockMethodTable, lockmode,
- lock,
proclock, MyProc);
-
-+#ifdef USE_REPLICATION
-+ PGR_Check_Lock.status_lock_conflict = status;
-+ PGR_Check_Lock.deadlock = false;
-+#endif /* USE_REPLICATION */
- if (status == STATUS_OK)
- {
- /* No conflict with held or previously requested locks */
-@@ -706,6 +714,17 @@
- else
- {
- Assert(status == STATUS_FOUND);
-+#ifdef USE_REPLICATION
-+ if ((PGR_Need_Notice == true) &&
-+ (PGR_Check_Lock.check_lock_conflict == true))
-+ {
-+ if (!PGR_Lock_Noticed && PGR_Notice_Conflict() ==
STATUS_ERROR)
-+ {
-+ return FALSE;
-+ }
-+ PGR_Lock_Noticed = true;
-+ }
-+#endif /* USE_REPLICATION */
-
- /*
- * We can't acquire the lock immediately. If caller
specified no
-diff -aruN postgresql-8.1.2/src/backend/storage/lmgr/proc.c
pgcluster-1.5.0rc7/src/backend/storage/lmgr/proc.c
---- postgresql-8.1.2/src/backend/storage/lmgr/proc.c 2005-11-22
19:23:19.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/storage/lmgr/proc.c 2006-01-10
17:39:39.000000000 +0100
-@@ -44,6 +44,9 @@
- #include "storage/procarray.h"
- #include "storage/spin.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /* GUC variables */
- int DeadlockTimeout = 1000;
-@@ -264,6 +267,9 @@
- MyProc->lwWaitLink = NULL;
- MyProc->waitLock = NULL;
- MyProc->waitProcLock = NULL;
-+#ifdef USE_REPLICATION
-+ MyProc->replicationId = 0;
-+#endif
- SHMQueueInit(&(MyProc->procLocks));
-
- /*
-@@ -360,6 +366,9 @@
- MyProc->lwWaitLink = NULL;
- MyProc->waitLock = NULL;
- MyProc->waitProcLock = NULL;
-+#ifdef USE_REPLICATION
-+ MyProc->replicationId=0;
-+#endif
- SHMQueueInit(&(MyProc->procLocks));
-
- /*
-@@ -691,6 +700,17 @@
- GrantAwaitedLock();
- return STATUS_OK;
- }
-+#ifdef USE_REPLICATION
-+ if(proc->replicationId == 0 ||
-+ (MyProc->replicationId >
proc->replicationId &&
-+ proc->heldLocks & aheadRequests) ) {
-+ elog(DEBUG1,"origin's RId = %d ,
MyProc->RId = %d , skip",proc->replicationId,MyProc->replicationId);
-+ aheadRequests |= (1 <<
proc->waitLockMode);
-+ proc = (PGPROC *)
MAKE_PTR(proc->links.next);
-+ continue;
-+ }
-+
-+#endif
- /* Break out of loop to put myself before him
*/
- break;
- }
-@@ -706,8 +726,21 @@
- }
- else
- {
-+#ifdef USE_REPLICATION
-+ proc = (PGPROC *) &(waitQueue->links);
-+ for (i = 0; i < waitQueue->size+1; i++){
-+ elog(DEBUG1,"origin's RId = %d , MyProc->RId =
%d",proc->replicationId,MyProc->replicationId);
-+ if(proc->replicationId == 0 ||
-+ MyProc->replicationId > proc->replicationId) {
-+ proc= (PGPROC *) MAKE_PTR(proc->links.next);
-+ }else {
-+ break;
-+ }
-+ }
-+#else
- /* I hold no locks, so I can't push in front of anyone. */
- proc = (PGPROC *) &(waitQueue->links);
-+#endif
- }
-
- /*
-@@ -988,6 +1021,9 @@
- * such processes.
- */
- LWLockRelease(LockMgrLock);
-+#ifdef USE_REPLICATION
-+ PGR_Notice_DeadLock();
-+#endif
- }
-
-
-diff -aruN postgresql-8.1.2/src/backend/tcop/postgres.c
pgcluster-1.5.0rc7/src/backend/tcop/postgres.c
---- postgresql-8.1.2/src/backend/tcop/postgres.c 2005-12-14
18:06:37.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/tcop/postgres.c 2006-02-09
11:09:21.000000000 +0100
-@@ -64,6 +64,10 @@
-
- #include "pgstat.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-+
- extern int optind;
- extern char *optarg;
-
-@@ -84,6 +88,9 @@
- /* GUC variable for maximum stack depth (measured in kilobytes) */
- int max_stack_depth = 2048;
-
-+#ifdef USE_REPLICATION
-+bool PGR_Not_Replication_Query = false;
-+#endif /* USE_REPLICATION */
-
- /* ----------------
- * private variables
-@@ -820,6 +827,24 @@
- char *prepare_string = NULL;
- bool was_logged = false;
-
-+#ifdef USE_REPLICATION
-+ char * query_ptr = NULL;
-+ char * null_ptr = NULL;
-+ int skip_cnt = 0;
-+ int status = 0;
-+
-+ PGR_Reliable_Mode_Wait = false;
-+ query_ptr = (char *)query_string;
-+ if (PGR_Is_Replicated_Query == false)
-+ {
-+ PGR_Is_Replicated_Query =
PGR_Is_Replicated_Command(query_ptr);
-+ }
-+ PGR_Retry_Query.query_string = (char *)query_string;
-+ PGR_Retry_Query.query_len = strlen(query_string);
-+ PGR_Retry_Query.cmdSts = CMD_STS_OTHER;
-+ PGR_Retry_Query.cmdType = CMD_TYPE_OTHER;
-+#endif /* USE_REPLICATION */
-+
- /*
- * Report query to various monitoring facilities.
- */
-@@ -898,6 +923,13 @@
- DestReceiver *receiver;
- int16 format;
-
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = false;
-+ PGR_Reliable_Mode_Wait = false;
-+ PGR_Retry_Query.useFlag = DATA_INIT;
-+ PGR_Lock_Noticed = false;
-+#endif /* USE_REPLICATION */
-+
- /*
- * Get the command name for use in status display (it also
becomes the
- * default completion tag, down inside PortalRun). Set
ps_status and
-@@ -905,7 +937,6 @@
- * destination.
- */
- commandTag = CreateCommandTag(parsetree);
--
- set_ps_display(commandTag);
-
- BeginCommand(commandTag, dest);
-@@ -920,10 +951,192 @@
- */
- if (IsAbortedTransactionBlockState() &&
- !IsTransactionExitStmt(parsetree))
-+ {
-+#ifdef USE_REPLICATION
-+ Transaction_Mode = 0;
-+#endif
- ereport(ERROR,
-
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
- errmsg("current transaction is
aborted, "
- "commands ignored until end
of transaction block")));
-+ }
-+#ifdef USE_REPLICATION
-+ Query_String = NULL;
-+ query_ptr = PGR_Remove_Comment(query_ptr);
-+ PGR_Check_Lock.dest = TO_FRONTEND;
-+ PGR_Need_Notice = false;
-+ PGR_Check_Lock.check_lock_conflict = false;
-+ if (!xact_started)
-+ {
-+ start_xact_command();
-+ xact_started = true;
-+ }
-+ if (skip_cnt == 0)
-+ {
-+ skip_cnt = PGR_Is_Skip_Replication(query_ptr);
-+ }
-+ null_ptr = PGR_scan_terminate (query_ptr);
-+ if(null_ptr != NULL)
-+ {
-+ *null_ptr = '\0';
-+ }
-+ Transaction_Mode =
PGR_Set_Transaction_Mode(Transaction_Mode,commandTag);
-+ if ((PGR_Is_Replicated_Query ) ||
-+ (skip_cnt != 0))
-+ {
-+ if (skip_cnt > 0)
-+ {
-+ skip_cnt --;
-+ }
-+ else
-+ {
-+ skip_cnt = 0;
-+ }
-+ PGR_Copy_Data_Need_Replicate = false;
-+ if (!strncmp(commandTag,"SELECT",strlen("SELECT")))
-+ {
-+ if (PGR_Is_System_Command(query_ptr))
-+ {
-+ status =
PGR_Call_System_Command(query_ptr);
-+ if (status == STATUS_SKIP_QUERY)
-+ {
-+
EndCommand(PGR_ALREADY_REPLICATED_NOTICE_CMD,dest);
-+ break;
-+ }
-+ else
-+ {
-+
EndCommand("SYSTEM_COMMAND",dest);
-+ continue;
-+ }
-+ }
-+ }
-+ PGR_Check_Lock.status_lock_conflict = STATUS_OK;
-+ PGR_Check_Lock.dest = TO_FRONTEND;
-+ }
-+ else
-+ {
-+ PGR_Copy_Data_Need_Replicate = false;
-+
-+ /* check cluster db status */
-+ if ((PGR_Get_Cluster_Status() == STATUS_RECOVERY)
&&
-+ (PGR_Not_Replication_Query == false)
&&
-+ (Transaction_Mode == 0 ) )
-+ {
-+ elog(WARNING, "This query is not permitted
while recovery db ");
-+ if(null_ptr != NULL)
-+ {
-+ *null_ptr = ';';
-+ query_ptr = null_ptr +1;
-+ }
-+ continue;
-+ }
-+ if (PGR_Is_Stand_Alone() == true)
-+ {
-+ if (PGR_Stand_Alone->permit ==
PERMIT_READ_ONLY)
-+ {
-+ if (!strcmp(commandTag, "SHOW")) {
-+ VariableShowStmt *stmt =
(VariableShowStmt *)parsetree;
-+ if (!strcmp(stmt->name,
"replication_server")) {
-+
PGR_Not_Replication_Query = true;
-+ }
-+ }
-+
-+ if (PGR_Not_Replication_Query ==
false)
-+ elog(ERROR, "This query is
not permitted when all replication servers fell down ");
-+ }
-+ }
-+ else if ((PGRforceLoadBalance == false) &&
-+ ((PGR_Not_Replication_Query == false
) ||
-+ (!strcmp(commandTag,"SELECT"))))
-+ {
-+ status =
PGR_replication(query_ptr,dest,parsetree,commandTag);
-+ if (status == STATUS_REPLICATED)
-+ {
-+ if (xact_started)
-+ {
-+ finish_xact_command();
-+ xact_started = false;
-+ }
-+ CommandCounterIncrement();
-+ continue;
-+ }
-+ else if (status == STATUS_ERROR)
-+ {
-+ if (!strcmp(commandTag, "SHOW")) {
-+ VariableShowStmt *stmt =
(VariableShowStmt *)parsetree;
-+ if (!strcmp(stmt->name,
"replication_server")) {
-+
PGR_Not_Replication_Query = true;
-+ }
-+ }
-+ else if (PGR_Stand_Alone->permit ==
PERMIT_READ_ONLY)
-+ {
-+ elog(ERROR, "This query is
not permitted when all replication servers fell down ");
-+ }
-+ }
-+ else if (status == STATUS_DEADLOCK_DETECT)
-+ {
-+ PGR_Need_Notice = false;
-+ elog(ERROR, "postmaster deadlock
detected");
-+ continue;
-+ }
-+ else if (status == STATUS_REPLICATION_ABORT)
-+ {
-+ PGR_Need_Notice = false;
-+ elog(ERROR, "replication server
should be down, transaction aborted.");
-+ continue;
-+ }
-+ else if (status != STATUS_CONTINUE)
-+ {
-+ PGR_Check_Lock.dest = TO_FRONTEND;
-+ }
-+ else
-+ {
-+ PGR_Check_Lock.dest =
TO_REPLICATION_SERVER;
-+ PGR_Reliable_Mode_Wait = true;
-+ }
-+ }
-+ }
-+ if(null_ptr != NULL)
-+ {
-+ *null_ptr = ';';
-+ query_ptr = null_ptr +1;
-+ }
-+ if (!PGR_Is_Replicated_Query )
-+ {
-+ if ((!strcmp(commandTag,"BEGIN")) ||
-+ (!strcmp(commandTag, "START TRANSACTION")) ||
-+ (Transaction_Mode == 0 ) )
-+ {
-+ PGR_Reload_Start_Time();
-+ }
-+ }
-+ if (((IsA(parsetree, TransactionStmt)) ||
-+ (Transaction_Mode > 0) ||
-+ (Create_Temp_Table_Mode == true) ||
-+ (Session_Authorization_Mode == true)) ||
-+ (!strcmp(commandTag,"COPY")))
-+ {
-+ PGR_Need_Notice = true;
-+ PGR_Check_Lock.check_lock_conflict = true;
-+ }
-+ else
-+ {
-+ if (PGR_Not_Replication_Query == false)
-+ {
-+ PGR_Need_Notice = true;
-+ PGR_Check_Lock.check_lock_conflict = true;
-+ }
-+ else
-+ {
-+ if ((PGR_Is_Replicated_Query ) &&
-+ (!strncmp(commandTag,
"SELECT",strlen("SELECT"))))
-+ {
-+ PGR_Need_Notice = true;
-+ PGR_Check_Lock.check_lock_conflict =
true;
-+ }
-+ }
-+ }
-+#endif /* USE_REPLICATION */
-
- /* Make sure we are in a transaction command */
- start_xact_command();
-@@ -1046,7 +1259,42 @@
- * command the client sent, regardless of rewriting. (But a
command
- * aborted by error will not send an EndCommand report at
all.)
- */
-+#ifdef USE_REPLICATION
-+ /*
-+ * In Non-CONTROL LOCK CONFLICT mode, we *MUST NOT* send
command tag twice.
-+ * So , if it was already sent for lock notification , we
didn't send
-+ * tag here. also ReadyForQuery,too.
-+ */
-+ if(!(PGR_Is_Replicated_Query && PGR_Lock_Noticed))
-+#endif
- EndCommand(completionTag, dest);
-+#ifdef USE_REPLICATION
-+ if(PGR_Is_Replicated_Query &&
-+ needToUpdateReplicateIdOnNextQueryIsDone) {
-+ ++(ReplicationLog_Info.PGR_Replicate_ID);
-+
-+ if (CurrentReplicateServer != NULL)
-+ {
-+ /* set replicate id in this system */
-+ ++(CurrentReplicateServer->replicate_id);
-+ }
-+ elog(DEBUG1,"increased replicate_id to
%d",CurrentReplicateServer->replicate_id);
-+ needToUpdateReplicateIdOnNextQueryIsDone=false;
-+ }
-+
-+ if ((PGR_Need_Notice == true) &&
-+ (PGRforceLoadBalance == false))
-+ {
-+ PGR_Notice_Transaction_Query_Done();
-+ }
-+ if (ReplicateCurrentTime != NULL)
-+ {
-+ if (Transaction_Mode == 0)
-+ {
-+ ReplicateCurrentTime->use_seed = 1;
-+ }
-+ }
-+#endif
- } /* end loop
over parsetrees */
-
- /*
-@@ -1234,11 +1482,15 @@
- */
- if (IsAbortedTransactionBlockState() &&
- !IsTransactionExitStmt(parsetree))
-+ {
-+#ifdef USE_REPLICATION
-+ Transaction_Mode = 0;
-+#endif
- ereport(ERROR,
-
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
- errmsg("current transaction is
aborted, "
- "commands ignored until end
of transaction block")));
--
-+ }
- /*
- * OK to analyze, rewrite, and plan this query. Note that the
- * originally specified parameter set is not required to be
complete,
-@@ -1432,11 +1684,15 @@
- if (IsAbortedTransactionBlockState() &&
- (!IsTransactionExitStmtList(pstmt->query_list) ||
- numParams != 0))
-+ {
-+#ifdef USE_REPLICATION
-+ Transaction_Mode = 0;
-+#endif
- ereport(ERROR,
- (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
- errmsg("current transaction is aborted, "
- "commands ignored until end
of transaction block")));
--
-+ }
- /*
- * Create the portal. Allow silent replacement of an existing portal
only
- * if the unnamed portal is specified.
-@@ -1737,11 +1993,15 @@
- */
- if (IsAbortedTransactionBlockState() &&
- !IsTransactionExitStmtList(portal->parseTrees))
-+ {
-+#ifdef USE_REPLICATION
-+ Transaction_Mode = 0;
-+#endif
- ereport(ERROR,
- (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
- errmsg("current transaction is aborted, "
- "commands ignored until end
of transaction block")));
--
-+ }
- /* Check for cancel signal before we start execution */
- CHECK_FOR_INTERRUPTS();
-
-@@ -1882,11 +2142,15 @@
- */
- if (IsAbortedTransactionBlockState() &&
- PreparedStatementReturnsTuples(pstmt))
-+ {
-+#ifdef USE_REPLICATION
-+ Transaction_Mode = 0;
-+#endif
- ereport(ERROR,
- (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
- errmsg("current transaction is aborted, "
- "commands ignored until end
of transaction block")));
--
-+ }
- if (whereToSendOutput != DestRemote)
- return; /* can't actually do
anything... */
-
-@@ -1952,11 +2216,15 @@
- */
- if (IsAbortedTransactionBlockState() &&
- portal->tupDesc)
-+ {
-+#ifdef USE_REPLICATION
-+ Transaction_Mode = 0;
-+#endif
- ereport(ERROR,
- (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
- errmsg("current transaction is aborted, "
- "commands ignored until end
of transaction block")));
--
-+ }
- if (whereToSendOutput != DestRemote)
- return; /* can't actually do
anything... */
-
-@@ -2112,6 +2380,9 @@
- * backend. This is necessary precisely because we don't clean up our
- * shared memory state.
- */
-+#ifdef USE_REPLICATION
-+ PGR_delete_shm();
-+#endif /* USE_REPLICATION */
- exit(1);
- }
-
-@@ -2149,6 +2420,9 @@
- }
- }
-
-+#ifdef USE_REPLICATION
-+ PGR_delete_shm();
-+#endif /* USE_REPLICATION */
- errno = save_errno;
- }
-
-@@ -2163,6 +2437,9 @@
- void
- authdie(SIGNAL_ARGS)
- {
-+#ifdef USE_REPLICATION
-+ PGR_delete_shm();
-+#endif /* USE_REPLICATION */
- exit(0);
- }
-
-@@ -3165,6 +3442,14 @@
- pgstat_report_activity("<IDLE>");
- }
-
-+#ifdef USE_REPLICATION
-+ /*
-+ * In Non-CONTROL LOCK CONFLICT mode, we *MUST NOT*
send command tag twice.
-+ * So , if it was already sent for lock notification
, we didn't send
-+ * tag here. also ReadyForQuery,too.
-+ */
-+ if(!(PGR_Is_Replicated_Query && PGR_Lock_Noticed))
-+#endif
- ReadyForQuery(whereToSendOutput);
- send_rfq = false;
- }
-@@ -3204,7 +3489,25 @@
- */
- if (ignore_till_sync && firstchar != EOF)
- continue;
--
-+#ifdef USE_REPLICATION
-+ if ((firstchar == CMD_TYPE_P_PARSE) ||
-+ (firstchar == CMD_TYPE_P_BIND) ||
-+ (firstchar == CMD_TYPE_P_DESCRIBE) ||
-+ (firstchar == CMD_TYPE_P_EXECUTE) ||
-+ (firstchar == CMD_TYPE_P_SYNC) ||
-+ (firstchar == CMD_TYPE_P_CLOSE))
-+ {
-+ if (PGR_Send_Input_Message(firstchar, &input_message)
!= STATUS_OK)
-+ {
-+ if ((PGR_Is_Stand_Alone() == true) &&
-+ (PGR_Stand_Alone->permit ==
PERMIT_READ_ONLY))
-+ {
-+ elog(WARNING, "This query is not
permitted when all replication servers fell down ");
-+ break;
-+ }
-+ }
-+ }
-+#endif /* USE_REPLICATION */
- switch (firstchar)
- {
- case 'Q': /* simple query */
-@@ -3213,9 +3516,7 @@
-
- query_string =
pq_getmsgstring(&input_message);
- pq_getmsgend(&input_message);
--
- exec_simple_query(query_string);
--
- send_rfq = true;
- }
- break;
-@@ -3239,7 +3540,6 @@
- paramTypes[i] =
pq_getmsgint(&input_message, 4);
- }
- pq_getmsgend(&input_message);
--
- exec_parse_message(query_string,
stmt_name,
-
paramTypes, numParams);
- }
-@@ -3262,7 +3562,6 @@
- portal_name =
pq_getmsgstring(&input_message);
- max_rows =
pq_getmsgint(&input_message, 4);
- pq_getmsgend(&input_message);
--
- exec_execute_message(portal_name,
max_rows);
- }
- break;
-@@ -3356,7 +3655,6 @@
- describe_type =
pq_getmsgbyte(&input_message);
- describe_target =
pq_getmsgstring(&input_message);
- pq_getmsgend(&input_message);
--
- switch (describe_type)
- {
- case 'S':
-@@ -3395,6 +3693,27 @@
- case 'X':
- case EOF:
-
-+#ifdef USE_REPLICATION
-+ if (PGRforceLoadBalance == false)
-+ {
-+ if (PGR_Is_Replicated_Query == false)
-+ {
-+ PGR_Noticed_Abort = 1;
-+
PGRsend_system_command(CMD_STS_TRANSACTION_ABORT, CMD_TYPE_FRONTEND_CLOSED);
-+ }
-+ else if ((Transaction_Mode == 1) &&
(PGR_Noticed_Abort == 0))
-+ {
-+ if
(PGR_Did_Commit_Transaction() == true)
-+ {
-+
pgstat_report_activity("commit");
-+
exec_simple_query("commit");
-+ }
-+ }
-+ }
-+ /*
-+ PGR_Notice_Transaction_Query_Aborted();
-+ */
-+#endif /* USE_REPLICATION */
- /*
- * Reset whereToSendOutput to prevent ereport
from attempting
- * to send any more messages to client.
-diff -aruN postgresql-8.1.2/src/backend/tcop/pquery.c
pgcluster-1.5.0rc7/src/backend/tcop/pquery.c
---- postgresql-8.1.2/src/backend/tcop/pquery.c 2005-11-22 19:23:20.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/backend/tcop/pquery.c 2006-01-23
04:56:04.000000000 +0100
-@@ -25,6 +25,9 @@
- #include "utils/guc.h"
- #include "utils/memutils.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*
- * ActivePortal is the currently executing Portal (the most closely nested,
-@@ -143,6 +146,18 @@
- */
- dest = None_Receiver;
- }
-+#ifdef USE_REPLICATION
-+ if (PGR_Is_Replicated_Query == true )
-+ {
-+ /*
-+ * Replicated *SELECT* query is used to replicate
-+ * ONLY lock and function execution , results . All of
-+ * them will be discarded by pgrp processes.
-+ * So , we don't need to send it.
-+ */
-+ dest = None_Receiver;
-+ }
-+#endif /*USE_REPLICATION */
- }
-
- /*
-diff -aruN postgresql-8.1.2/src/backend/tcop/utility.c
pgcluster-1.5.0rc7/src/backend/tcop/utility.c
---- postgresql-8.1.2/src/backend/tcop/utility.c 2005-10-15
04:49:27.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/tcop/utility.c 2006-01-23
22:51:52.000000000 +0100
-@@ -57,6 +57,9 @@
- #include "utils/lsyscache.h"
- #include "utils/syscache.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*
- * Error-checking support for DROP commands
-@@ -1198,29 +1201,48 @@
-
- case T_SelectStmt:
- tag = "SELECT";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
-
- case T_TransactionStmt:
- {
- TransactionStmt *stmt = (TransactionStmt *)
parsetree;
-
-+#ifdef USE_REPLICATION
-+ bool isInTransaction=IsTransactionBlock();
-+#endif /* USE_REPLICATION */
-+
- switch (stmt->kind)
- {
- case TRANS_STMT_BEGIN:
- tag = "BEGIN";
-+#ifdef USE_REPLICATION
-+
PGR_Not_Replication_Query=isInTransaction;
-+#endif /* USE_REPLICATION */
- break;
-
- case TRANS_STMT_START:
- tag = "START TRANSACTION";
-+#ifdef USE_REPLICATION
-+
PGR_Not_Replication_Query=isInTransaction;
-+#endif /* USE_REPLICATION */
- break;
-
- case TRANS_STMT_COMMIT:
- tag = "COMMIT";
-+#ifdef USE_REPLICATION
-+
PGR_Not_Replication_Query=!isInTransaction;
-+#endif /* USE_REPLICATION */
- break;
-
- case TRANS_STMT_ROLLBACK:
- case TRANS_STMT_ROLLBACK_TO:
- tag = "ROLLBACK";
-+#ifdef USE_REPLICATION
-+
PGR_Not_Replication_Query=!isInTransaction;
-+#endif /* USE_REPLICATION */
- break;
-
- case TRANS_STMT_SAVEPOINT:
-@@ -1252,10 +1274,16 @@
-
- case T_DeclareCursorStmt:
- tag = "DECLARE CURSOR";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
-
- case T_ClosePortalStmt:
- tag = "CLOSE CURSOR";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
-
- case T_FetchStmt:
-@@ -1264,6 +1292,9 @@
-
- tag = (stmt->ismove) ? "MOVE" : "FETCH";
- }
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
-
- case T_CreateDomainStmt:
-@@ -1581,10 +1612,16 @@
- tag = "VACUUM";
- else
- tag = "ANALYZE";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
-
- case T_ExplainStmt:
- tag = "EXPLAIN";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
-
- case T_VariableSetStmt:
-@@ -1593,6 +1630,14 @@
-
- case T_VariableShowStmt:
- tag = "SHOW";
-+#ifdef USE_REPLICATION
-+ {
-+ VariableShowStmt *stmt = (VariableShowStmt
*)parsetree;
-+ if (strcmp(stmt->name, "replication_server"))
{
-+ PGR_Not_Replication_Query = true;
-+ }
-+ }
-+#endif /* USE_REPLICATION */
- break;
-
- case T_VariableResetStmt:
-@@ -1651,10 +1696,16 @@
-
- case T_CheckPointStmt:
- tag = "CHECKPOINT";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
-
- case T_ReindexStmt:
- tag = "REINDEX";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
-
- case T_CreateConversionStmt:
-@@ -1696,6 +1747,13 @@
- break;
- }
-
-+#ifdef USE_REPLICATION
-+ if(PGRforceLoadBalance == true)
-+ {
-+ PGR_Not_Replication_Query = true;
-+ }
-+#endif /* USE_REPLICATION */
-+
- return tag;
- }
-
-@@ -1729,7 +1787,12 @@
- tag = "SELECT FOR SHARE";
- }
- else
-+ {
- tag = "SELECT";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
-+ }
- break;
- case CMD_UPDATE:
- tag = "UPDATE";
-@@ -1747,6 +1810,9 @@
- elog(WARNING, "unrecognized commandType: %d",
- (int) parsetree->commandType);
- tag = "???";
-+#ifdef USE_REPLICATION
-+ PGR_Not_Replication_Query = true;
-+#endif /* USE_REPLICATION */
- break;
- }
-
-diff -aruN postgresql-8.1.2/src/backend/utils/adt/datetime.c
pgcluster-1.5.0rc7/src/backend/utils/adt/datetime.c
---- postgresql-8.1.2/src/backend/utils/adt/datetime.c 2005-12-01
18:56:43.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/utils/adt/datetime.c 2006-01-18
23:42:03.000000000 +0100
-@@ -25,7 +25,6 @@
- #include "utils/datetime.h"
- #include "utils/guc.h"
-
--
- static int DecodeNumber(int flen, char *field, bool haveTextMonth,
- int fmask, int *tmask,
- struct pg_tm * tm, fsec_t *fsec, int *is2digits);
-diff -aruN postgresql-8.1.2/src/backend/utils/adt/float.c
pgcluster-1.5.0rc7/src/backend/utils/adt/float.c
---- postgresql-8.1.2/src/backend/utils/adt/float.c 2005-10-15
04:49:28.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/utils/adt/float.c 2006-01-10
17:39:38.000000000 +0100
-@@ -68,6 +68,9 @@
- #include "utils/array.h"
- #include "utils/builtins.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- #ifndef M_PI
- /* from my RH5.2 gcc math.h file - thomas 2000-04-03 */
-@@ -1834,7 +1837,11 @@
- float8 result;
-
- /* result 0.0-1.0 */
-+#ifdef USE_REPLICATION
-+ result = ((double) PGR_Random()) / ((double) MAX_RANDOM_VALUE);
-+#else
- result = ((double) random()) / ((double) MAX_RANDOM_VALUE);
-+#endif /* USE_REPLICATION */
-
- PG_RETURN_FLOAT8(result);
- }
-diff -aruN postgresql-8.1.2/src/backend/utils/adt/nabstime.c
pgcluster-1.5.0rc7/src/backend/utils/adt/nabstime.c
---- postgresql-8.1.2/src/backend/utils/adt/nabstime.c 2005-10-22
16:27:29.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/utils/adt/nabstime.c 2006-01-18
23:58:50.000000000 +0100
-@@ -29,6 +29,10 @@
- #include "utils/builtins.h"
- #include "utils/nabstime.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-+
- #define MIN_DAYNUM (-24856) /* December 13, 1901 */
- #define MAX_DAYNUM 24854 /* January 18, 2038 */
-
-@@ -94,7 +98,13 @@
- {
- time_t now;
-
-+#ifdef USE_REPLICATION
-+ struct timeval tp;
-+ PGR_GetTimeOfDay(&tp,NULL);
-+ now = tp.tv_sec;
-+#else
- now = time(NULL);
-+#endif /* USE_REPLICATION */
- return (AbsoluteTime) now;
- }
-
-@@ -1033,9 +1043,14 @@
- {
- time_t sec;
-
-+#ifdef USE_REPLICATION
-+ struct timeval tp;
-+ PGR_GetTimeOfDay(&tp,NULL);
-+ sec = tp.tv_sec;
-+#else
- if (time(&sec) < 0)
- PG_RETURN_ABSOLUTETIME(INVALID_ABSTIME);
--
-+#endif
- PG_RETURN_ABSOLUTETIME((AbsoluteTime) sec);
- }
-
-@@ -1590,7 +1605,11 @@
- int len;
- pg_time_t tt;
-
-+#ifdef USE_REPLICATION
-+ PGR_GetTimeOfDay(&tp,NULL);
-+#else
- gettimeofday(&tp, NULL);
-+#endif /* USE_REPLICATION */
- tt = (pg_time_t) tp.tv_sec;
- pg_strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z",
- pg_localtime(&tt, global_timezone));
-diff -aruN postgresql-8.1.2/src/backend/utils/adt/ri_triggers.c
pgcluster-1.5.0rc7/src/backend/utils/adt/ri_triggers.c
---- postgresql-8.1.2/src/backend/utils/adt/ri_triggers.c 2005-11-22
19:23:21.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/utils/adt/ri_triggers.c 2006-01-10
17:39:38.000000000 +0100
-@@ -45,6 +45,10 @@
- #include "utils/typcache.h"
- #include "miscadmin.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+extern bool check_constraint_with_lock;
-+#endif /* USE_REPLICATION */
-
- /* ----------
- * Local definitions
-@@ -266,8 +270,18 @@
- * ----------
- */
- quoteRelationName(pkrelname, pk_rel);
-+#ifdef USE_REPLICATION
-+ if (check_constraint_with_lock)
-+ snprintf(querystr, sizeof(querystr), "SELECT
1 FROM ONLY %s x FOR UPDATE OF x",
-+ pkrelname);
-+ else
-+ snprintf(querystr, sizeof(querystr), "SELECT
1 FROM ONLY %s x ",
-+ pkrelname);
-+
-+#else
- snprintf(querystr, sizeof(querystr), "SELECT 1 FROM
ONLY %s x FOR SHARE OF x",
- pkrelname);
-+#endif /* USE_REPLICATION */
-
- /* Prepare and save the plan */
- qplan = ri_PlanCheck(querystr, 0, NULL,
-@@ -411,6 +425,9 @@
- queryoids[i] = SPI_gettypeid(fk_rel->rd_att,
-
qkey.keypair[i][RI_KEYPAIR_FK_IDX]);
- }
-+#ifdef USE_REPLICATION
-+ if (check_constraint_with_lock)
-+#endif /* USE_REPLICATION */
- strcat(querystr, " FOR SHARE OF x");
-
- /* Prepare and save the plan */
-@@ -572,6 +589,9 @@
- queryoids[i] = SPI_gettypeid(pk_rel->rd_att,
-
qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
- }
-+#ifdef USE_REPLICATION
-+ if (check_constraint_with_lock)
-+#endif /* USE_REPLICATION */
- strcat(querystr, " FOR SHARE OF x");
-
- /* Prepare and save the plan */
-@@ -728,6 +748,9 @@
- queryoids[i] =
SPI_gettypeid(pk_rel->rd_att,
-
qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
- }
-+#ifdef USE_REPLICATION
-+ if (check_constraint_with_lock)
-+#endif /* USE_REPLICATION */
- strcat(querystr, " FOR SHARE OF x");
-
- /* Prepare and save the plan */
-@@ -917,6 +940,9 @@
- queryoids[i] =
SPI_gettypeid(pk_rel->rd_att,
-
qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
- }
-+#ifdef USE_REPLICATION
-+ if (check_constraint_with_lock)
-+#endif /* USE_REPLICATION */
- strcat(querystr, " FOR SHARE OF x");
-
- /* Prepare and save the plan */
-@@ -1423,6 +1449,9 @@
- queryoids[i] =
SPI_gettypeid(pk_rel->rd_att,
-
qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
- }
-+#ifdef USE_REPLICATION
-+ if (check_constraint_with_lock)
-+#endif /* USE_REPLICATION */
- strcat(querystr, " FOR SHARE OF x");
-
- /* Prepare and save the plan */
-@@ -1602,6 +1631,9 @@
- queryoids[i] =
SPI_gettypeid(pk_rel->rd_att,
-
qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
- }
-+#ifdef USE_REPLICATION
-+ if (check_constraint_with_lock)
-+#endif /* USE_REPLICATION */
- strcat(querystr, " FOR SHARE OF x");
-
- /* Prepare and save the plan */
-diff -aruN postgresql-8.1.2/src/backend/utils/adt/timestamp.c
pgcluster-1.5.0rc7/src/backend/utils/adt/timestamp.c
---- postgresql-8.1.2/src/backend/utils/adt/timestamp.c 2005-11-22
19:23:22.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/utils/adt/timestamp.c 2006-01-18
23:59:10.000000000 +0100
-@@ -31,6 +31,9 @@
- #include "utils/builtins.h"
- #include "utils/datetime.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /*
- * gcc's -ffast-math switch breaks routines that expect exact results from
-@@ -937,7 +940,11 @@
- TimestampTz result;
- struct timeval tp;
-
-+#ifdef USE_REPLICATION
-+ PGR_GetTimeOfDay(&tp,NULL);
-+#else
- gettimeofday(&tp, NULL);
-+#endif
-
- result = (TimestampTz) tp.tv_sec -
- ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-diff -aruN postgresql-8.1.2/src/backend/utils/error/assert.c
pgcluster-1.5.0rc7/src/backend/utils/error/assert.c
---- postgresql-8.1.2/src/backend/utils/error/assert.c 2005-10-15
04:49:32.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/utils/error/assert.c 2006-01-10
17:39:34.000000000 +0100
-@@ -19,6 +19,10 @@
-
- #include <unistd.h>
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-+
- /*
- * ExceptionalCondition - Handles the failure of an Assert()
- */
-@@ -39,6 +43,18 @@
- fileName, lineNumber);
- }
-
-+#ifdef USE_REPLICATION
-+ if ((PGR_Check_Lock.dest == TO_REPLICATION_SERVER ) &&
-+ (PGR_Need_Notice == true))
-+ {
-+ PGR_Notice_Transaction_Query_Aborted();
-+ }
-+ if (PGR_Copy_Data_Need_Replicate)
-+ {
-+ PGR_Set_Copy_Data(PGRCopyData,NULL,0,1);
-+ }
-+#endif /* USE_REPLICATION */
-+
- #ifdef SLEEP_ON_ASSERT
-
- /*
-diff -aruN postgresql-8.1.2/src/backend/utils/error/elog.c
pgcluster-1.5.0rc7/src/backend/utils/error/elog.c
---- postgresql-8.1.2/src/backend/utils/error/elog.c 2005-11-22
19:23:23.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/utils/error/elog.c 2006-01-10
17:39:34.000000000 +0100
-@@ -69,6 +69,9 @@
- #include "utils/guc.h"
- #include "utils/ps_status.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
- /* Global variables */
- ErrorContextCallback *error_context_stack = NULL;
-@@ -313,6 +316,16 @@
- MemoryContext oldcontext;
- ErrorContextCallback *econtext;
-
-+#ifdef USE_REPLICATION
-+ int status = 0;
-+ bool parse_error_flag = false;
-+
-+ if ((edata->message) && (strstr(edata->message,"parse error") !=
NULL))
-+ {
-+ parse_error_flag = true;
-+ }
-+#endif /* USE_REPLICATION */
-+
- recursion_depth++;
- CHECK_STACK_DEPTH();
-
-@@ -362,6 +375,24 @@
- * handler should reset it to something else soon.
- */
-
-+#ifdef USE_REPLICATION
-+ if (parse_error_flag)
-+ {
-+ if ((PGR_Check_Lock.dest != TO_FRONTEND) &&
-+ (Transaction_Mode > 0))
-+ {
-+ PGR_Force_Replicate_Query();
-+ }
-+ }
-+ if (PGR_Copy_Data_Need_Replicate)
-+ {
-+ PGR_Set_Copy_Data(PGRCopyData,NULL,0,1);
-+ }
-+ else if (PGR_Need_Notice == true)
-+ {
-+ PGR_Notice_Transaction_Query_Done();
-+ }
-+#endif /* USE_REPLICATION */
- recursion_depth--;
- PG_RE_THROW();
- }
-@@ -376,7 +407,16 @@
- * client_min_messages above FATAL, so don't look at output_to_client.
- */
- if (elevel >= FATAL && whereToSendOutput == DestRemote)
-+ {
-+#ifdef USE_REPLICATION
-+ if (PGR_Copy_Data_Need_Replicate)
-+ {
-+ PGR_Set_Copy_Data(PGRCopyData,NULL,0,1);
-+ }
-+#endif /* USE_REPLICATION */
- pq_endcopyout(true);
-+ }
-+
-
- /* Emit the message to the right places */
- EmitErrorReport();
-@@ -416,6 +456,34 @@
- if (PG_exception_stack == NULL && whereToSendOutput ==
DestRemote)
- whereToSendOutput = DestNone;
-
-+#ifdef USE_REPLICATION
-+ if (CurrentReplicateServer != NULL)
-+ {
-+ if (PGR_Need_Notice == true)
-+ {
-+ PGR_Notice_Transaction_Query_Aborted();
-+ }
-+ if (PGR_Copy_Data_Need_Replicate)
-+ {
-+ PGR_Set_Copy_Data(PGRCopyData,NULL,0,1);
-+ }
-+ else
-+ {
-+ if ((!PGR_Is_Replicated_Query ) &&
-+ (PGR_Check_Lock.dest != TO_FRONTEND)
&&
-+ (PGR_Reliable_Mode_Wait == true) &&
-+
(CurrentReplicateServer->response_mode == PGR_RELIABLE_MODE))
-+ {
-+ status = PGR_Recv_Trigger(0);
-+ }
-+ }
-+ }
-+ if (TransactionSock != -1)
-+ {
-+ close (TransactionSock);
-+ TransactionSock = -1;
-+ }
-+#endif /* USE_REPLICATION */
- /*
- * fflush here is just to improve the odds that we get to see
the
- * error message, in case things are so hosed that proc_exit
crashes.
-@@ -437,6 +505,34 @@
-
- if (elevel >= PANIC)
- {
-+#ifdef USE_REPLICATION
-+ if (CurrentReplicateServer != NULL)
-+ {
-+ if (PGR_Need_Notice == true)
-+ {
-+ PGR_Notice_Transaction_Query_Aborted();
-+ }
-+ if (PGR_Copy_Data_Need_Replicate)
-+ {
-+ PGR_Set_Copy_Data(PGRCopyData,NULL,0,1);
-+ }
-+ else
-+ {
-+ if ((!PGR_Is_Replicated_Query ) &&
-+ (PGR_Check_Lock.dest != TO_FRONTEND)
&&
-+ (PGR_Reliable_Mode_Wait == true) &&
-+
(CurrentReplicateServer->response_mode == PGR_RELIABLE_MODE))
-+ {
-+ status =
PGR_Recv_Trigger(PGR_RECV_TIMEOUT);
-+ }
-+ }
-+ }
-+ if (TransactionSock != -1)
-+ {
-+ close (TransactionSock);
-+ TransactionSock = -1;
-+ }
-+#endif /* USE_REPLICATION */
- /*
- * Serious crash time. Postmaster will observe nonzero
process exit
- * status and kill the other backends too.
-diff -aruN postgresql-8.1.2/src/backend/utils/fmgr/dfmgr.c
pgcluster-1.5.0rc7/src/backend/utils/fmgr/dfmgr.c
---- postgresql-8.1.2/src/backend/utils/fmgr/dfmgr.c 2005-10-15
04:49:32.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/utils/fmgr/dfmgr.c 2006-01-10
17:39:34.000000000 +0100
-@@ -20,6 +20,9 @@
- #include "dynloader.h"
- #include "miscadmin.h"
- #include "utils/dynamic_loader.h"
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-
-
- /*
-@@ -82,6 +85,9 @@
- char *load_error;
- struct stat stat_buf;
- char *fullname;
-+#ifdef USE_REPLICATION
-+ int status = STATUS_OK;
-+#endif /* USE_REPLICATION */
-
- fullname = expand_dynamic_library_name(filename);
- if (!fullname)
-@@ -176,6 +182,13 @@
- funcname, fullname)));
-
- pfree(fullname);
-+#ifdef USE_REPLICATION
-+ status = PGR_Replicate_Function_Call();
-+ if (status != STATUS_OK)
-+ {
-+ return NULL;
-+ }
-+#endif /* USE_REPLICATION */
- return retval;
- }
-
-diff -aruN postgresql-8.1.2/src/backend/utils/mb/mbutils.c
pgcluster-1.5.0rc7/src/backend/utils/mb/mbutils.c
---- postgresql-8.1.2/src/backend/utils/mb/mbutils.c 2005-10-15
04:49:33.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/backend/utils/mb/mbutils.c 2006-01-10
17:39:34.000000000 +0100
-@@ -16,6 +16,9 @@
- #include "utils/syscache.h"
- #include "catalog/namespace.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
- /*
- * We handle for actual FE and BE encoding setting encoding-identificator
- * and encoding-name too. It prevent searching and conversion from encoding
-@@ -404,6 +407,11 @@
- dest_encoding;
- FmgrInfo *flinfo;
-
-+#ifdef USE_REPLICATION
-+ if (PGR_Is_Replicated_Query)
-+ return src;
-+#endif /* USE_REPLICATION */
-+
- if (len <= 0)
- return (char *) src;
-
-diff -aruN postgresql-8.1.2/src/backend/utils/misc/guc.c
pgcluster-1.5.0rc7/src/backend/utils/misc/guc.c
---- postgresql-8.1.2/src/backend/utils/misc/guc.c 2005-11-22
19:23:24.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/utils/misc/guc.c 2006-01-23
04:55:40.000000000 +0100
-@@ -64,6 +64,14 @@
- #include "utils/pg_locale.h"
- #include "pgstat.h"
-
-+#ifdef USE_REPLICATION
-+#include "replicate.h"
-+#endif /* USE_REPLICATION */
-+
-+#ifdef USE_REPLICATION
-+bool check_constraint_with_lock = false;
-+bool auto_lock_table = true;
-+#endif /* USE_REPLICATION */
-
- #ifndef PG_KRB_SRVTAB
- #define PG_KRB_SRVTAB ""
-@@ -225,6 +233,9 @@
- char *role_string;
- char *session_authorization_string;
-
-+#ifdef USE_REPLICATION
-+static void ShowReplicationServerConfig(DestReceiver *dest);
-+#endif /* USE_REPLICATION */
-
- /*
- * Displayable names for context types (enum GucContext)
-@@ -947,6 +958,32 @@
- &pg_krb_caseins_users,
- false, NULL, NULL
- },
-+#ifdef USE_REPLICATION
-+ {
-+ {"pgr_force_loadbalance", PGC_USERSET, CLIENT_CONN_STATEMENT,
-+ gettext_noop("force loadbalance mode"),
-+ NULL
-+ },
-+ &PGRforceLoadBalance,
-+ false, NULL, NULL
-+ },
-+ {
-+ {"check_constraint_with_lock", PGC_USERSET,
CLIENT_CONN_STATEMENT,
-+ gettext_noop("check constrain with lock"),
-+ NULL
-+ },
-+ &check_constraint_with_lock,
-+ false, NULL, NULL
-+ },
-+ {
-+ {"auto_lock_table", PGC_USERSET, CLIENT_CONN_STATEMENT,
-+ gettext_noop("auto lock table"),
-+ NULL
-+ },
-+ &auto_lock_table,
-+ true, NULL, NULL
-+ },
-+#endif
-
- {
- {"escape_string_warning", PGC_USERSET,
COMPAT_OPTIONS_PREVIOUS,
-@@ -4544,6 +4581,10 @@
- {
- if (pg_strcasecmp(name, "all") == 0)
- ShowAllGUCConfig(dest);
-+#ifdef USE_REPLICATION
-+ else if (strcasecmp(name, "replication_server") == 0)
-+ ShowReplicationServerConfig(dest);
-+#endif
- else
- ShowGUCConfigOption(name, dest);
- }
-@@ -5976,5 +6017,72 @@
- return nbuf;
- }
-
-+#ifdef USE_REPLICATION
-+/*
-+ * SHOW REPLICATION SERVER command
-+ */
-+static void
-+ShowReplicationServerConfig(DestReceiver *dest)
-+{
-+ TupOutputState *tstate;
-+ TupleDesc tupdesc;
-+ char *values[4];
-+ char buffer[256];
-+ ReplicateServerInfo *sp;
-+
-+ /* need a tuple descriptor representing two TEXT columns */
-+ tupdesc = CreateTemplateTupleDesc(4, false);
-+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "status",
-+ TEXTOID, -1, 0 );
-+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "host_name",
-+ TEXTOID, -1, 0 );
-+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "port_num",
-+ TEXTOID, -1, 0 );
-+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "recovery_port_num",
-+ TEXTOID, -1, 0 );
-+
-+ /* prepare for projection of tuples */
-+ tstate = begin_tup_output_tupdesc(dest, tupdesc);
-+
-+ sp = ReplicateServerData;
-+ while (sp->useFlag != DATA_END) {
-+ if (PGR_Check_Replicate_Server_Status(sp) == STATUS_ERROR) {
-+ PGR_Set_Replication_Server_Status(sp, DATA_ERR);
-+ }
-+
-+ sp++;
-+ }
-+
-+ sp = ReplicateServerData;
-+ while (sp->useFlag != DATA_END) {
-+ if (sp->useFlag == DATA_USE) {
-+ values[0] = "ALIVE";
-+ } else if (sp->useFlag == DATA_ERR) {
-+ values[0] = "DEAD";
-+ } else if (sp->useFlag == DATA_INIT) {
-+ values[0] = "STANDBY";
-+ } else {
-+ values[0] = "UNKNOWN";
-+ }
-+
-+ values[1] = (char *) sp->hostName;
-+
-+ snprintf(buffer, sizeof(buffer), "%d", sp->portNumber);
-+ values[2] = pstrdup(buffer);
-+
-+ snprintf(buffer, sizeof(buffer), "%d",
sp->recoveryPortNumber);
-+ values[3] = pstrdup(buffer);
-+
-+ do_tup_output(tstate, values);
-+
-+ pfree(values[2]);
-+ pfree(values[3]);
-+
-+ sp++;
-+ }
-+
-+ end_tup_output(tstate);
-+}
-+#endif /* USE_REPLICATION */
-
- #include "guc-file.c"
-diff -aruN postgresql-8.1.2/src/backend/utils/misc/postgresql.conf.sample
pgcluster-1.5.0rc7/src/backend/utils/misc/postgresql.conf.sample
---- postgresql-8.1.2/src/backend/utils/misc/postgresql.conf.sample
2005-11-10 15:02:59.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/backend/utils/misc/postgresql.conf.sample
2006-01-10 17:39:38.000000000 +0100
-@@ -428,3 +428,11 @@
- #---------------------------------------------------------------------------
-
- #custom_variable_classes = '' # list of custom variable class names
-+
-+
-+#---------------------------------------------------------------------------
-+# PGCluster
-+#---------------------------------------------------------------------------
-+
-+# auto_lock_table = false
-+# check_constraint_with_lock = false
-diff -aruN postgresql-8.1.2/src/bin/initdb/initdb.c
pgcluster-1.5.0rc7/src/bin/initdb/initdb.c
---- postgresql-8.1.2/src/bin/initdb/initdb.c 2005-11-22 19:23:26.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/bin/initdb/initdb.c 2006-01-10 17:39:49.000000000
+0100
-@@ -107,6 +107,11 @@
- static char *info_schema_file;
- static char *features_file;
- static char *system_views_file;
-+#ifdef USE_REPLICATION
-+static char *cluster_conf_file;
-+static char *pgreplicate_conf_file;
-+static char *pglb_conf_file;
-+#endif /* USE_REPLICATION */
- static char *effective_user;
- static bool made_new_pgdata = false;
- static bool found_existing_pgdata = false;
-@@ -1284,6 +1289,14 @@
-
- free(conflines);
-
-+#ifdef USE_REPLICATION
-+ /* cluster.conf */
-+ conflines = readfile(cluster_conf_file);
-+ snprintf(path, sizeof(path), "%s/cluster.conf", pg_data);
-+ writefile(path, conflines);
-+ chmod(path, 0600);
-+ free(conflines);
-+#endif /* USE_REPLICATION */
- check_ok();
- }
-
-@@ -2468,6 +2481,11 @@
- set_input(&info_schema_file, "information_schema.sql");
- set_input(&features_file, "sql_features.txt");
- set_input(&system_views_file, "system_views.sql");
-+#ifdef USE_REPLICATION
-+ set_input(&cluster_conf_file, "cluster.conf.sample");
-+ set_input(&pgreplicate_conf_file, "pgreplicate.conf.sample");
-+ set_input(&pglb_conf_file, "pglb.conf.sample");
-+#endif /* USE_REPLICATION */
-
- set_info_version();
-
-@@ -2484,6 +2502,16 @@
- effective_user, bki_file,
- desc_file, conf_file,
- hba_file, ident_file);
-+#ifdef USE_REPLICATION
-+ fprintf(stderr,
-+ "PGCLUSTER_VERSION=%s\n"
-+
"CLUSTER_CONF_SAMPLE=%s\nPGREPLICATE_CONF_SAMPLE=%s\n"
-+ "PGLB_CONF_SAMPLE=%s\n",
-+ PGCLUSTER_VERSION,
-+ cluster_conf_file,
-+ pgreplicate_conf_file,
-+ pglb_conf_file);
-+#endif /* USE_REPLICATION */
- if (show_setting)
- exit(0);
- }
-@@ -2497,6 +2525,11 @@
- check_input(info_schema_file);
- check_input(features_file);
- check_input(system_views_file);
-+#ifdef USE_REPLICATION
-+ check_input(cluster_conf_file);
-+ check_input(pgreplicate_conf_file);
-+ check_input(pglb_conf_file);
-+#endif /* USE_REPLICATION */
-
- setlocales();
-
-diff -aruN postgresql-8.1.2/src/bin/pg_dump/pg_dump.c
pgcluster-1.5.0rc7/src/bin/pg_dump/pg_dump.c
---- postgresql-8.1.2/src/bin/pg_dump/pg_dump.c 2005-11-22 19:23:26.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/bin/pg_dump/pg_dump.c 2006-01-23
21:35:54.000000000 +0100
-@@ -111,6 +111,9 @@
- /* flag to turn on/off dollar quoting */
- static int disable_dollar_quoting = 0;
-
-+#ifdef USE_REPLICATION
-+ bool nonReplicate=true;
-+#endif
-
- static void help(const char *progname);
- static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid);
-@@ -220,6 +223,9 @@
- {"column-inserts", no_argument, NULL, 'D'},
- {"host", required_argument, NULL, 'h'},
- {"ignore-version", no_argument, NULL, 'i'},
-+#ifdef USE_REPLICATION
-+ {"non-replicate", no_argument ,NULL, 'r'},
-+#endif
- {"no-reconnect", no_argument, NULL, 'R'},
- {"oids", no_argument, NULL, 'o'},
- {"no-owner", no_argument, NULL, 'O'},
-@@ -280,7 +286,7 @@
- }
- }
-
-- while ((c = getopt_long(argc, argv,
"abcCdDE:f:F:h:in:oOp:RsS:t:uU:vWxX:Z:",
-+ while ((c = getopt_long(argc, argv,
"abcCdDE:f:F:h:in:oOp:rRsS:t:uU:vWxX:Z:",
- long_options,
&optindex)) != -1)
- {
- switch (c)
-@@ -347,6 +353,12 @@
- pgport = optarg;
- break;
-
-+#ifdef USE_REPLICATION
-+ case 'r':
-+ nonReplicate = true;
-+ break;
-+#endif
-+
- case 'R':
- /* no-op, still accepted for backwards
compatibility */
- break;
-@@ -514,6 +526,11 @@
- /*
- * Start serializable transaction to dump consistent data.
- */
-+#ifdef USE_REPLICATION
-+ if(nonReplicate) {
-+ do_sql_command(g_conn, "set pgr_force_loadbalance to on");
-+ }
-+#endif /* USE_REPLICATION */
- do_sql_command(g_conn, "BEGIN");
-
- do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL
SERIALIZABLE");
-@@ -685,6 +702,9 @@
- printf(_(" -o, --oids include OIDs in dump\n"));
- printf(_(" -O, --no-owner skip restoration of object
ownership\n"
- " in plain text
format\n"));
-+#ifdef USE_REPLICATION
-+ printf(_(" -r, --non-replicate No queries replicate. Available
only in pgcluster.\n"));
-+#endif
- printf(_(" -s, --schema-only dump only the schema, no
data\n"));
- printf(_(" -S, --superuser=NAME specify the superuser user name
to use in\n"
- " plain text format\n"));
-diff -aruN postgresql-8.1.2/src/bin/pg_dump/pg_dumpall.c
pgcluster-1.5.0rc7/src/bin/pg_dump/pg_dumpall.c
---- postgresql-8.1.2/src/bin/pg_dump/pg_dumpall.c 2005-10-15
04:49:39.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/bin/pg_dump/pg_dumpall.c 2006-01-10
17:39:48.000000000 +0100
-@@ -99,6 +99,9 @@
- {"oids", no_argument, NULL, 'o'},
- {"no-owner", no_argument, NULL, 'O'},
- {"port", required_argument, NULL, 'p'},
-+#ifdef USE_REPLICATION
-+ {"non-replicate", no_argument ,NULL, 'r'},
-+#endif
- {"password", no_argument, NULL, 'W'},
- {"schema-only", no_argument, NULL, 's'},
- {"superuser", required_argument, NULL, 'S'},
-@@ -164,7 +167,7 @@
-
- pgdumpopts = createPQExpBuffer();
-
-- while ((c = getopt_long(argc, argv, "acdDgh:ioOp:sS:U:vWxX:",
long_options, &optindex)) != -1)
-+ while ((c = getopt_long(argc, argv, "acdDgh:ioOp:rsS:U:vWxX:",
long_options, &optindex)) != -1)
- {
- switch (c)
- {
-@@ -218,6 +221,11 @@
- #endif
- break;
-
-+#ifdef USE_REPLICATION
-+ case 'r':
-+ appendPQExpBuffer(pgdumpopts, " -r");
-+ break;
-+#endif /* USE_REPLICATION */
- case 's':
- schema_only = true;
- appendPQExpBuffer(pgdumpopts, " -s");
-@@ -383,6 +391,9 @@
- printf(_("\nConnection options:\n"));
- printf(_(" -h, --host=HOSTNAME database server host or socket
directory\n"));
- printf(_(" -p, --port=PORT database server port number\n"));
-+#ifdef USE_REPLICATION
-+ printf(_(" -r, --non-replicate No queries replicate. Available
only in pgcluster.\n"));
-+#endif /* USE_REPLICATION */
- printf(_(" -U, --username=NAME connect as specified database
user\n"));
- printf(_(" -W, --password force password prompt (should
happen automatically)\n"));
-
-diff -aruN postgresql-8.1.2/src/bin/psql/sql_help.h
pgcluster-1.5.0rc7/src/bin/psql/sql_help.h
---- postgresql-8.1.2/src/bin/psql/sql_help.h 2006-01-06 05:09:44.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/bin/psql/sql_help.h 2006-01-10 17:39:49.000000000
+0100
-@@ -3,7 +3,7 @@
- * *** generated from the DocBook documentation.
- *
- * generated by
-- * /usr/local/bin/perl create_help.pl ../../../doc/src/sgml/ref
sql_help.h
-+ * /usr/bin/perl create_help.pl ../../../doc/src/sgml/ref sql_help.h
- *
- */
-
-diff -aruN postgresql-8.1.2/src/include/catalog/catalog.h
pgcluster-1.5.0rc7/src/include/catalog/catalog.h
---- postgresql-8.1.2/src/include/catalog/catalog.h 2005-10-15
04:49:42.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/include/catalog/catalog.h 2006-01-10
17:39:43.000000000 +0100
-@@ -35,5 +35,4 @@
- extern Oid GetNewOidWithIndex(Relation relation, Relation indexrel);
- extern Oid GetNewRelFileNode(Oid reltablespace, bool relisshared,
- Relation pg_class);
--
- #endif /* CATALOG_H */
-diff -aruN postgresql-8.1.2/src/include/pg_config.h.in
pgcluster-1.5.0rc7/src/include/pg_config.h.in
---- postgresql-8.1.2/src/include/pg_config.h.in 2005-12-06
03:29:26.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/include/pg_config.h.in 2006-01-10
17:39:43.000000000 +0100
-@@ -676,3 +676,7 @@
- /* Define to empty if the keyword `volatile' does not work. Warning: valid
- code using `volatile' can become incorrect without. Disable with care. */
- #undef volatile
-+
-+/* PGCluster version */
-+#undef PGCLUSTER_VERSION
-+
-diff -aruN postgresql-8.1.2/src/include/pg_config.h.win32
pgcluster-1.5.0rc7/src/include/pg_config.h.win32
---- postgresql-8.1.2/src/include/pg_config.h.win32 2006-01-05
05:02:26.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/include/pg_config.h.win32 2006-01-10
17:39:43.000000000 +0100
-@@ -5,6 +5,7 @@
- */
- #define PG_VERSION "8.1.2"
- #define PG_VERSION_STR "8.1.2 (win32)"
-+#define PGCLUSTER_VERSION "1.5.0"
-
- #define DEF_PGPORT 5432
- #define DEF_PGPORT_STR "5432"
-diff -aruN postgresql-8.1.2/src/include/replicate.h
pgcluster-1.5.0rc7/src/include/replicate.h
---- postgresql-8.1.2/src/include/replicate.h 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/include/replicate.h 2006-01-31 13:12:04.000000000
+0100
-@@ -0,0 +1,198 @@
-+/*-------------------------------------------------------------------------
-+ *
-+ * replicate.h
-+ * Primary include file for replicate server .c files
-+ *
-+ * This should be the first file included by replicate modules.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+#ifndef REPLICATE_H
-+#define REPLICATE_H
-+
-+#ifndef _SYS_TIME_H
-+#include <sys/time.h>
-+#endif
-+#include "tcop/dest.h"
-+#include "storage/proc.h"
-+#include "lib/stringinfo.h"
-+#include "replicate_com.h"
-+
-+#define STAND_ALONE_TAG "When_Stand_Alone"
-+#define NOT_REPLICATE_INFO_TAG "Not_Replicate_Info"
-+#define DB_NAME_TAG "DB_Name"
-+#define TABLE_NAME_TAG "Table_Name"
-+
-+#define CLUSTER_CONF_FILE "cluster.conf"
-+#define NOT_SESSION_AUTHORIZATION (0)
-+#define SESSION_AUTHORIZATION_BEGIN (1)
-+#define SESSION_AUTHORIZATION_END (2)
-+
-+#define READ_ONLY_IF_STAND_ALONE "read_only"
-+#define READ_WRITE_IF_STAND_ALONE "read_write"
-+#define PERMIT_READ_ONLY (1)
-+#define PERMIT_READ_WRITE (2)
-+#define STATUS_REPLICATED (3)
-+#define STATUS_CONTINUE (4)
-+#define STATUS_CONTINUE_SELECT (5)
-+#define STATUS_NOT_REPLICATE (6)
-+#define STATUS_SKIP_QUERY (7)
-+#define STATUS_REPLICATE (10)
-+#define STATUS_RECOVERY (11)
-+#define STATUS_REPLICATION_ABORT (98)
-+#define STATUS_DEADLOCK_DETECT (99)
-+
-+#define TO_REPLICATION_SERVER (0)
-+#define TO_FRONTEND (1)
-+
-+#define PGR_DEADLOCK_DETECTION_MSG "deadlock detected!"
-+#define PGR_REPLICATION_ABORT_MSG "replication aborted!"
-+#define SKIP_QUERY_1 "begin; select getdatabaseencoding(); commit"
-+#define SKIP_QUERY_2 "BEGIN; SELECT usesuper FROM pg_catalog.pg_user WHERE
usename = '%s'; COMMIT"
-+#define SKIP_QUERY_3 "SET autocommit TO 'on'"
-+#define SKIP_QUERY_4 "SET search_path = public"
-+#define SYS_QUERY_1 "set pgr_force_loadbalance to on"
-+
-+#define PGR_SEND_RETRY_CNT (3)
-+#define PGR_SEND_WAIT_MSEC (150)
-+#define PGR_RECV_RETRY_CNT (3)
-+#define PGR_RECV_WAIT_MSEC (150)
-+#define PGR_SEND_TIMEOUT (5)
-+#define PGR_RECV_TIMEOUT (5)
-+#define PGR_LOCK_RETRY_CNT (50)
-+#define PGR_LOCK_WAIT_MSEC (20)
-+
-+#define PGR_1ST_RECOVERY (1)
-+#define PGR_2ND_RECOVERY (2)
-+
-+typedef struct
-+{
-+ bool is_stand_alone;
-+ int permit;
-+} PGR_Stand_Alone_Type;
-+
-+typedef struct
-+{
-+ char db_name[DBNAME_MAX_LENGTH];
-+ char table_name[TABLENAME_MAX_LENGTH];
-+} PGR_Not_Replicate_Type;
-+
-+typedef struct
-+{
-+ bool check_lock_conflict;
-+ bool deadlock;
-+ int status_lock_conflict;
-+ int dest;
-+} PGR_Check_Lock_Type;
-+
-+typedef struct
-+{
-+ char * query_string;
-+ int query_len;
-+ char cmdSts;
-+ char cmdType;
-+ char useFlag;
-+} PGR_Retry_Query_Type;
-+
-+
-+/* replicaition log */
-+typedef struct {
-+ uint32_t PGR_Replicate_ID;
-+ uint32_t PGR_Request_ID;
-+} PGR_ReplicationLog_Info;
-+
-+
-+extern char * Query_String;
-+extern int TransactionQuery;
-+extern int Transaction_Mode;
-+extern int PGR_Noticed_Abort;
-+extern bool Session_Authorization_Mode;
-+extern bool Create_Temp_Table_Mode;
-+extern int RecoveryPortNumber;
-+extern char * RsyncPath;
-+extern char * RsyncOption;
-+extern bool RsyncCompress;
-+extern int TransactionSock;
-+extern ReplicateNow * ReplicateCurrentTime;
-+extern CopyData * PGRCopyData;
-+extern bool PGR_Copy_Data_Need_Replicate;
-+extern PGR_Stand_Alone_Type * PGR_Stand_Alone;
-+extern PGR_Not_Replicate_Type * PGR_Not_Replicate;
-+extern int PGR_Not_Replicate_Rec_Num;
-+extern bool autocommit;
-+extern bool PGR_Is_Replicated_Query;
-+extern PGR_Check_Lock_Type PGR_Check_Lock;
-+extern int PGR_Sock_To_Replication_Server;
-+extern bool PGR_Need_Notice;
-+extern bool PGR_Lock_Noticed;
-+extern ReplicateServerInfo * CurrentReplicateServer;
-+extern ReplicateServerInfo * LastReplicateServer;
-+extern char * PGRSelfHostName;
-+extern int PGR_Pending_Sem_Num;
-+extern int PGR_Response_Mode;
-+extern bool PGR_Reliable_Mode_Wait;
-+extern PGR_Retry_Query_Type PGR_Retry_Query;
-+extern bool PGRforceLoadBalance;
-+extern bool needToUpdateReplicateIdOnNextQueryIsDone;
-+extern PGR_ReplicationLog_Info ReplicationLog_Info;
-+extern bool PGR_Not_Replication_Query;
-+extern bool PGR_Is_Sync_OID;
-+
-+/* in backend/libpq/replicate.c */
-+extern int PGR_Init_Replicate_Server_Data(void);
-+extern int PGR_Set_Replicate_Server_Socket(void);
-+extern ReplicateServerInfo * PGR_get_replicate_server_info(void);
-+extern char * PGR_Send_Replicate_Command(char * query_string, int
query_len, char cmdSts ,char cmdType);
-+extern bool PGR_Is_Replicated_Command(char * query);
-+extern int Xlog_Check_Replicate(int operation);
-+extern int PGR_Replicate_Function_Call(void);
-+extern void PGR_delete_shm(void);
-+extern int PGR_replication(char * query_string, CommandDest dest, Node
*parsetree, const char * commandTag);
-+extern bool PGR_Is_System_Command(char * query);
-+extern int PGR_Call_System_Command(char * command);
-+extern int PGR_GetTimeOfDay(struct timeval *tp,struct timezone *tpz);
-+extern long PGR_Random(void);
-+extern int PGR_Set_Current_Time(char * sec, char * usec);
-+extern int PGR_Send_Copy(CopyData * copy, int end);
-+extern CopyData * PGR_Set_Copy_Data(CopyData * copy, char *str, int len,
int end);
-+extern char * PGR_scan_terminate( char * str);
-+extern bool PGR_Is_Stand_Alone(void);
-+extern void PGR_Send_Message_To_Frontend(const char * msg);
-+extern void PGR_Notice_Transaction_Query_Done(void);
-+extern void PGR_Notice_Transaction_Query_Aborted(void);
-+extern int PGRsend_system_command(char cmdSts, char cmdType);
-+extern int PGR_Notice_Conflict(void);
-+extern int PGR_Recv_Trigger (int user_timeout);
-+#if 0
-+extern bool PGR_Check_DeadLock(LOCKMETHODTABLE *lockMethodTable, LOCKMODE
lockmode, LOCK *lock, PROCLOCK *holder);
-+#endif
-+extern void PGR_Set_Replication_Server_Status( ReplicateServerInfo * sp,
int status);
-+extern int PGR_Is_Skip_Replication(char * query);
-+extern bool PGR_Did_Commit_Transaction(void);
-+extern int PGR_Set_Transaction_Mode(int mode,const char * commandTag);
-+extern char * PGR_Remove_Comment(char * str);
-+extern void PGR_Force_Replicate_Query(void);
-+extern void PGR_Notice_DeadLock(void);
-+extern void PGR_Set_Cluster_Status(int status);
-+extern int PGR_Get_Cluster_Status(void);
-+extern int PGR_Check_Replicate_Server_Status(ReplicateServerInfo * sp);
-+extern int PGR_lo_import(char * filename);
-+extern int PGR_lo_create(int flags);
-+extern int PGR_lo_open(Oid lobjId,int32 mode);
-+extern int PGR_lo_close(int32 fd);
-+extern int PGR_lo_write(int fd, char *buf, int len);
-+extern int PGR_lo_lseek(int32 fd, int32 offset, int32 whence);
-+extern int PGR_lo_unlink(Oid lobjId);
-+extern uint32_t PGRget_replication_id(void);
-+extern Oid PGRGetNewObjectId(Oid last_id);
-+extern int PGR_Send_Input_Message(char cmdType,StringInfo input_message);
-+
-+/* in backend/libpq/recovery.c */
-+extern int PGR_Master_Main(void);
-+extern int PGR_Recovery_Main(void);
-+extern int PGR_recovery_error_send(void);
-+extern int PGR_recovery_finish_send(void);
-+
-+/* in backend/access/transam/xact.c */
-+extern void PGR_Reload_Start_Time(void);
-+#endif /* REPLICATE_H */
-diff -aruN postgresql-8.1.2/src/include/replicate_com.h
pgcluster-1.5.0rc7/src/include/replicate_com.h
---- postgresql-8.1.2/src/include/replicate_com.h 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/include/replicate_com.h 2006-01-29
22:45:17.000000000 +0100
-@@ -0,0 +1,388 @@
-+/*-------------------------------------------------------------------------
-+ *
-+ * replicate.h
-+ * Primary include file for replicate server .c files
-+ *
-+ * This should be the first file included by replicate modules.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+#ifndef REPLICATE_COM_H
-+#define REPLICATE_COM_H 1
-+
-+#ifndef _SYS_TYPES_H
-+#include <sys/types.h>
-+#endif
-+#ifndef _INTTYPES_H
-+#include <inttypes.h>
-+#endif
-+#ifndef _NETINET_IN_H
-+#include <netinet/in.h>
-+#endif
-+
-+#include "pg_config.h"
-+
-+/* default values */
-+#define DEFAULT_PGLB_PORT (6001)
-+#define DEFAULT_PGLB_RECOVERY_PORT (6101)
-+#define DEFAULT_PGLB_LIFECHECK_PORT (6201)
-+#define DEFAULT_CLUSTER_PORT (5432)
-+#define DEFAULT_CLUSTER_RECOVERY_PORT (7101)
-+#define DEFAULT_CLUSTER_LIFECHECK_PORT (7201)
-+#define DEFAULT_PGRP_PORT (8001)
-+#define DEFAULT_PGRP_RECOVERY_PORT (8101)
-+#define DEFAULT_PGRP_LIFECHECK_PORT (8201)
-+#define DEFAULT_PGRP_RLOG_PORT (8301)
-+#define MAX_DB_SERVER (32)
-+
-+/**************************
-+* *
-+* Packet ID definition *
-+* *
-+***************************/
-+/*=========================
-+ Replication packet id
-+===========================*/
-+#define CMD_SYS_REPLICATE 'R'
-+/*-------------------------
-+ Simple Query
-+--------------------------*/
-+#define CMD_STS_SET_SESSION_AUTHORIZATION 'S'
-+#define CMD_STS_TRANSACTION 'T'
-+#define CMD_STS_TEMP_TABLE 'E'
-+#define CMD_STS_QUERY 'Q'
-+#define CMD_STS_OTHER 'O'
-+
-+#define CMD_TYPE_VACUUM 'V'
-+#define CMD_TYPE_ANALYZE 'A'
-+#define CMD_TYPE_REINDEX 'N'
-+#define CMD_TYPE_SELECT 'S'
-+#define CMD_TYPE_EXPLAIN 'X'
-+#define CMD_TYPE_SET 'T'
-+#define CMD_TYPE_RESET 't'
-+#define CMD_TYPE_INSERT 'I'
-+#define CMD_TYPE_DELETE 'D'
-+#define CMD_TYPE_EXECUTE 'U'
-+#define CMD_TYPE_UPDATE 'U'
-+#define CMD_TYPE_BEGIN 'B'
-+#define CMD_TYPE_COMMIT 'E'
-+#define CMD_TYPE_ROLLBACK 'R'
-+#define CMD_TYPE_CONNECTION_CLOSE 'x'
-+#define CMD_TYPE_SESSION_AUTHORIZATION_BEGIN 'a'
-+#define CMD_TYPE_SESSION_AUTHORIZATION_END 'b'
-+#define CMD_TYPE_SAVEPOINT 's'
-+#define CMD_TYPE_ROLLBACK_TO_SAVEPOINT 'r'
-+#define CMD_TYPE_RELEASE_SAVEPOINT 'l'
-+#define CMD_TYPE_OTHER 'O'
-+
-+/*=========================
-+ System call packet id
-+===========================*/
-+#define CMD_SYS_CALL 'S'
-+#define CMD_SYS_PREREPLICATE 'Z'
-+
-+#define CMD_STS_NOTICE 'N'
-+#define CMD_STS_RESPONSE 'R'
-+#define CMD_STS_TRANSACTION_ABORT 'A'
-+#define CMD_STS_QUERY_SUSPEND 'P'
-+#define CMD_STS_QUERY_DONE 'D'
-+
-+#define CMD_TYPE_COMMIT_CONFIRM 'c'
-+#define CMD_TYPE_QUERY_CONFIRM 'q'
-+#define CMD_TYPE_DEADLOCK_DETECT 'd'
-+#define CMD_TYPE_FRONTEND_CLOSED 'x'
-+
-+/*----------------------------
-+ Copy Command
-+------------------------------*/
-+#define CMD_STS_COPY 'C'
-+
-+#define CMD_TYPE_COPY 'C'
-+#define CMD_TYPE_COPY_DATA 'd'
-+#define CMD_TYPE_COPY_DATA_END 'e'
-+
-+/*----------------------------
-+ Large Object
-+------------------------------*/
-+#define CMD_STS_LARGE_OBJECT 'L'
-+
-+#define CMD_TYPE_LO_IMPORT 'I'
-+#define CMD_TYPE_LO_CREATE 'C'
-+#define CMD_TYPE_LO_OPEN 'O'
-+#define CMD_TYPE_LO_WRITE 'W'
-+#define CMD_TYPE_LO_LSEEK 'S'
-+#define CMD_TYPE_LO_CLOSE 'X'
-+#define CMD_TYPE_LO_UNLINK 'U'
-+
-+/*-------------------------
-+ Prepare/Params Query
-+--------------------------*/
-+#define CMD_STS_PREPARE 'P'
-+
-+#define CMD_TYPE_P_PARSE 'P'
-+#define CMD_TYPE_P_BIND 'B'
-+#define CMD_TYPE_P_EXECUTE 'E'
-+#define CMD_TYPE_P_FASTPATH 'F'
-+#define CMD_TYPE_P_CLOSE 'C'
-+#define CMD_TYPE_P_DESCRIBE 'D'
-+#define CMD_TYPE_P_FLUSH 'H'
-+#define CMD_TYPE_P_SYNC 'S'
-+
-+#define PGR_TRANSACTION_SOCKET (0)
-+#define PGR_QUERY_SOCKET (1)
-+
-+#define DATA_FREE (0)
-+#define DATA_INIT (1)
-+#define DATA_USE (2)
-+#define DATA_ERR (90)
-+#define DATA_END (-1)
-+#define HOSTNAME_MAX_LENGTH (128)
-+#define DBNAME_MAX_LENGTH (128)
-+#define USERNAME_MAX_LENGTH (128)
-+#define TABLENAME_MAX_LENGTH (128)
-+#define PATH_MAX_LENGTH (256)
-+#define MAX_SERVER_NUM (128)
-+#define MAX_RETRY_TIMES (3)
-+#define MAX_SOCKET_QUEUE (100000)
-+#define TRANSACTION_ERROR_RESULT "TRANSACTION_ERROR"
-+#define REPLICATE_SERVER_SHM_KEY (1020)
-+/* target -> replicate */
-+#define RECOVERY_PREPARE_REQ (1)
-+/* replicate -> master */
-+#define RECOVERY_PGDATA_REQ (2)
-+/* master -> replicate */
-+#define RECOVERY_PGDATA_ANS (3)
-+/* replicate -> target */
-+#define RECOVERY_PREPARE_ANS (4)
-+/* target -> replicate */
-+#define RECOVERY_START_REQ (5)
-+/* replicate -> master */
-+#define RECOVERY_FSYNC_REQ (6)
-+/* master -> replicate */
-+#define RECOVERY_FSYNC_ANS (7)
-+/* replicate -> target */
-+#define RECOVERY_START_ANS (8)
-+/* target -> replicate */
-+#define RECOVERY_FINISH (9)
-+#define RECOVERY_ERROR_OCCUPIED (100)
-+#define RECOVERY_ERROR_CONNECTION (101)
-+#define RECOVERY_ERROR_TARGET_ONLY (102)
-+#define RECOVERY_ERROR_ANS (200)
-+#define REPLICATION_SERVER_INFO_TAG "Replicate_Server_Info"
-+#define HOST_NAME_TAG "Host_Name"
-+#define PORT_TAG "Port"
-+#define RECOVERY_PORT_TAG "Recovery_Port"
-+#define LIFECHECK_PORT_TAG "LifeCheck_Port"
-+#define RSYNC_PATH_TAG "Rsync_Path"
-+#define RSYNC_OPTION_TAG "Rsync_Option"
-+#define RSYNC_COMPRESS_TAG "Rsync_Compress"
-+#define RECOVERY_INIT (0)
-+#define RECOVERY_PREPARE_START (1)
-+#define RECOVERY_START (2)
-+#define RECOVERY_ERROR (99)
-+
-+/* response mode */
-+#define PGR_FAST_MODE (0)
-+#define PGR_NORMAL_MODE (1)
-+#define PGR_RELIABLE_MODE (2)
-+
-+#define RECOVERY_TIMEOUT (600)
-+#ifndef COMPLETION_TAG_BUFSIZE
-+#define COMPLETION_TAG_BUFSIZE (128)
-+#endif
-+
-+/* replicate log type */
-+#define FROM_R_LOG_TYPE (1)
-+#define FROM_C_DB_TYPE (2)
-+#define CONNECTION_SUSPENDED_TYPE (3)
-+
-+#define PGR_SYSTEM_COMMAND_FUNC "PGR_SYSTEM_COMMAND_FUNCTION"
-+#define PGR_STARTUP_REPLICATION_SERVER_FUNC_NO (1)
-+#define PGR_CHANGE_REPLICATION_SERVER_FUNC_NO (2)
-+#define PGR_SET_CURRENT_TIME_FUNC_NO (3)
-+#define PGR_NOTICE_DEADLOCK_DETECTION_FUNC_NO (4)
-+#define PGR_TRANSACTION_CONFIRM_ANSWER_FUNC_NO (5)
-+#define PGR_RELIABLE_MODE_DONE_FUNC_NO (6)
-+#define PGR_NOTICE_ABORT_FUNC_NO (7)
-+#define PGR_SET_CURRENT_REPLICATION_QUERY_ID_NO (8)
-+#define PGR_QUERY_CONFIRM_ANSWER_FUNC_NO (9)
-+#define PGR_GET_OID_FUNC_NO (10)
-+#define PGR_SET_OID_FUNC_NO (11)
-+
-+#define PGR_CMD_ARG_NUM (10)
-+#define PGR_LOCK_CONFLICT_NOTICE_CMD "PGR_LOCK_CONFLICT_NOTICE_CMD"
-+#define PGR_DEADLOCK_DETECT_NOTICE_CMD
"PGR_DEADLOCK_DETECT_NOTICE_CMD"
-+#define PGR_QUERY_DONE_NOTICE_CMD "PGR_QUERY_DONE_NOTICE_CMD"
-+#define PGR_QUERY_ABORTED_NOTICE_CMD "PGR_QUERY_ABORTED_NOTICE_CMD"
-+#define PGR_RETRY_LOCK_QUERY_CMD "PGR_RETRY_LOCK_QUERY_CMD"
-+#define PGR_NOT_YET_REPLICATE_NOTICE_CMD
"PGR_NOT_YET_REPLICATE_NOTICE_CMD"
-+#define PGR_ALREADY_REPLICATED_NOTICE_CMD
"PGR_ALREADY_REPLICATED_NOTICE_CMD"
-+#define PGR_NOT_YET_COMMIT (0)
-+#define PGR_ALREADY_COMMITTED (1)
-+
-+#define COPYBUFSIZ (8192)
-+#define MAX_WORDS (24)
-+#define MAX_WORD_LETTERS (48)
-+#define PGR_MESSAGE_BUFSIZE (128)
-+#define INT_LENGTH (12)
-+#define PGR_MAX_COUNTER (0x0FFFFFFF)
-+#define PGR_GET_OVER_FLOW_FILTER (0xF0000000)
-+#define PGR_GET_DATA_FILTER (0x0FFFFFFF)
-+#define PGR_SET_OVER_FLOW (0x10000000)
-+#define PGR_MIN_COUNTER (0x0000000F)
-+
-+#define STRCMP(x,y) (strncmp(x,y,strlen(y)))
-+
-+/* life check target */
-+#define SYN_TO_LOAD_BALANCER (0)
-+#define SYN_TO_CLUSTER_DB (1)
-+#define SYN_TO_REPLICATION_SERVER (2)
-+#define LIFE_CHECK_TRY_COUNT (2)
-+#define LIFE_CHECK_STOP (0)
-+#define LIFE_CHECK_START (1)
-+
-+#ifndef HAVE_UNION_SEMUN
-+union semun {
-+ int val;
-+ struct semid_ds *buf;
-+ unsigned short int *array;
-+ struct seminfo *__buf;
-+};
-+#endif
-+
-+typedef struct ReplicateHeaderType
-+{
-+ char cmdSys;
-+ char cmdSts; /*
-+ Q:query
-+ T:transaction
-+ */
-+ char cmdType; /*
-+ S:select
-+ I:insert
-+ D:delete
-+ U:update
-+ B:begin
-+ E:commit/rollback/end
-+ O:others
-+ */
-+ char rlog; /*
-+ -- kind of replication log --
-+ 1: send from replication log
-+ 2: send from cluster db
(should be retry)
-+ 3: connection suspended
-+ */
-+ uint16_t port;
-+ uint16_t pid;
-+ uint32_t query_size;
-+ char from_host[HOSTNAME_MAX_LENGTH];
-+ char dbName[DBNAME_MAX_LENGTH];
-+ char userName[USERNAME_MAX_LENGTH];
-+ struct timeval tv;
-+ uint32_t query_id;
-+ int isAutoCommit; /* 0 if autocommit is off. 1 if autocommit is on */
-+ uint32_t request_id;
-+ uint32_t replicate_id;
-+} ReplicateHeader;
-+
-+typedef struct RecoveryPacketType
-+{
-+ uint16_t packet_no; /*
-+ 1:start recovery prepare
-+ 2:ask pgdata
-+ 3:ans pgdata
-+ 4:send master info
-+ 5:start queueing query
-+ 6:requst fsync
-+ 7:ready to fsync
-+ 8:pepared master
-+ 9:finished rsync
-+ */
-+ uint16_t max_connect;
-+ uint16_t port;
-+ uint16_t recoveryPort;
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+ char pg_data[PATH_MAX_LENGTH];
-+ char userName[USERNAME_MAX_LENGTH];
-+} RecoveryPacket;
-+
-+typedef struct
-+{
-+ char table[128];
-+ int rec_no;
-+ char key[128];
-+ char value[128];
-+ char * last;
-+ char * next;
-+} ConfDataType;
-+
-+
-+typedef struct ReplicateServerInfoType
-+{
-+ uint32_t useFlag;
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+ uint16_t portNumber;
-+ uint16_t recoveryPortNumber;
-+ uint16_t lifecheckPortNumber;
-+ uint16_t RLogPortNumber;
-+ uint32_t sock;
-+ uint32_t rlog_sock;
-+ uint32_t replicate_id;
-+ uint16_t response_mode;
-+} ReplicateServerInfo;
-+
-+
-+typedef struct ReplicateNowType
-+{
-+ uint32_t replicate_id;
-+ int useFlag;
-+ int use_seed;
-+ int use_time;
-+ int offset_sec;
-+ int offset_usec;
-+ struct timeval tp;
-+} ReplicateNow;
-+
-+typedef struct CopyDataType
-+{
-+ int cnt;
-+ char copy_data[COPYBUFSIZ];
-+} CopyData;
-+
-+typedef struct ClusterDBInfoType
-+{
-+ int status;
-+} ClusterDBInfo;
-+
-+typedef struct
-+{
-+ uint32_t arg1;
-+ uint32_t arg2;
-+ uint32_t arg3;
-+ char buf[1];
-+} LOArgs;
-+
-+extern ConfDataType * ConfData_Top;
-+extern ConfDataType * ConfData_End;
-+extern ReplicateServerInfo * ReplicateServerData;
-+extern ClusterDBInfo * ClusterDBData;
-+extern int ReplicateServerShmid;
-+extern int ClusterDBShmid;
-+
-+
-+/* in backend/libpq/replicate_com.c */
-+extern int PGR_Create_Socket_Connect(int * fdP, char * hostName , unsigned
short portNumber);
-+extern void PGR_Close_Sock(int * sock);
-+extern int PGR_Create_Socket_Bind(int * fdP, char * hostName , unsigned
short portNumber);
-+extern int PGR_Create_Acception(int fd, int * sockP, char * hostName ,
unsigned short portNumber);
-+extern int PGR_Free_Conf_Data(void);
-+extern int PGR_Get_Conf_Data(char * dir , char * fname);
-+extern void PGRset_recovery_packet_no(RecoveryPacket * packet, int
packet_no);
-+extern unsigned int PGRget_ip_by_name(char * host);
-+extern void PGRwrite_log_file(FILE * fp, const char * fmt,...);
-+extern void show_debug(const char * fmt,...);
-+extern void show_error(const char * fmt,...);
-+
-+
-+
-+#endif /* REPLICATE_COM_H */
-diff -aruN postgresql-8.1.2/src/include/storage/lmgr.h
pgcluster-1.5.0rc7/src/include/storage/lmgr.h
---- postgresql-8.1.2/src/include/storage/lmgr.h 2005-10-15
04:49:46.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/include/storage/lmgr.h 2006-01-10
17:39:43.000000000 +0100
-@@ -15,6 +15,7 @@
- #define LMGR_H
-
- #include "storage/lock.h"
-+#include "storage/bufmgr.h"
- #include "utils/rel.h"
-
-
-@@ -85,4 +86,5 @@
- extern void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
- LOCKMODE lockmode);
-
-+extern void XactLockTableWaitForCluster(TransactionId xid,Buffer buffer);
- #endif /* LMGR_H */
-diff -aruN postgresql-8.1.2/src/include/storage/proc.h
pgcluster-1.5.0rc7/src/include/storage/proc.h
---- postgresql-8.1.2/src/include/storage/proc.h 2005-10-15
04:49:46.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/include/storage/proc.h 2006-01-10
17:39:43.000000000 +0100
-@@ -90,6 +90,9 @@
- * awaited by
this backend */
-
- struct XidCache subxids; /* cache for subtransaction XIDs */
-+#ifdef USE_REPLICATION
-+ unsigned int replicationId; /* id for replication. */
-+#endif
- };
-
- /* NOTE: "typedef struct PGPROC PGPROC" appears in storage/lock.h. */
-diff -aruN postgresql-8.1.2/src/interfaces/libpq/Makefile
pgcluster-1.5.0rc7/src/interfaces/libpq/Makefile
---- postgresql-8.1.2/src/interfaces/libpq/Makefile 2005-08-29
02:47:35.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/interfaces/libpq/Makefile 2006-01-10
17:39:43.000000000 +0100
-@@ -30,7 +30,7 @@
-
- OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
- fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \
-- md5.o ip.o wchar.o encnames.o noblock.o pgstrcasecmp.o thread.o \
-+ dllist.o md5.o ip.o wchar.o encnames.o noblock.o pgstrcasecmp.o
thread.o \
- $(filter crypt.o getaddrinfo.o inet_aton.o open.o snprintf.o
strerror.o, $(LIBOBJS))
-
- ifeq ($(PORTNAME), cygwin)
-@@ -86,6 +86,9 @@
- encnames.c wchar.c : % : $(backend_src)/utils/mb/%
- rm -f $@ && $(LN_S) $< .
-
-+dllist.c : % : $(backend_src)/lib/dllist.c
-+ rm -f $@ && $(LN_S) $< .
-+
-
- # We need several not-quite-identical variants of .DEF files to build libpq
- # DLLs for Windows. These are made from the single source file exports.txt.
-@@ -144,7 +147,7 @@
- rm -f $(DESTDIR)$(includedir)/libpq-fe.h
$(DESTDIR)$(includedir_internal)/libpq-int.h
$(DESTDIR)$(includedir_internal)/pqexpbuffer.h
-
- clean distclean: clean-lib
-- rm -f $(OBJS) pg_config_paths.h crypt.c getaddrinfo.c inet_aton.c
noblock.c pgstrcasecmp.c snprintf.c strerror.c open.c thread.c md5.c ip.c
encnames.c wchar.c pthread.h
-+ rm -f $(OBJS) pg_config_paths.h crypt.c getaddrinfo.c inet_aton.c
noblock.c pgstrcasecmp.c snprintf.c strerror.c open.c thread.c md5.c ip.c
encnames.c wchar.c pthread.h dllist.c
- rm -f pg_config_paths.h # Might be left over from a Win32 client-only
build
-
- maintainer-clean: distclean
-diff -aruN postgresql-8.1.2/src/interfaces/libpq/libpq.rc
pgcluster-1.5.0rc7/src/interfaces/libpq/libpq.rc
---- postgresql-8.1.2/src/interfaces/libpq/libpq.rc 2006-01-06
05:09:37.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/interfaces/libpq/libpq.rc 2006-02-09
23:03:29.000000000 +0100
-@@ -1,8 +1,8 @@
- #include <winver.h>
-
- VS_VERSION_INFO VERSIONINFO
-- FILEVERSION 8,1,2,6006
-- PRODUCTVERSION 8,1,2,6006
-+ FILEVERSION 8,1,2,6040
-+ PRODUCTVERSION 8,1,2,6040
- FILEFLAGSMASK 0x3fL
- FILEFLAGS 0
- FILEOS VOS__WINDOWS32
-diff -aruN postgresql-8.1.2/src/makefiles/Makefile.aix
pgcluster-1.5.0rc7/src/makefiles/Makefile.aix
---- postgresql-8.1.2/src/makefiles/Makefile.aix 2005-10-28
19:32:22.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/makefiles/Makefile.aix 2006-01-10
17:39:48.000000000 +0100
-@@ -36,3 +36,5 @@
- $(CC) $(LDFLAGS) $(LDFLAGS_SL) -o $@ $*.o -Wl,-bE:$*$(EXPSUFF)
$(SHLIB_LINK)
-
- sqlmansect = 7
-+CFLAGS += -pthread
-+LDFLAGS += -L/usr/lib/threads
-diff -aruN postgresql-8.1.2/src/makefiles/Makefile.freebsd
pgcluster-1.5.0rc7/src/makefiles/Makefile.freebsd
---- postgresql-8.1.2/src/makefiles/Makefile.freebsd 2005-08-24
22:20:38.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/makefiles/Makefile.freebsd 2006-01-10
17:39:48.000000000 +0100
-@@ -28,3 +28,5 @@
- endif
-
- sqlmansect = 7
-+
-+LIBS += -lc_r
-diff -aruN postgresql-8.1.2/src/makefiles/Makefile.hpux
pgcluster-1.5.0rc7/src/makefiles/Makefile.hpux
---- postgresql-8.1.2/src/makefiles/Makefile.hpux 2004-12-21
19:47:42.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/makefiles/Makefile.hpux 2006-01-10
17:39:48.000000000 +0100
-@@ -16,6 +16,9 @@
- # correctly in the LP64 data model.
- LIBS := -lxnet $(LIBS)
-
-+# add thread lib for PGCluster
-+LIBS := -lpthread $(LIBS)
-+
- # Set up rpath so that the executables don't need SHLIB_PATH to be set.
- # (Note: --disable-rpath is a really bad idea on this platform...)
- ifeq ($(with_gnu_ld), yes)
-diff -aruN postgresql-8.1.2/src/makefiles/Makefile.linux
pgcluster-1.5.0rc7/src/makefiles/Makefile.linux
---- postgresql-8.1.2/src/makefiles/Makefile.linux 2004-12-21
19:47:42.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/makefiles/Makefile.linux 2006-01-10
17:39:48.000000000 +0100
-@@ -14,3 +14,4 @@
- $(CC) -shared -o $@ $<
-
- sqlmansect = 7
-+LIBS += -lpthread
-diff -aruN postgresql-8.1.2/src/makefiles/Makefile.netbsd
pgcluster-1.5.0rc7/src/makefiles/Makefile.netbsd
---- postgresql-8.1.2/src/makefiles/Makefile.netbsd 2004-12-21
19:47:42.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/makefiles/Makefile.netbsd 2006-01-10
17:39:48.000000000 +0100
-@@ -30,3 +30,4 @@
- endif
-
- sqlmansect = 7
-+LIBS += -lpthread
-diff -aruN postgresql-8.1.2/src/makefiles/Makefile.openbsd
pgcluster-1.5.0rc7/src/makefiles/Makefile.openbsd
---- postgresql-8.1.2/src/makefiles/Makefile.openbsd 2004-12-21
19:47:42.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/makefiles/Makefile.openbsd 2006-01-10
17:39:48.000000000 +0100
-@@ -28,3 +28,4 @@
- endif
-
- sqlmansect = 7
-+LIBS += -lc_r
-diff -aruN postgresql-8.1.2/src/makefiles/Makefile.solaris
pgcluster-1.5.0rc7/src/makefiles/Makefile.solaris
---- postgresql-8.1.2/src/makefiles/Makefile.solaris 2004-12-21
19:47:42.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/makefiles/Makefile.solaris 2006-01-10
17:39:48.000000000 +0100
-@@ -20,3 +20,4 @@
- $(LD) -G -Bdynamic -o $@ $<
-
- sqlmansect = 5sql
-+LIBS += -lpthread
-diff -aruN postgresql-8.1.2/src/makefiles/Makefile.sunos4
pgcluster-1.5.0rc7/src/makefiles/Makefile.sunos4
---- postgresql-8.1.2/src/makefiles/Makefile.sunos4 2002-09-05
00:54:18.000000000 +0200
-+++ pgcluster-1.5.0rc7/src/makefiles/Makefile.sunos4 2006-01-10
17:39:48.000000000 +0100
-@@ -11,3 +11,4 @@
- $(LD) -assert pure-text -Bdynamic -o $@ $<
-
- sqlmansect = 7
-+LIBS += -lpthread
-diff -aruN postgresql-8.1.2/src/pgcluster/Makefile
pgcluster-1.5.0rc7/src/pgcluster/Makefile
---- postgresql-8.1.2/src/pgcluster/Makefile 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/Makefile 2006-01-10 17:39:44.000000000
+0100
-@@ -0,0 +1,17 @@
-+#-------------------------------------------------------------------------
-+#
-+# Makefile for src/pgcluster (client programs)
-+#
-+#-------------------------------------------------------------------------
-+
-+subdir = src/pgcluster
-+top_builddir = ../..
-+include $(top_builddir)/src/Makefile.global
-+
-+DIRS := libpgc pgrp pglb tool
-+
-+all install installdirs uninstall depend distprep:
-+ @for dir in $(DIRS); do $(MAKE) -C $$dir $@ || exit; done
-+
-+clean distclean maintainer-clean:
-+ -@for dir in $(DIRS); do $(MAKE) -C $$dir $@; done
-diff -aruN postgresql-8.1.2/src/pgcluster/libpgc/Makefile
pgcluster-1.5.0rc7/src/pgcluster/libpgc/Makefile
---- postgresql-8.1.2/src/pgcluster/libpgc/Makefile 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/libpgc/Makefile 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,32 @@
-+#-------------------------------------------------------------------------
-+#
-+# Makefile--
-+# Makefile for libpq subsystem (backend half of libpq interface)
-+#
-+# IDENTIFICATION
-+# $Header: /cvsroot/pgsql-server/src/backend/libpq/Makefile,v 1.33
2002/06/14 04:23:17 momjian Exp $
-+#
-+#-------------------------------------------------------------------------
-+
-+subdir = src/pgcluster/libpgc
-+top_builddir = ../../..
-+include $(top_builddir)/src/Makefile.global
-+
-+OBJS = sem.o show.o
-+
-+all: SUBSYS.o
-+
-+SUBSYS.o: $(OBJS)
-+ $(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
-+
-+depend dep:
-+ $(CC) -MM $(CFLAGS) *.c >depend
-+
-+distclean: clean
-+
-+clean:
-+ rm -f SUBSYS.o $(OBJS)
-+
-+ifeq (depend,$(wildcard depend))
-+include depend
-+endif
-diff -aruN postgresql-8.1.2/src/pgcluster/libpgc/libpgc.h
pgcluster-1.5.0rc7/src/pgcluster/libpgc/libpgc.h
---- postgresql-8.1.2/src/pgcluster/libpgc/libpgc.h 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/libpgc/libpgc.h 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,22 @@
-+/*-------------------------------------------------------------------------
-+ *
-+ * lilbpgc.h
-+ * external definition of the function for pgreplicate and pglb
-+ *
-+ * This should be the first file included by replicate modules.
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+#ifndef LIBPGC_H
-+#define LIBPGC_H
-+
-+/* external definition of the function in sem.c */
-+extern void PGRsem_unlock( int semid, short sem_num );
-+extern void PGRsem_lock( int semid, short sem_num );
-+
-+/* external definition of the function in show.c */
-+extern void show_debug(const char * fmt,...);
-+extern void show_error(const char * fmt,...);
-+extern void PGRwrite_log_file(FILE * fp, const char * fmt,...);
-+
-+#endif /* LIBPGC_H */
-diff -aruN postgresql-8.1.2/src/pgcluster/libpgc/sem.c
pgcluster-1.5.0rc7/src/pgcluster/libpgc/sem.c
---- postgresql-8.1.2/src/pgcluster/libpgc/sem.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/libpgc/sem.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,67 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * sem.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at pgreplicate for the semapho control.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <sys/types.h>
-+#include <errno.h>
-+#include <sys/ipc.h>
-+#include <sys/sem.h>
-+#include <signal.h>
-+
-+extern void show_debug(const char * fmt,...);
-+
-+void PGRsem_unlock( int semid, short sem_num );
-+void PGRsem_lock( int semid, short sem_num );
-+
-+#define PGR_SEM_UNLOCK_WAIT_MSEC (100)
-+#define PGR_SEM_LOCK_WAIT_MSEC (500)
-+
-+void
-+PGRsem_unlock( int semid, short sem_num )
-+{
-+ int status = 0;
-+ struct sembuf sops;
-+
-+ sops.sem_num = sem_num;
-+ sops.sem_op = 1;
-+ /*sops.sem_flg = IPC_NOWAIT;*/
-+ sops.sem_flg = 0;
-+ do
-+ {
-+ status = semop(semid, &sops, 1);
-+ if ((status == -1) && (errno != EINTR))
-+ {
-+ usleep(PGR_SEM_UNLOCK_WAIT_MSEC);
-+ }
-+ } while (status == -1);
-+}
-+
-+void
-+PGRsem_lock( int semid, short sem_num )
-+{
-+ int status = 0;
-+ struct sembuf sops;
-+
-+ sops.sem_num = sem_num;
-+ sops.sem_op = -1;
-+ /*sops.sem_flg = IPC_NOWAIT;*/
-+ sops.sem_flg = 0;
-+ do
-+ {
-+ status = semop(semid, &sops, 1);
-+ if ((status == -1) && (errno != EINTR))
-+ {
-+ usleep(PGR_SEM_LOCK_WAIT_MSEC);
-+ }
-+ } while (status == -1);
-+}
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/libpgc/show.c
pgcluster-1.5.0rc7/src/pgcluster/libpgc/show.c
---- postgresql-8.1.2/src/pgcluster/libpgc/show.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/libpgc/show.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,119 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * show.c
-+ *
-+ * NOTE:
-+ * This file is composed of the logging and debug functions
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#include <stdio.h>
-+#include <stdarg.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <time.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+
-+#define TIMESTAMP_SIZE 19 /* format `YYYY-MM-DD HH:MM:SS' */
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+void show_debug(const char * fmt,...);
-+void show_error(const char * fmt,...);
-+void PGRwrite_log_file(FILE * fp, const char * fmt,...);
-+
-+extern int Debug_Print;
-+extern int Log_Print;
-+extern FILE * LogFp;
-+
-+static char*
-+get_current_timestamp(void)
-+{
-+ time_t now;
-+ static char buf[TIMESTAMP_SIZE + 1];
-+
-+ now = time(NULL);
-+ strftime(buf, sizeof(buf),
-+ "%Y-%m-%d %H:%M:%S", localtime(&now));
-+ return buf;
-+}
-+
-+void
-+show_debug(const char * fmt,...)
-+{
-+ va_list ap;
-+ char *timestamp;
-+
-+ if (Debug_Print)
-+ {
-+ timestamp = get_current_timestamp();
-+ fprintf(stdout,"%s [%d] DEBUG:",timestamp, getpid());
-+ va_start(ap,fmt);
-+ vfprintf(stdout,fmt,ap);
-+ va_end(ap);
-+ fprintf(stdout,"\n");
-+ fflush(stdout);
-+ }
-+}
-+
-+void
-+show_error(const char * fmt,...)
-+{
-+ va_list ap;
-+ char buf[256], *timestamp;
-+
-+ if (Debug_Print)
-+ {
-+ timestamp = get_current_timestamp();
-+ fprintf(stderr,"%s [%d] ERROR:",timestamp, getpid());
-+ va_start(ap,fmt);
-+ vfprintf(stderr,fmt,ap);
-+ va_end(ap);
-+ fprintf(stderr,"\n");
-+ fflush(stderr);
-+ }
-+ if ((Log_Print) && (LogFp != NULL))
-+ {
-+ va_start(ap,fmt);
-+ vsnprintf(buf,sizeof(buf),fmt,ap);
-+ va_end(ap);
-+ PGRwrite_log_file(LogFp,buf);
-+ }
-+}
-+
-+void
-+PGRwrite_log_file(FILE * fp, const char * fmt,...)
-+{
-+ char buf[256];
-+ char log[288];
-+ char * timestamp;
-+ va_list ap;
-+ time_t t;
-+
-+ if (fp == NULL)
-+ {
-+ return;
-+ }
-+ if (time(&t) < 0)
-+ {
-+ return;
-+ }
-+ timestamp = get_current_timestamp();
-+ snprintf(log,sizeof(log),"%s ",timestamp);
-+ va_start(ap,fmt);
-+ vsnprintf(buf,sizeof(buf),fmt,ap);
-+ va_end(ap);
-+ strcat(log,buf);
-+ strcat(log,"\n");
-+ if (fputs(log,fp) >= 0)
-+ {
-+ fflush(fp);
-+ }
-+}
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/AUTHORS
pgcluster-1.5.0rc7/src/pgcluster/pglb/AUTHORS
---- postgresql-8.1.2/src/pgcluster/pglb/AUTHORS 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/AUTHORS 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,3 @@
-+Authors of pglb
-+
-+pglb was written by Atsushi Mitani
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/COPYING
pgcluster-1.5.0rc7/src/pgcluster/pglb/COPYING
---- postgresql-8.1.2/src/pgcluster/pglb/COPYING 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/COPYING 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,14 @@
-+Copyright (c) 2003 Atsushi Mitani
-+
-+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.
-+
-+Portions copyright (c) 2003, Tatsuo Ishii
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/Makefile
pgcluster-1.5.0rc7/src/pgcluster/pglb/Makefile
---- postgresql-8.1.2/src/pgcluster/pglb/Makefile 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/Makefile 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,38 @@
-+#-------------------------------------------------------------------------
-+#
-+# Makefile for src/pgcluster/pgrp
-+#
-+#-------------------------------------------------------------------------
-+
-+subdir = src/pgcluster/pglb
-+top_builddir = ../../..
-+include $(top_builddir)/src/Makefile.global
-+
-+OBJS= child.o cluster_table.o load_balance.o main.o pool_auth.o \
-+ pool_connection_pool.o pool_process_query.o pool_stream.o \
-+ pool_params.o recovery.o socket.o
-+
-+EXTRA_OBJS = $(top_builddir)/src/backend/libpq/replicate_com.o
../libpgc/SUBSYS.o
-+
-+CFLAGS += -DPRINT_DEBUG
-+override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) -DBINDIR=\"$(bindir)\"
-+
-+all: pglb
-+
-+pglb: $(OBJS) $(libpq_builddir)/libpq.a
-+ $(CC) $(CFLAGS) $(OBJS) $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o
$@
-+
-+install: all installdirs
-+ $(INSTALL_PROGRAM) pglb$(X) $(DESTDIR)$(bindir)/pglb$(X)
-+ $(INSTALL_DATA) pglb.conf.sample
$(DESTDIR)$(datadir)/pglb.conf.sample
-+
-+installdirs:
-+ $(mkinstalldirs) $(DESTDIR)$(bindir)
-+ $(mkinstalldirs) $(DESTDIR)$(datadir)
-+
-+uninstall:
-+ rm -f $(addprefix $(DESTDIR)$(bindir)/, pglb$(X))
-+ rm -f $(DESTDIR)$(datadir)/pglb.conf.sample
-+
-+clean distclean maintainer-clean:
-+ rm -f pglb$(X) $(OBJS)
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/README
pgcluster-1.5.0rc7/src/pgcluster/pglb/README
---- postgresql-8.1.2/src/pgcluster/pglb/README 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/README 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,276 @@
-+PGCluster Installation Instructions
-+
-+=============================================================
-+1. Installation
-+=============================================================
-+
-+1-1. Install Cluster DB Server, Replication Server & Load Balancer
-+----------------------------------------------------------------
-+$ cd $source_dir
-+$ ./configure
-+$ gmake
-+$ su
-+# gmake install
-+# chown -R postgres /usr/local/pgsql
-+----------------------------------------------------------------
-+
-+=============================================================
-+2. Initialize DB
-+=============================================================
-+$ su
-+# adduser postgres
-+# mkdir /usr/local/pgsql/data
-+# chown postgres /usr/local/pgsql/data
-+# su - postgres
-+$ /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
-+
-+
-+=============================================================
-+3. Configuration
-+=============================================================
-+(EX.System Composition)
-+
-+ |
-+ ((Load Balance Server))
-+ ( hostname: lb.hoo.com)
-+ ( receive port:5432 )
-+ ( recovery port:6001 )
-+ |
-+----------+-------------+------------+----------
-+ | |
-+ (( Cluster DB 1 )) (( Cluster DB 2 ))
-+ ( hostname:c1.hoo.com) ( hostname:c2.hoo.com)
-+ ( receive port: 5432 ) ( receive port:5432 )
-+ ( recovery port:7001 ) ( recovery port 7002 )
-+ | |
-+----------+-------------+------------+----------
-+ |
-+ ((Replication Server))
-+ ( hostname:pgr.hoo.com)
-+ ( receive port:8001 )
-+ ( recovery port:8101 )
-+
-+
-+3-1. Load Balance Server
-+
-+The setup file of load balance server is copied from the sample file and
edited.
-+(the sample file is installed '/usr/local/pgsql/etc' in default)
-+----------------------------------------------------------------
-+$cd /usr/local/pgsql/etc
-+$cp pglb.conf.sample pglb.conf
-+----------------------------------------------------------------
-+
-+In the case of the above system composition example,
-+the setup example of pglb.conf file is as the following
-+
-+#============================================================
-+# Load Balance Server configuration file
-+#-------------------------------------------------------------
-+# file: pglb.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts are db cluster server
-+# o which port use connect to db cluster server
-+# o how many connections are allowed on each DB server
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Max_Connection : maximun number of connection to postmaster
-+#-------------------------------------------------------------
-+<Cluster_Server_Info>
-+ <Host_Name> c1.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Max_Connect> 32 </Max_Connect>
-+</Cluster_Server_Info>
-+<Cluster_Server_Info>
-+ <Host_Name> c2.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Max_Connect> 32 </Max_Connect>
-+</Cluster_Server_Info>
-+#-------------------------------------------------------------
-+# set Load Balance server information
-+# o Receive_Port : connection from client
-+# o Recovery_Port : connection for recovery process
-+# o Max_Cluster_Num : maximun number of cluster DB servers
-+# o Use_Connection_Pooling : use connection pool [yes/no]
-+# o Max_Pool_Each_Server : number of pool connections/DB server
-+#-------------------------------------------------------------
-+<Receive_Port> 5432 </Receive_Port>
-+<Recovery_Port> 6001 </Recovery_Port>
-+<Max_Cluster_Num> 128 </Max_Cluster_Num>
-+<Use_Connection_Pooling> yes </Use_Connection_Pooling>
-+<Max_Pool_Each_Server> 1 </Max_Pool_Each_Server>
-+
-+3-2. Cluster DB Server
-+
-+The Cluster DB server need edit two configuration files
-+('pg_hba.conf' and 'cluster.conf').
-+These files are create under the $PG_DATA directory after 'initdb'.
-+
-+A. pg_hba.conf
-+Permission to connect DB via IP connectoins is need for this system.
-+
-+B. cluster.conf
-+In the case of the above system composition example,
-+the setup example of cluster.conf file is as the following
-+
-+#============================================================
-+# Cluster DB Server configuration file
-+#-------------------------------------------------------------
-+# file: cluster.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts & port are replication server
-+# o which port use for replication request to replication server
-+# o which command use for recovery function
-+#
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Recovery_Port : connection for recovery process
-+#-------------------------------------------------------------
-+<Replicate_Server_Info>
-+ <Host_Name> pgr.hoo.com </Host_Name>
-+ <Port> 8001 </Port>
-+ <Recovery_Port> 8101 </Recovery_Port>
-+</Replicate_Server_Info>
-+#-------------------------------------------------------------
-+# set Cluster DB Server information
-+# o Recovery_Port : connection for recovery
-+# o Rsync_Path : path of rsync command
-+# o Rsync_Option : file transfer option for rsync
-+# o When_Stand_Alone : When all replication servers fell,
-+# you can set up two kinds of permittion,
-+# "real_only" or "read_write".
-+#-------------------------------------------------------------
-+<Recovery_Port> 7001 </Recovery_Port>
-+<Rsync_Path> /usr/bin/rsync </Rsync_Path>
-+<Rsync_Option> ssh -1 </Rsync_Option>
-+<When_Stand_Alone> read_only </When_Stand_Alone>
-+#-------------------------------------------------------------
-+# set partitional replicate control information
-+# set DB name and Table name to stop reprication
-+# o DB_Name : DB name
-+# o Table_Name : table name
-+#-------------------------------------------------------------
-+#<Not_Replicate_Info>
-+# <DB_Name> test_db </DB_Name>
-+# <Table_Name> log_table </Table_Name>
-+#</Not_Replicate_Info>
-+
-+3-3. Replication Server
-+
-+The setup file of replication server is copied from the sample file and
edited.
-+(the sample file is installed '/usr/local/pgsql/etc' in default)
-+----------------------------------------------------------------
-+$cd /usr/local/pgsql/etc
-+$cp pgreplicate.conf.sample pgreplicate.conf
-+----------------------------------------------------------------
-+In the case of the above system composition example,
-+the setup example of pgreplicate.conf file is as the following
-+
-+#============================================================
-+# PGReplicate configuration file
-+#-------------------------------------------------------------
-+# file: pgreplicate.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts & port are cluster server
-+# o which port use for replication request from cluster server
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Recovery_Port : connection for recovery
-+#-------------------------------------------------------------
-+<Cluster_Server_Info>
-+ <Host_Name> c1.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Recovery_Port> 7001 </Recovery_Port>
-+</Cluster_Server_Info>
-+<Cluster_Server_Info>
-+ <Host_Name> c2.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Recovery_Port> 7001 </Recovery_Port>
-+</Cluster_Server_Info>
-+#-------------------------------------------------------------
-+# set Load Balance server information
-+# o Host_Name : hostname
-+# o Recovery_Port : connection for recovery
-+#-------------------------------------------------------------
-+<LoadBalance_Server_Info>
-+ <Host_Name> lb.hoo.com </Host_Name>
-+ <Recovery_Port> 6001 </Recovery_Port>
-+</LoadBalance_Server_Info>
-+#-------------------------------------------------------------
-+# set PGReplicate server information
-+# o Replicate_Port : connection for reprication
-+# o Recovery_Port : connection for recovery
-+#-------------------------------------------------------------
-+<Replication_Port> 8001 </Replication_Port>
-+<Recovery_Port> 8101 </Recovery_Port>
-+
-+
-+=============================================================
-+4. Start Up / Stop
-+=============================================================
-+
-+4-1. replication server
-+
-+A. Start replication server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pgreplicate -D /usr/local/pgsql/etc
-+----------------------------------------------------------------
-+
-+B. Stop replication server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pgreplicate -D /usr/local/pgsql/etc stop
-+----------------------------------------------------------------
-+
-+usage: pgreplicate [-D path_of_config_file] [-W path_of_work_files] [-U
login us
-+er][-l][-n][-v][-h][stop]
-+ -l: print error logs in the log file.
-+ -n: don't run in daemon mode.
-+ -v: debug mode. need '-n' flag
-+ -h: print this help
-+ stop: stop pgreplicate
-+(config file default path: ./pgreplicate.conf)
-+
-+4-2. cluster DB server
-+$PG_HOME = /usr/local/pgsql
-+$PG_DATA = /usr/local/pgsql/data
-+
-+A. Start cluster DB server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -o "-i" start
-+----------------------------------------------------------------
-+
-+B. Stop cluster DB server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data stop
-+----------------------------------------------------------------
-+
-+4-3. load balance server
-+
-+A. Start load balance server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pglb -D /usr/local/pgsql/etc
-+----------------------------------------------------------------
-+
-+B. Stop load balance server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pglb -D /usr/local/pgsql/etc stop
-+----------------------------------------------------------------
-+
-+usage: pglb [-D path_of_config_file] [-W path_of_work_files]
[-n][-v][-h][stop]
-+ -l: print error logs in the log file.
-+ -n: don't run in daemon mode.
-+ -v: debug mode. need '-n' flag
-+ -h: print this help
-+ stop: stop pglb
-+ (config file default path: ./pglb.conf)
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/child.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/child.c
---- postgresql-8.1.2/src/pgcluster/pglb/child.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/child.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,1194 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * child.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at child process of pglb.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ * Portions Copyright (c) 2003-2006, Tatsuo Ishii
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 "postgres.h"
-+
-+#include <stdio.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <sys/time.h>
-+#include <ctype.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <sys/param.h>
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+#include "postgres_fe.h"
-+#include "libpq/pqcomm.h"
-+
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+/*--------------------------------------
-+ * GLOBAL VARIABLE DECLARATION
-+ *--------------------------------------
-+ */
-+POOL_CONNECTION * Frontend = NULL;
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+int PGRpre_fork_children(ClusterTbl * ptr);
-+int PGRpre_fork_child(ClusterTbl * ptr);
-+int PGRdo_child( int use_pool);
-+int PGRcreate_child(ClusterTbl * cluster_p);
-+pid_t PGRscan_child_tbl(ClusterTbl * cluster_p);
-+void notice_backend_error(void);
-+void do_pooling_child(int sig);
-+int PGRset_status_to_child_tbl(pid_t pid, int status);
-+int PGRadd_child_tbl(ClusterTbl * cluster_p, pid_t pid, int status);
-+int PGRget_child_status(pid_t pid);
-+void PGRreturn_connection_full_error(void);
-+void PGRreturn_no_connection_error(void);
-+void PGRquit_children_on_cluster(int rec_no);
-+
-+#ifdef NONE_BLOCK
-+static void set_nonblock(int fd);
-+#endif
-+static void unset_nonblock(int fd);
-+static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd);
-+static PGR_StartupPacket *read_startup_packet(POOL_CONNECTION *cp);
-+static int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp);
-+static void cancel_request(CancelPacket *sp, int secondary_backend);
-+static POOL_CONNECTION_POOL *connect_backend(PGR_StartupPacket *sp,
POOL_CONNECTION *frontend);
-+static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*backend);
-+static void child_end(int sig);
-+static void PGRreturn_with_error(char *msg);
-+
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRpre_fork_children()
-+ * NOTES
-+ * pre forked child precesses
-+ * ARGS
-+ * ClusterTbl * ptr: pointer of cluster server table (I)
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGRpre_fork_children(ClusterTbl * ptr)
-+{
-+ int cnt;
-+
-+ if (ptr == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ cnt = 0 ;
-+ while ((ptr->useFlag != TBL_END) && (cnt < ClusterNum))
-+ {
-+ PGRpre_fork_child(ptr);
-+ cnt ++;
-+ ptr ++;
-+ }
-+ return STATUS_OK;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRpre_fork_child()
-+ * NOTES
-+ * pre forked child precess
-+ * ARGS
-+ * ClusterTbl * ptr: pointer of cluster server table (I)
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGRpre_fork_child(ClusterTbl * ptr)
-+{
-+ pid_t pid = 0;
-+ int i;
-+
-+ if (ptr == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (ptr->useFlag == TBL_END)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ for ( i = 0 ; i < ptr->max_connect * Max_Pool ; i ++)
-+ {
-+ pid = PGRcreate_child(ptr);
-+ }
-+ return STATUS_OK;
-+}
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRdo_child()
-+ * NOTES
-+ * execute child process
-+ * ARGS
-+ * int use_pool: usage flag of connection pooling (I)
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGRdo_child( int use_pool)
-+{
-+ char * func = "PGRdo_child()";
-+ pid_t pid = 0;
-+ PGR_StartupPacket *sp = NULL;
-+ POOL_CONNECTION *frontend = NULL;
-+ POOL_CONNECTION_POOL *backend = NULL;
-+ int status = 0;
-+ int connection_reuse = 1;
-+ int ssl_request = 0;
-+ int count = 0;
-+
-+ pid = getpid();
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:I am %d",func, pid);
-+#endif
-+
-+ /* set up signal handlers */
-+ signal(SIGALRM, SIG_DFL);
-+ signal(SIGTERM, child_end);
-+ signal(SIGHUP, child_end);
-+ signal(SIGINT, child_end);
-+ signal(SIGUSR1, SIG_IGN);
-+ signal(SIGUSR2, SIG_IGN);
-+
-+#ifdef NONE_BLOCK
-+ /* set listen fds to none block */
-+ set_nonblock(Frontend_FD.unix_fd);
-+ set_nonblock(Frontend_FD.inet_fd);
-+#endif
-+
-+retry_accept:
-+ /* perform accept() */
-+ frontend = do_accept(Frontend_FD.unix_fd,Frontend_FD.inet_fd);
-+ if (frontend == NULL)
-+ {
-+ /* accept() failed. return to the accept() loop */
-+ PGRset_status_to_child_tbl(pid,TBL_FREE);
-+ return STATUS_ERROR;
-+ }
-+
-+ /* unset frontend fd tp none block */
-+ unset_nonblock(frontend->fd);
-+
-+ /* read the startup packet */
-+ sp = 0;
-+retry_startup:
-+ if (sp)
-+ {
-+ free(sp->startup_packet);
-+ free(sp->database);
-+ free(sp->user);
-+ free(sp);
-+ }
-+
-+ sp = read_startup_packet(frontend);
-+ if (sp == NULL)
-+ {
-+ /* failed to read the startup packet. return to the
-+ accept() loop */
-+ pool_close(frontend);
-+ PGRset_status_to_child_tbl(pid,TBL_FREE);
-+ return STATUS_ERROR;
-+ }
-+ PGRset_status_to_child_tbl(pid,TBL_ACCEPT);
-+
-+ /* cancel request? */
-+ if (sp->major == 1234 && sp->minor == 5678)
-+ {
-+ cancel_request((CancelPacket *)sp->startup_packet, 0);
-+ pool_close(frontend);
-+ return STATUS_ERROR;
-+ }
-+
-+ /* SSL? */
-+ if (sp->major == 1234 && sp->minor == 5679)
-+ {
-+ /* SSL not supported */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:SSLRequest: sent N; retry startup",func);
-+#endif
-+ if (ssl_request)
-+ {
-+ pool_close(frontend);
-+ return STATUS_ERROR;
-+ }
-+
-+ /*
-+ * say to the frontend "we do not suppport SSL"
-+ * note that this is not a NOTICE response despite it's an
'N'!
-+ */
-+ pool_write_and_flush(frontend, "N", 1);
-+ ssl_request = 1;
-+ goto retry_startup;
-+ }
-+
-+ /*
-+ * Ok, negotiaton with frontend has been done. Let's go to the next
step.
-+ */
-+ /*
-+ * if there's no connection associated with user and database,
-+ * we need to connect to the backend and send the startup packet.
-+ */
-+ count = 0;
-+ if ((backend = pool_get_cp(sp->user, sp->database, sp->major)) ==
NULL)
-+ {
-+ connection_reuse = 0;
-+
-+ if ((backend = connect_backend(sp, frontend)) == NULL)
-+ {
-+ /*
-+
PGRset_status_on_cluster_tbl(TBL_ERROR,CurrentCluster);
-+ return STATUS_ERROR;
-+ */
-+ goto retry_accept;
-+ }
-+ }
-+ else
-+ {
-+ /* reuse existing connection to backend */
-+
-+ if (pool_do_reauth(frontend, backend))
-+ {
-+ pool_close(frontend);
-+ return STATUS_ERROR;
-+ }
-+
-+ if (MAJOR(backend) == 3)
-+ {
-+ if (send_params(frontend, backend))
-+ {
-+ pool_close(frontend);
-+ return STATUS_ERROR;
-+ }
-+ }
-+
-+ /* send ReadyForQuery to frontend */
-+ pool_write(frontend, "Z", 1);
-+
-+ if (MAJOR(backend) == 3)
-+ {
-+ int len;
-+ char tstate;
-+
-+ len = htonl(5);
-+ pool_write(frontend, &len, sizeof(len));
-+ tstate = TSTATE(backend);
-+ pool_write(frontend, &tstate, 1);
-+ }
-+
-+ if (pool_flush(frontend) < 0)
-+ {
-+ pool_close(frontend);
-+ return STATUS_ERROR;
-+ }
-+
-+ }
-+
-+ /* query process loop */
-+ for (;;)
-+ {
-+ POOL_STATUS status;
-+
-+ status = pool_process_query(frontend, backend, 0);
-+
-+ switch (status)
-+ {
-+ /* client exits */
-+ case POOL_END:
-+ /* do not cache connection to template0,
template1, regression */
-+ if (!strcmp(sp->database, "template0") ||
!strcmp(sp->database, "template1") ||
-+ !strcmp(sp->database, "regression") ||
use_pool == NOT_USE_CONNECTION_POOL)
-+ {
-+ pool_close(frontend);
-+ pool_send_frontend_exits(backend);
-+ pool_discard_cp(sp->user,
sp->database, sp->major);
-+ }
-+ else
-+ {
-+ POOL_STATUS status1;
-+
-+ /* send reset request to backend */
-+ status1 =
pool_process_query(frontend, backend, 1);
-+ pool_close(frontend);
-+
-+ /* if we detect errors on resetting
connection, we need to discard
-+ * this connection since it might be
in unknown status
-+ */
-+ if (status1 != POOL_CONTINUE)
-+ pool_discard_cp(sp->user,
sp->database, sp->major);
-+ else
-+
pool_connection_pool_timer(backend);
-+ }
-+ break;
-+
-+ /* error occured. discard backend connection pool
-+ and disconnect connection to the frontend */
-+ case POOL_ERROR:
-+ show_error("%s:do_child: exits with status 1
due to error",func);
-+ break;
-+
-+ /* fatal error occured. just exit myself... */
-+ case POOL_FATAL:
-+ show_error("%s:do_child: fatal error
occured",func);
-+ notice_backend_error();
-+ break;
-+
-+ /* not implemented yet */
-+ case POOL_IDLE:
-+
do_accept(Frontend_FD.unix_fd,Frontend_FD.inet_fd);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:accept while idle",func);
-+#endif
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (status != POOL_CONTINUE)
-+ break;
-+ }
-+ if ((status == POOL_ERROR) ||
-+ (status == POOL_FATAL))
-+ {
-+ PGRset_status_to_child_tbl(pid,TBL_FREE);
-+ return STATUS_ERROR;
-+ }
-+ PGRset_status_to_child_tbl(pid,TBL_INIT);
-+ return STATUS_OK;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRcreate_child()
-+ * NOTES
-+ * create child process
-+ * ARGS
-+ * ClusterTbl * ptr: pointer of cluster server table (I)
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGRcreate_child(ClusterTbl * cluster_p)
-+{
-+ char * func = "PGRcreate_child()";
-+ pid_t pid,pgid;
-+
-+ if (cluster_p == NULL)
-+ return STATUS_ERROR;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:create child
[%d@%s]",func,cluster_p->port,cluster_p->hostName);
-+#endif
-+ signal(SIGCHLD,PGRrecreate_child);
-+ pgid = getpgid((pid_t)0);
-+ pid = fork();
-+ if (pid < 0)
-+ {
-+ show_error("%s:fork() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ if (pid == 0)
-+ {
-+ CurrentCluster = cluster_p;
-+ if (pool_init_cp())
-+ {
-+ show_error("%s:pool_init_cp failed",func);
-+ exit(1);
-+ }
-+ signal(SIGCHLD,PGRchild_wait);
-+ signal(SIGTERM, child_end);
-+ signal(SIGHUP, child_end);
-+ signal(SIGINT, child_end);
-+ signal(SIGUSR1,do_pooling_child);
-+ setpgid((pid_t)0,pgid);
-+ for (;;)
-+ {
-+ pause();
-+ signal(SIGUSR1,do_pooling_child);
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:create child end
[%d@%s]",func,cluster_p->port,cluster_p->hostName);
-+#endif
-+ child_end(SIGTERM);
-+ }
-+ else
-+ {
-+ PGRadd_child_tbl(cluster_p,pid,TBL_INIT);
-+ }
-+ return pid;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRscan_child_tbl()
-+ * NOTES
-+ * get a child process id that is waiting for connection
-+ * with the cluster server
-+ * ARGS
-+ * ClusterTbl * ptr: pointer of cluster server table (I)
-+ * RETURN
-+ * OK: child process id
-+ * NG: 0
-+ *--------------------------------------------------------------------
-+ */
-+pid_t
-+PGRscan_child_tbl(ClusterTbl * cluster_p)
-+{
-+ char * func = "PGRscan_child_tbl()";
-+ ChildTbl * p;
-+
-+ if ( cluster_p == NULL)
-+ {
-+ show_error("%s:Cluster_Tbl is not initialize",func);
-+ return STATUS_ERROR;
-+ }
-+ p = Child_Tbl;
-+ if ( p == NULL)
-+ {
-+ show_error("%s:Child_Tbl is not initialize",func);
-+ return STATUS_ERROR;
-+ }
-+ while(p->useFlag != TBL_END)
-+ {
-+ if (p->pid <= 0)
-+ {
-+ p++;
-+ continue;
-+ }
-+ if ((p->useFlag == TBL_INIT) &&
-+ (p->rec_no == cluster_p->rec_no))
-+ {
-+ p->useFlag = TBL_USE;
-+ return (p->pid);
-+ }
-+ p++;
-+ }
-+ return 0;
-+}
-+
-+/* notice backend connection error using SIGUSR2 */
-+void
-+notice_backend_error(void)
-+{
-+ pid_t pid = getpid();
-+
-+ PGRset_status_to_child_tbl(pid,TBL_ERROR);
-+ PGRset_status_on_cluster_tbl(TBL_ERROR_NOTICE,CurrentCluster);
-+
-+ /*
-+ kill(parent, SIGUSR2);
-+ sleep(1);
-+ */
-+}
-+
-+
-+/*
-+ * start up pooling child process
-+ */
-+void
-+do_pooling_child(int sig)
-+{
-+ char * func = "do_pooling_child()";
-+ int rtn;
-+ pid_t pid;
-+
-+ pid = getpid();
-+ rtn = PGRdo_child(USE_CONNECTION_POOL);
-+ PGRrelease_connection(CurrentCluster);
-+ if (rtn != STATUS_OK)
-+ {
-+ show_error("%s:PGRdo_child failed",func);
-+ child_end(SIGTERM);
-+ }
-+ return ;
-+}
-+
-+/*
-+ * set status in child process table
-+ */
-+int
-+PGRset_status_to_child_tbl(pid_t pid, int status)
-+{
-+ char * func = "PGRset_status_to_child_tbl()";
-+ ChildTbl * p;
-+
-+ p = Child_Tbl;
-+ if ( p == NULL)
-+ {
-+ show_error("%s:Child_Tbl is not initialize",func);
-+ return STATUS_ERROR;
-+ }
-+ while(p->useFlag != TBL_END)
-+ {
-+ if (p->pid == pid)
-+ {
-+ p->useFlag = status;
-+ return STATUS_OK;
-+ }
-+ p++;
-+ }
-+ return STATUS_ERROR;
-+}
-+
-+/*
-+ * add child process data in child process table
-+ */
-+int
-+PGRadd_child_tbl(ClusterTbl * cluster_p, pid_t pid, int status)
-+{
-+ char * func = "PGRadd_child_tbl()";
-+ ChildTbl * p;
-+
-+ p = Child_Tbl;
-+ if ( cluster_p == NULL)
-+ {
-+ show_error("%s:Cluster_Tbl is not initialize",func);
-+ return STATUS_ERROR;
-+ }
-+ if ( p == NULL)
-+ {
-+ show_error("%s:Child_Tbl is not initialize",func);
-+ return STATUS_ERROR;
-+ }
-+ while(p->useFlag != TBL_END)
-+ {
-+ if ((p->useFlag == TBL_FREE) ||
-+ (p->useFlag == TBL_ERROR))
-+ {
-+ p->useFlag = status;
-+ p->rec_no = cluster_p->rec_no;
-+ p->pid = pid;
-+ return STATUS_OK;
-+ }
-+ p++;
-+ }
-+ return STATUS_ERROR;
-+}
-+
-+int
-+PGRget_child_status(pid_t pid)
-+{
-+ char * func = "PGRget_child_status()";
-+ ChildTbl * p;
-+
-+ p = Child_Tbl;
-+ if ( p == NULL)
-+ {
-+ show_error("%s:Child_Tbl is not initialize",func);
-+ return STATUS_ERROR;
-+ }
-+
-+ while (p->useFlag != TBL_END)
-+ {
-+ if (p->pid == pid)
-+ {
-+ return p->useFlag;
-+ }
-+ p++;
-+ }
-+ return STATUS_ERROR;
-+}
-+
-+void
-+PGRreturn_connection_full_error(void)
-+{
-+ PGRreturn_with_error( "Sorry, backend connection is full\n");
-+}
-+
-+void
-+PGRreturn_no_connection_error(void) {
-+ PGRreturn_with_error("pglb could not connect to server: no cluster
available.\n");
-+}
-+
-+static void
-+PGRreturn_with_error (char *msg)
-+{
-+ PGR_StartupPacket *sp = NULL;
-+ POOL_CONNECTION *frontend = NULL;
-+
-+
-+ /* perform accept() */
-+ frontend = do_accept(Frontend_FD.unix_fd,Frontend_FD.inet_fd);
-+ if (frontend == NULL)
-+ {
-+ /* accept() failed. return to the accept() loop */
-+ return ;
-+ }
-+ sp = read_startup_packet(frontend);
-+ if (sp == NULL)
-+ {
-+ /* failed to read the startup packet. return to the
-+ accept() loop */
-+ pool_close(frontend);
-+ return ;
-+ }
-+ pool_write_and_flush(frontend, "E", 1);
-+ pool_write_and_flush(frontend, msg, strlen(msg)+1);
-+ pool_close(frontend);
-+ return ;
-+}
-+
-+void
-+PGRquit_children_on_cluster(int rec_no)
-+{
-+ char * func = "PGRquit_children_on_cluster()";
-+ ChildTbl * p;
-+
-+ if (Child_Tbl == NULL)
-+ {
-+ return;
-+ }
-+ signal(SIGCHLD,SIG_IGN);
-+ p = Child_Tbl;
-+ while(p->useFlag != TBL_END)
-+ {
-+ if (p->rec_no == rec_no)
-+ {
-+ if (kill (p->pid,SIGTERM) == -1)
-+ {
-+ show_error("%s:could not stop pid: %d
(%s)",func,p->pid,strerror(errno));
-+ return;
-+ }
-+ PGRchild_wait(SIGTERM);
-+ p->useFlag = DATA_FREE;
-+ }
-+ p++;
-+ }
-+ if (Use_Connection_Pool)
-+ {
-+ signal(SIGCHLD,PGRrecreate_child);
-+ }
-+ else
-+ {
-+ signal(SIGCHLD,PGRchild_wait);
-+ }
-+}
-+
-+/* -------------------------------------------------------------------
-+ * private functions
-+ * -------------------------------------------------------------------
-+ */
-+
-+#ifdef NONE_BLOCK
-+/*
-+ * set non-block flag
-+ */
-+static void set_nonblock(int fd)
-+{
-+ char* func = "set_nonblock()";
-+ int var;
-+
-+ /* set fd to none blocking */
-+ var = fcntl(fd, F_GETFL, 0);
-+ if (var == -1)
-+ {
-+ show_error("%s:fcntl failed. %s", func,strerror(errno));
-+ child_end(SIGTERM);
-+ }
-+ if (fcntl(fd, F_SETFL, var | O_NONBLOCK) == -1)
-+ {
-+ show_error("%s:fcntl failed. %s", func,strerror(errno));
-+ child_end(SIGTERM);
-+ }
-+}
-+#endif
-+
-+/*
-+ * unset non-block flag
-+ */
-+static void unset_nonblock(int fd)
-+{
-+ char * func = "unset_nonblock()";
-+ int var;
-+
-+ /* set fd to none blocking */
-+ var = fcntl(fd, F_GETFL, 0);
-+ if (var == -1)
-+ {
-+ show_error("%s,fcntl failed. %s", func,strerror(errno));
-+ child_end(SIGTERM);
-+ }
-+ if (fcntl(fd, F_SETFL, var & ~O_NONBLOCK) == -1)
-+ {
-+ show_error("%s,fcntl failed. %s", func,strerror(errno));
-+ child_end(SIGTERM);
-+ }
-+}
-+
-+
-+/*
-+* perform accept() and returns new fd
-+*/
-+static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd)
-+{
-+ char * func = "do_accept()";
-+ fd_set readmask;
-+ int fds;
-+ struct sockaddr addr;
-+ socklen_t addrlen;
-+ int fd = 0;
-+ int afd;
-+ int inet = 0;
-+ POOL_CONNECTION *cp;
-+#ifdef ACCEPT_PERFORMANCE
-+ struct timeval now1, now2;
-+ static long atime;
-+ static int cnt;
-+#endif
-+
-+ FD_ZERO(&readmask);
-+ FD_SET(unix_fd, &readmask);
-+ if (inet_fd)
-+ FD_SET(inet_fd, &readmask);
-+
-+ fds = select(Max(unix_fd, inet_fd)+1, &readmask, NULL, NULL, NULL);
-+ if (fds == -1)
-+ {
-+ if (errno == EAGAIN || errno == EINTR)
-+ return NULL;
-+
-+ show_error("%s:select() failed. reason %s",func,
strerror(errno));
-+ return NULL;
-+ }
-+
-+ if (fds == 0)
-+ return NULL;
-+
-+ if (FD_ISSET(unix_fd, &readmask))
-+ {
-+ fd = unix_fd;
-+ }
-+
-+ if (FD_ISSET(inet_fd, &readmask))
-+ {
-+ fd = inet_fd;
-+ inet++;
-+ }
-+
-+ /*
-+ * Note that some SysV systems do not work here. For those
-+ * systems, we need some locking mechanism for the fd.
-+ */
-+ addrlen = sizeof(addr);
-+
-+#ifdef ACCEPT_PERFORMANCE
-+ gettimeofday(&now1,0);
-+#endif
-+ afd = accept(fd, &addr, &addrlen);
-+ if (afd < 0)
-+ {
-+ /*
-+ * "Resource temporarily unavailable" (EAGAIN or EWOULDBLOCK)
-+ * can be silently ignored.
-+ */
-+ if (errno != EAGAIN && errno != EWOULDBLOCK)
-+ show_error("%s:accept() failed. reason: %s",func,
strerror(errno));
-+ return NULL;
-+ }
-+#ifdef ACCEPT_PERFORMANCE
-+ gettimeofday(&now2,0);
-+ atime += (now2.tv_sec - now1.tv_sec)*1000000 + (now2.tv_usec -
now1.tv_usec);
-+ cnt++;
-+ if (cnt % 100 == 0)
-+ {
-+ show_error("%s:cnt: %d atime: %ld",func, cnt, atime);
-+ }
-+#endif
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:I am %d accept fd %d",func, getpid(), afd);
-+#endif
-+
-+ /* set NODELAY and KEEPALIVE options if INET connection */
-+ if (inet)
-+ {
-+ int on = 1;
-+
-+ if (setsockopt(afd, IPPROTO_TCP, TCP_NODELAY,
-+ (char *) &on,
-+ sizeof(on)) < 0)
-+ {
-+ show_error("%s:do_accept: setsockopt() failed:
%s",func, strerror(errno));
-+ close(afd);
-+ return NULL;
-+ }
-+ if (setsockopt(afd, SOL_SOCKET, SO_KEEPALIVE,
-+ (char *) &on,
-+ sizeof(on)) < 0)
-+ {
-+ show_error("%s:do_accept: setsockopt() failed: %s",
func,strerror(errno));
-+ close(afd);
-+ return NULL;
-+ }
-+ }
-+
-+ if ((cp = pool_open(afd)) == NULL)
-+ {
-+ close(afd);
-+ return NULL;
-+ }
-+ return cp;
-+}
-+
-+/*
-+* read startup packet
-+*/
-+static PGR_StartupPacket *read_startup_packet(POOL_CONNECTION *cp)
-+{
-+ char * func = "read_startup_packet()";
-+ PGR_StartupPacket *sp;
-+ PGR_StartupPacket_v2 *sp2;
-+ int protov;
-+ int len;
-+ char *p;
-+
-+ sp = (PGR_StartupPacket *)malloc(sizeof(PGR_StartupPacket));
-+ if (!sp)
-+ {
-+ show_error("%s:read_startup_packet: out of memory",func);
-+ return NULL;
-+ }
-+
-+ /* read startup packet length */
-+ if (pool_read(cp, &len, sizeof(len)))
-+ {
-+ free(sp);
-+ return NULL;
-+ }
-+ len = ntohl(len);
-+ len -= sizeof(len);
-+
-+ if (len <= 0)
-+ {
-+ show_error("%s:read_startup_packet: incorrect packet length
(%d)", func,len);
-+ free(sp);
-+ return NULL;
-+ }
-+
-+ sp->startup_packet = calloc(len, 1);
-+ if (!sp->startup_packet)
-+ {
-+ show_error("%s:read_startup_packet: out of memory",func);
-+ free(sp);
-+ return NULL;
-+ }
-+
-+ /* read startup packet */
-+ if (pool_read(cp, sp->startup_packet, len))
-+ {
-+ free(sp);
-+ return NULL;
-+ }
-+
-+ sp->len = len;
-+ memcpy(&protov, sp->startup_packet, sizeof(protov));
-+ sp->major = ntohl(protov)>>16;
-+ sp->minor = ntohl(protov) & 0x0000ffff;
-+ p = sp->startup_packet;
-+
-+ switch(sp->major)
-+ {
-+ case PROTO_MAJOR_V2: /* V2 */
-+ sp2 = (PGR_StartupPacket_v2 *)(sp->startup_packet);
-+
-+ sp->database = calloc(SM_DATABASE+1, 1);
-+ if (!sp->database)
-+ {
-+ show_error("%s:read_startup_packet: out of
memory",func);
-+ free(sp);
-+ return NULL;
-+ }
-+ strncpy(sp->database, sp2->database, SM_DATABASE);
-+
-+ sp->user = calloc(SM_USER+1, 1);
-+ if (!sp->user)
-+ {
-+ show_error("%s:read_startup_packet: out of
memory",func);
-+ free(sp);
-+ return NULL;
-+ }
-+ strncpy(sp->user, sp2->user, SM_USER);
-+
-+ break;
-+
-+ case PROTO_MAJOR_V3: /* V3 */
-+ p += sizeof(int); /* skip protocol version info
*/
-+
-+ while(*p)
-+ {
-+ if (!strcmp("user", p))
-+ {
-+ p += (strlen(p) + 1);
-+ sp->user = strdup(p);
-+ if (!sp->user)
-+ {
-+
show_error("%s:read_startup_packet: out of memory",func);
-+ free(sp);
-+ return NULL;
-+ }
-+ }
-+ else if (!strcmp("database", p))
-+ {
-+ p += (strlen(p) + 1);
-+ sp->database = strdup(p);
-+ if (!sp->database)
-+ {
-+
show_error("%s:read_startup_packet: out of memory",func);
-+ free(sp);
-+ return NULL;
-+ }
-+ }
-+ p += (strlen(p) + 1);
-+ }
-+ break;
-+
-+ case 1234: /* cancel or SSL request */
-+ /* set dummy database, user info */
-+ sp->database = calloc(1, 1);
-+ if (!sp->database)
-+ {
-+ show_error("%s:read_startup_packet: out of
memory",func);
-+ free(sp);
-+ return NULL;
-+ }
-+ sp->user = calloc(1, 1);
-+ if (!sp->user)
-+ {
-+ show_error("%s:read_startup_packet: out of
memory",func);
-+ free(sp);
-+ return NULL;
-+ }
-+ break;
-+
-+ default:
-+ show_error("%s:read_startup_packet: invalid major no:
%d",func, sp->major);
-+ free(sp);
-+ return NULL;
-+ }
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:Protocol Major: %d Minor: %d database: %s user: %s",
-+ func,sp->major, sp->minor, sp->database, sp->user);
-+#endif
-+
-+ return sp;
-+}
-+
-+/*
-+* send startup packet
-+*/
-+static int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp)
-+{
-+ int len;
-+
-+ len = htonl(cp->sp->len + sizeof(len));
-+ pool_write(cp->con, &len, sizeof(len));
-+ return pool_write_and_flush(cp->con, cp->sp->startup_packet,
cp->sp->len);
-+}
-+
-+/*
-+ * process cancel request
-+ */
-+static void cancel_request(CancelPacket *sp, int secondary_backend)
-+{
-+ char * func = "cancel_request()";
-+ int len;
-+ int fd;
-+ POOL_CONNECTION *con;
-+ char hostName[128];
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:Cancel request received",func);
-+#endif
-+
-+ if (CurrentCluster == NULL)
-+ {
-+ return;
-+ }
-+ if (gethostname(hostName,sizeof(hostName)) < 0)
-+ {
-+ show_error("%s:gethostname() failed.
(%s)",func,strerror(errno));
-+ return ;
-+ }
-+ if (secondary_backend)
-+ {
-+ if (PGRis_same_host(hostName,CurrentCluster->hostName))
-+ fd = connect_unix_domain_socket(1);
-+ else
-+ fd = connect_inet_domain_socket(1);
-+ }
-+ else
-+ {
-+ if (PGRis_same_host(hostName,CurrentCluster->hostName))
-+ fd = connect_unix_domain_socket(0);
-+ else
-+ fd = connect_inet_domain_socket(0);
-+ }
-+
-+ if (fd < 0)
-+ {
-+ show_error("%s:Could not create socket for sending cancel
request",func);
-+ return;
-+ }
-+
-+ con = pool_open(fd);
-+ if (con == NULL)
-+ return;
-+
-+ len = htonl(sizeof(len) + sizeof(CancelPacket));
-+ pool_write(con, &len, sizeof(len));
-+
-+ if (pool_write_and_flush(con, sp, sizeof(CancelPacket)) < 0)
-+ show_error("%s:Could not send cancel request packet",func);
-+ pool_close(con);
-+}
-+
-+static POOL_CONNECTION_POOL *connect_backend(PGR_StartupPacket *sp,
POOL_CONNECTION *frontend)
-+{
-+ char * func ="connect_backend()";
-+ POOL_CONNECTION_POOL *backend;
-+
-+ /* connect to the backend */
-+ backend = pool_create_cp();
-+ if (backend == NULL)
-+ {
-+ pool_send_error_message(frontend, sp->major, "XX000",
"connection cache is full", "",
-+ "increace
max_pool", __FILE__, __LINE__);
-+ pool_close(frontend);
-+ return NULL;
-+ }
-+
-+ /* mark this is a backend connection */
-+ backend->slots[0]->con->isbackend = 1;
-+ /*
-+ * save startup packet info
-+ */
-+ backend->slots[0]->sp = sp;
-+
-+ if (pool_config_replication_enabled)
-+ {
-+ backend->slots[1]->con->isbackend = 1;
-+ backend->slots[1]->con->issecondary_backend = 1;
-+ /*
-+ * save startup packet info
-+ */
-+ backend->slots[1]->sp = sp;
-+ }
-+
-+ /* send startup packet */
-+ if (send_startup_packet(backend->slots[0]) < 0)
-+ {
-+ show_error("%s:do_child: fails to send startup packet to the
backend",func);
-+ pool_close(frontend);
-+ return NULL;
-+ }
-+
-+ /* send startup packet */
-+ if (pool_config_replication_enabled)
-+ {
-+ if (send_startup_packet(backend->slots[1]) < 0)
-+ {
-+ show_error("%s:do_child: fails to send startup packet
to the secondary backend",func);
-+ pool_close(frontend);
-+ return NULL;
-+ }
-+ }
-+
-+ /*
-+ * do authentication stuff
-+ */
-+ if (pool_do_auth(frontend, backend))
-+ {
-+ pool_close(frontend);
-+ pool_discard_cp(sp->user, sp->database, sp->major);
-+ return NULL;
-+ }
-+ return backend;
-+}
-+
-+static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*backend)
-+{
-+ char * func = "send_params()";
-+ int index;
-+ char *name, *value;
-+ int len, sendlen;
-+
-+ index = 0;
-+ while (pool_get_param(&MASTER(backend)->params, index++, &name,
&value) == 0)
-+ {
-+ pool_write(frontend, "S", 1);
-+ len = sizeof(sendlen) + strlen(name) + 1 + strlen(value) + 1;
-+ sendlen = htonl(len);
-+ pool_write(frontend, &sendlen, sizeof(sendlen));
-+ pool_write(frontend, name, strlen(name) + 1);
-+ pool_write(frontend, value, strlen(value) + 1);
-+ }
-+
-+ if (pool_flush(frontend))
-+ {
-+ show_error("%s:pool_send_params: pool_flush() failed",func);
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * ending function of child process
-+ */
-+static void
-+child_end(int sig)
-+{
-+ signal(sig,SIG_IGN);
-+
-+ pool_finish();
-+ exit(0);
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/cluster_table.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/cluster_table.c
---- postgresql-8.1.2/src/pgcluster/pglb/cluster_table.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/cluster_table.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,338 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * cluster_tbl.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to use a cluster table.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 <stdarg.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <sys/time.h>
-+#include <ctype.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <sys/sem.h>
-+#include <sys/msg.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <sys/param.h>
-+#include <sys/select.h>
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+int PGRis_cluster_alive(void) ;
-+ClusterTbl * PGRscan_cluster(void);
-+void PGRset_key_of_cluster(ClusterTbl * ptr, RecoveryPacket * packet);
-+ClusterTbl * PGRadd_cluster_tbl (ClusterTbl * conf_data);
-+ClusterTbl * PGRset_status_on_cluster_tbl (int status, ClusterTbl * ptr);
-+ClusterTbl * PGRsearch_cluster_tbl(ClusterTbl * conf_data);
-+
-+static int set_cluster_tbl(ClusterTbl * ptr , ClusterTbl * conf_data);
-+static ClusterTbl * search_free_cluster_tbl(void );
-+static void write_cluster_status_file(ClusterTbl * ptr);
-+
-+int PGRis_cluster_alive(void)
-+{
-+ ClusterTbl * ptr = NULL;
-+ int use=0;
-+ ptr = Cluster_Tbl;
-+
-+ PGRsem_lock(ClusterSemid,MAX_DB_SERVER);
-+ while (ptr->useFlag != TBL_END)
-+ {
-+ if (ptr->useFlag == TBL_USE)
-+ {
-+ use++;
-+ }
-+ ptr++;
-+ }
-+ PGRsem_unlock(ClusterSemid,MAX_DB_SERVER);
-+ return use==0 ? STATUS_ERROR : STATUS_OK;
-+}
-+
-+ClusterTbl *
-+PGRscan_cluster(void)
-+{
-+ char * func = "PGRscan_cluster";
-+ ClusterTbl * ptr = NULL;
-+ ClusterTbl * rtn = NULL;
-+ int min_use_rate = 100;
-+ int use_rate = 0;
-+ int cnt = 0;
-+
-+
-+ ptr = Cluster_Tbl;
-+ if (ptr == NULL)
-+ {
-+ show_error("%s:Cluster Table is not initialize",func);
-+ return (ClusterTbl *)NULL;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:%d ClusterDB can be used",func,ClusterNum);
-+#endif
-+ PGRsem_lock(ClusterSemid,MAX_DB_SERVER);
-+ while ((cnt <= ClusterNum) && (ptr->useFlag != TBL_END))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:%s [%d],useFlag->%d max->%d use_num->%d\n",
-+ func,
ptr->hostName,ptr->port,ptr->useFlag,ptr->max_connect,ptr->use_num);
-+#endif
-+ cnt ++;
-+ if (ptr->useFlag != TBL_USE)
-+ {
-+ ptr ++;
-+ continue;
-+ }
-+ if (ptr->max_connect <= ptr->use_num)
-+ {
-+ ptr ++;
-+ continue;
-+ }
-+ if (ptr->use_num > 0)
-+ {
-+ use_rate = ptr->use_num * 100 / ptr->max_connect ;
-+ }
-+ else
-+ {
-+ use_rate = 0;
-+ rtn = ptr;
-+ break;
-+ }
-+ if (min_use_rate > use_rate)
-+ {
-+ min_use_rate = use_rate;
-+ rtn = ptr;
-+ }
-+ ptr ++;
-+ }
-+ if (rtn != NULL)
-+ {
-+ rtn->use_num ++;
-+ }
-+ PGRsem_unlock(ClusterSemid,MAX_DB_SERVER);
-+ return rtn;
-+}
-+
-+void
-+PGRset_key_of_cluster(ClusterTbl * ptr, RecoveryPacket * packet)
-+{
-+ int max_connect = 0;
-+ int port = 0;
-+
-+ memset(ptr,0,sizeof(ClusterTbl));
-+ memcpy(ptr->hostName,packet->hostName,sizeof(ptr->hostName));
-+ max_connect = ntohs(packet->max_connect);
-+ if (max_connect >= 0)
-+ {
-+ ptr->max_connect = max_connect;
-+ }
-+ else
-+ {
-+ ptr->max_connect = DEFAULT_CONNECT_NUM;
-+ }
-+ port = ntohs(packet->port);
-+ if ( port >= 0)
-+ {
-+ ptr->port = port;
-+ }
-+ else
-+ {
-+ ptr->port = DEFAULT_PORT;
-+ }
-+}
-+
-+ClusterTbl *
-+PGRadd_cluster_tbl (ClusterTbl * conf_data)
-+{
-+ char * func = "PGRadd_cluster_tbl()";
-+ ClusterTbl * ptr;
-+
-+ ptr = PGRsearch_cluster_tbl(conf_data);
-+ if ((ptr != NULL) && (ptr->useFlag == TBL_USE ))
-+ {
-+ ptr->max_connect = conf_data->max_connect;
-+ ptr->use_num = 0;
-+ ptr->rate = 0;
-+ return ptr;
-+ }
-+ ptr = search_free_cluster_tbl();
-+ if (ptr == (ClusterTbl *) NULL)
-+ {
-+ show_error("%s:no more free space in cluster table",func);
-+ return (ClusterTbl *)NULL;
-+ }
-+ if (ClusterNum < Max_DB_Server)
-+ {
-+ set_cluster_tbl( ptr, conf_data);
-+ return ptr;
-+ }
-+ return (ClusterTbl *)NULL;
-+}
-+
-+ClusterTbl *
-+PGRset_status_on_cluster_tbl (int status, ClusterTbl * ptr)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "PGRset_status_on_cluster_tbl()";
-+#endif
-+
-+ if (ptr != (ClusterTbl*)NULL)
-+ {
-+ if (ptr->useFlag != status)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:host:%s port:%d max:%d use:%d
status%d",
-+ func,
ptr->hostName,ptr->port,ptr->max_connect,ptr->useFlag,status);
-+#endif
-+ ptr->useFlag = status;
-+ write_cluster_status_file(ptr);
-+ if (status == TBL_USE)
-+ {
-+ if (ClusterNum < Max_DB_Server)
-+ ClusterNum ++ ;
-+ }
-+ else if (status != TBL_STOP)
-+ {
-+ if (ClusterNum > 0)
-+ ClusterNum -- ;
-+ }
-+ }
-+ }
-+ return ptr;
-+}
-+
-+static void
-+write_cluster_status_file(ClusterTbl * ptr)
-+{
-+ switch( ptr->useFlag)
-+ {
-+ case TBL_FREE:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s free",
-+ ptr->port,
-+ ptr->hostName);
-+ break;
-+ case TBL_INIT:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s
initialize",
-+ ptr->port,
-+ ptr->hostName);
-+ break;
-+ case TBL_USE:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s start
use",
-+ ptr->port,
-+ ptr->hostName);
-+ break;
-+ case TBL_ERROR:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s error",
-+ ptr->port,
-+ ptr->hostName);
-+ break;
-+ case TBL_END:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s end",
-+ ptr->port,
-+ ptr->hostName);
-+ break;
-+ }
-+}
-+
-+ClusterTbl *
-+PGRsearch_cluster_tbl(ClusterTbl * conf_data)
-+{
-+ ClusterTbl *ptr;
-+ int cnt = 0;
-+ int rec_num = 0;
-+
-+ ptr = Cluster_Tbl;
-+ while ((cnt <= ClusterNum) && (rec_num < Max_DB_Server))
-+ {
-+ if (ptr->port > 0)
-+ {
-+ if ((!strcmp(ptr->hostName,conf_data->hostName)) &&
-+ (ptr->port == conf_data->port))
-+ {
-+ return ptr;
-+ }
-+ if (ptr->useFlag == TBL_USE)
-+ {
-+ cnt ++;
-+ }
-+ }
-+ ptr ++;
-+ rec_num ++;
-+ }
-+ return (ClusterTbl *)NULL;
-+}
-+
-+static int
-+set_cluster_tbl(ClusterTbl * ptr , ClusterTbl * conf_data)
-+{
-+ int rec_no;
-+
-+ rec_no = ptr->rec_no;
-+ memcpy(ptr->hostName,conf_data->hostName,sizeof(ptr->hostName));
-+ ptr->max_connect = conf_data->max_connect;
-+ ptr->port = conf_data->port;
-+ ptr->use_num = conf_data->use_num;
-+ ptr->rate = conf_data->rate;
-+ PGRset_status_on_cluster_tbl (TBL_USE, ptr);
-+
-+ return STATUS_OK;
-+}
-+
-+static ClusterTbl *
-+search_free_cluster_tbl(void )
-+{
-+ ClusterTbl *ptr;
-+ int cnt = 0;
-+
-+ ptr = Cluster_Tbl;
-+ while ((cnt <= ClusterNum ) && (cnt < Max_DB_Server))
-+ {
-+ if (ptr->useFlag != TBL_USE)
-+ {
-+ return ptr;
-+ }
-+ cnt ++;
-+ ptr ++;
-+ }
-+ return (ClusterTbl *)NULL;
-+}
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/load_balance.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/load_balance.c
---- postgresql-8.1.2/src/pgcluster/pglb/load_balance.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/load_balance.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,252 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * load_balance.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions of load balance modules
-+ * with connection pooling or not
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 "postgres.h"
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <sys/time.h>
-+#include <ctype.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/sem.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <sys/param.h>
-+#include <sys/select.h>
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+int PGRload_balance(void);
-+int PGRload_balance_with_pool(void);
-+char PGRis_connection_full(ClusterTbl * ptr);
-+void PGRrelease_connection(ClusterTbl * ptr);
-+void PGRchild_wait(int sig);
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRload_balance()
-+ * NOTES
-+ * load balance module that normal connection is used
-+ * ARGS
-+ * void
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGRload_balance(void)
-+{
-+ char * func = "PGRload_balance()";
-+ pid_t pid,pgid;
-+ int count;
-+ int status;
-+ ClusterTbl * cluster_p = NULL;
-+
-+ signal(SIGCHLD, PGRchild_wait);
-+ /* get the least locaded cluster server info */
-+ cluster_p = PGRscan_cluster();
-+ count = 0;
-+ while (cluster_p == NULL )
-+ {
-+ if ( count > PGLB_CONNECT_RETRY_TIME)
-+ {
-+ show_error("%s:no cluster available",func);
-+ return STATUS_ERROR;
-+ }
-+ cluster_p = PGRscan_cluster();
-+ count ++;
-+ }
-+
-+ pgid = getpgid((pid_t)0);
-+ pid = fork();
-+ if (pid < 0)
-+ {
-+ show_error("%s:fork() failed. (%s)",func,strerror(errno));
-+ exit(1);
-+ }
-+ if (pid == 0)
-+ {
-+ setpgid((pid_t)0,pgid);
-+ CurrentCluster = cluster_p;
-+
-+ if (pool_init_cp())
-+ {
-+ show_error("%s:pool_init_cp failed",func);
-+ exit(1);
-+ }
-+ PGRsem_lock(ClusterSemid,cluster_p->rec_no);
-+ if (PGRget_child_status(getpid()) == STATUS_ERROR)
-+ {
-+ PGRadd_child_tbl(cluster_p, getpid(), TBL_USE);
-+ }
-+ PGRsem_unlock(ClusterSemid,cluster_p->rec_no);
-+ PGRdo_child(NOT_USE_CONNECTION_POOL );
-+ PGRrelease_connection(cluster_p);
-+ PGRset_status_to_child_tbl(getpid(), TBL_FREE);
-+ exit(0);
-+ }
-+ else if (pid > 0)
-+ {
-+ PGRsem_lock(ClusterSemid,cluster_p->rec_no);
-+ if (PGRget_child_status(pid) == STATUS_ERROR)
-+ {
-+ PGRadd_child_tbl(cluster_p, pid, TBL_USE);
-+ }
-+ PGRsem_unlock(ClusterSemid,cluster_p->rec_no);
-+ status = PGRget_child_status(pid);
-+ while (status == TBL_USE)
-+ {
-+ status = PGRget_child_status(pid);
-+ usleep(20);
-+ }
-+ return STATUS_OK;
-+ }
-+ else
-+ {
-+ return STATUS_ERROR;
-+ }
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRload_balance_with_pool()
-+ * NOTES
-+ * load balance module that connection pooling system is used
-+ * ARGS
-+ * void
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGRload_balance_with_pool(void)
-+{
-+ char * func = "PGRload_balance_with_pool()";
-+ int count;
-+ pid_t pid;
-+ ClusterTbl * cluster_p = NULL;
-+ int status = TBL_USE;
-+
-+ /* get the least locaded cluster server info */
-+ cluster_p = PGRscan_cluster();
-+ count = 0;
-+ while (cluster_p == NULL )
-+ {
-+ if ( count > PGLB_CONNECT_RETRY_TIME)
-+ {
-+ show_error("%s:no cluster available",func);
-+ PGRreturn_no_connection_error();
-+ return STATUS_ERROR;
-+ }
-+ cluster_p = PGRscan_cluster();
-+ count ++;
-+ }
-+ pid = PGRscan_child_tbl(cluster_p);
-+ if ((pid == 0) || (pid == STATUS_ERROR))
-+ {
-+ show_error("%s:no child process available",func);
-+ return STATUS_ERROR;
-+ }
-+ kill(pid,SIGUSR1);
-+
-+ status = PGRget_child_status(pid);
-+ while (status == TBL_USE)
-+ {
-+ status = PGRget_child_status(pid);
-+ usleep(20);
-+ }
-+
-+ return STATUS_OK;
-+
-+}
-+
-+char
-+PGRis_connection_full(ClusterTbl * ptr)
-+{
-+ char rtn = 1;
-+
-+ if (ptr == NULL)
-+ {
-+ return rtn;
-+ }
-+ PGRsem_lock(ClusterSemid,ptr->rec_no);
-+ if (ptr->max_connect > ptr->use_num)
-+ {
-+ rtn = 0;
-+ }
-+ PGRsem_unlock(ClusterSemid,ptr->rec_no);
-+ return rtn;
-+}
-+
-+void
-+PGRrelease_connection(ClusterTbl * ptr)
-+{
-+ if (ptr == NULL)
-+ {
-+ return;
-+ }
-+ PGRsem_lock(ClusterSemid,MAX_DB_SERVER);
-+ if (ptr->use_num > 0)
-+ {
-+ ptr->use_num --;
-+ }
-+ PGRsem_unlock(ClusterSemid,MAX_DB_SERVER);
-+}
-+
-+void
-+PGRchild_wait(int sig)
-+{
-+ pid_t pid = 0;
-+ int ret = 0;
-+
-+ do {
-+ pid = waitpid(-1,&ret,WNOHANG);
-+ if ((pid <= 0) && (WTERMSIG(ret) > 0))
-+ {
-+ pid = 1;
-+ }
-+ } while(pid > 0);
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/main.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/main.c
---- postgresql-8.1.2/src/pgcluster/pglb/main.c 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/main.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,1050 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * main.c
-+ *
-+ * NOTE:
-+ * This file is composed of the main function of pglb.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 "postgres.h"
-+#include <stdio.h>
-+#include <stdarg.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <sys/sem.h>
-+#include <sys/msg.h>
-+#include <netdb.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <sys/param.h>
-+#include <sys/select.h>
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+#include <arpa/inet.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+#ifdef HAVE_GETOPT_H
-+#include <getopt.h>
-+#endif
-+
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+
-+
-+#define IPC_NMAXSEM (32)
-+/*--------------------------------------
-+ * GLOBAL VARIABLE DECLARATION
-+ *--------------------------------------
-+ */
-+/* for replicate_com.h */
-+ConfDataType * ConfData_Top = (ConfDataType *)NULL;
-+ConfDataType * ConfData_End = (ConfDataType *)NULL;
-+int SynSemID = -1;
-+int MapTableShmid = -1;
-+int LifeCheckStartShmid = -1;
-+char * LifeCheckStartFlag = NULL;
-+int LifeCheckTimeOut = 10;
-+FILE * StatusFp = (FILE *)NULL;
-+FILE * LogFp = (FILE *)NULL;
-+char * PGRStatusFileName = NULL;
-+char * PGRLogFileName = NULL;
-+int Log_Print = 0;
-+int Debug_Print = 0;
-+
-+int Recv_Port_Number = 0;
-+int Recovery_Port_Number = 0;
-+uint16_t LifeCheck_Port_Number = 0;
-+int Use_Connection_Pool = 0;
-+int Max_Pool = 1;
-+int Connection_Life_Time = 0;
-+int Max_DB_Server = 0;
-+int MaxBackends = 0;
-+ClusterTbl * Cluster_Tbl = (ClusterTbl *)NULL;
-+int ClusterNum = 0;
-+int ClusterShmid = 0;
-+int ClusterSemid = 0;
-+ChildTbl * Child_Tbl = (ChildTbl *)NULL;
-+int ChildShmid = 0;
-+char * PGR_Data_Path = NULL;
-+char * PGR_Write_Path = NULL;
-+char * Backend_Socket_Dir = NULL;
-+FrontSocket Frontend_FD;
-+ClusterTbl * CurrentCluster = NULL;
-+
-+extern char *optarg;
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+int init_pglb(char * path);
-+static void pglb_exit(int signal_args);
-+static void load_balance_main(void);
-+static void daemonize(void);
-+static void write_pid_file(void);
-+static void stop_pglb(void);
-+static int is_exist_pid_file(void);
-+static ClusterTbl * scan_cluster_by_pid(pid_t pid);
-+static void usage(void);
-+static void close_child(int signal_args);
-+
-+void PGRrecreate_child(int signal_args);
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * init_pglb()
-+ * NOTES
-+ * Reading of the setup file
-+ * and the initialization of the memory area.
-+ * ARGS
-+ * char * path: path of the setup file (I)
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+init_pglb(char * path)
-+{
-+ char * func = "init_pglb()";
-+
-+ ConfDataType * conf;
-+ ClusterTbl cluster_tbl[MAX_DB_SERVER];
-+ int size = 0;
-+ int rec_no = 0;
-+ int i;
-+ int max_connect = 0;
-+ union semun sem_arg;
-+ char fname[256];
-+
-+ /*
-+ * read configuration file
-+ */
-+ if (path == NULL)
-+ {
-+ path = ".";
-+ }
-+ if (PGR_Get_Conf_Data(path,PGLB_CONF_FILE) != STATUS_OK)
-+ {
-+ show_error("%s:PGR_Get_Conf_Data failed",func);
-+ return STATUS_ERROR;
-+ }
-+
-+ /* cluster db status file open */
-+ if (PGRStatusFileName == NULL)
-+ {
-+
snprintf(fname,sizeof(fname),"%s/%s",PGR_Write_Path,PGLB_STATUS_FILE);
-+ }
-+ else
-+ {
-+ memcpy(fname,PGRStatusFileName,sizeof(fname));
-+ }
-+ StatusFp = fopen(fname, "a");
-+ if (StatusFp == NULL)
-+ {
-+ show_error("%s:open() %s file failed. (%s)",
-+ func,fname, strerror(errno));
-+ exit(1);
-+ }
-+ /* pglb log file open */
-+ if (Log_Print)
-+ {
-+ if (PGRLogFileName == NULL)
-+ {
-+
snprintf(fname,sizeof(fname),"%s/%s",PGR_Write_Path,PGLB_LOG_FILE);
-+ }
-+ else
-+ {
-+ memcpy(fname,PGRLogFileName,sizeof(fname));
-+ }
-+ LogFp = fopen(fname,"a");
-+ if (LogFp == NULL)
-+ {
-+ show_error("%s:fopen failed:
(%s)",func,strerror(errno));
-+ exit(1);
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:%s open ok",func,fname);
-+#endif
-+ }
-+
-+ Backend_Socket_Dir = malloc(128);
-+ if (Backend_Socket_Dir == NULL)
-+ {
-+ show_error("%s:malloc() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(Backend_Socket_Dir,0,128);
-+ /* set initiarize data */
-+ strcpy(Backend_Socket_Dir,"/tmp");
-+ Max_Pool = 1;
-+ Connection_Life_Time = 0;
-+ Use_Connection_Pool = 0;
-+
-+ conf = ConfData_Top;
-+ while (conf != (ConfDataType *)NULL)
-+ {
-+ /* get cluster db servers name */
-+ if (!strcmp(conf->table,CLUSTER_SERVER_TAG))
-+ {
-+ rec_no = conf->rec_no;
-+ if (!strcmp(conf->key,HOST_NAME_TAG))
-+ {
-+
memcpy(cluster_tbl[rec_no].hostName,conf->value,sizeof(cluster_tbl[rec_no].hostName));
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,PORT_TAG))
-+ {
-+ cluster_tbl[rec_no].port = atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,MAX_CONNECT_TAG))
-+ {
-+ cluster_tbl[rec_no].max_connect =
atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ }
-+ else
-+ {
-+ /* get port number for receive querys */
-+ if (!strcmp(conf->key,RECV_PORT_TAG))
-+ {
-+ Recv_Port_Number = atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ /* get port number for recovery session */
-+ if (!strcmp(conf->key,RECOVERY_PORT_TAG))
-+ {
-+ Recovery_Port_Number = atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ /*
-+ if (!STRCMP(conf->key,LIFECHECK_PORT_TAG))
-+ {
-+ LifeCheck_Port_Number = atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!STRCMP(conf->key,STATUS_LOG_FILE_TAG))
-+ {
-+ PGRStatusFileName = strdup(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!STRCMP(conf->key,ERROR_LOG_FILE_TAG))
-+ {
-+ PGRLogFileName = strdup(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ */
-+ if (!strcmp(conf->key,MAX_CLUSTER_TAG))
-+ {
-+ Max_DB_Server = atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,USE_CONNECTION_POOL_TAG))
-+ {
-+ if (!strcmp(conf->value,"yes"))
-+ {
-+ Use_Connection_Pool = 1;
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,MAX_POOL_TAG))
-+ {
-+ Max_Pool = atoi(conf->value);
-+ if (Max_Pool < 0)
-+ Max_Pool = 1;
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,CONNECTION_LIFE_TIME))
-+ {
-+ Connection_Life_Time = atoi(conf->value);
-+ if (Connection_Life_Time < 0)
-+ Connection_Life_Time = 0;
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,BACKEND_SOCKET_DIR_TAG))
-+ {
-+ strncpy(Backend_Socket_Dir,conf->value,128);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ }
-+ if (Max_DB_Server <= 0)
-+ {
-+ show_error("%s:Max_DB_Server is wrong value. %s/%s file
should be broken",func, path, PGLB_CONF_FILE);
-+ exit(1);
-+ }
-+ /* shared memory allocation for cluster table */
-+ size = sizeof(ClusterTbl) * Max_DB_Server;
-+
-+ ClusterShmid = shmget(IPC_PRIVATE,size,IPC_CREAT | IPC_EXCL | 0600);
-+ if (ClusterShmid < 0)
-+ {
-+ show_error("%s:ClusterShm shmget() failed. (%s)",
func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ Cluster_Tbl = (ClusterTbl *)shmat(ClusterShmid,0,0);
-+ if (Cluster_Tbl == (ClusterTbl *)-1)
-+ {
-+ show_error("%s:shmat() failed. (%s)", func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ if ((ClusterSemid = semget(IPC_PRIVATE,MAX_DB_SERVER+1,IPC_CREAT |
IPC_EXCL | 0600)) < 0)
-+ {
-+ show_error("%s:semget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ for ( i = 0 ; i <= MAX_DB_SERVER ; i ++)
-+ {
-+ semctl(ClusterSemid, i, GETVAL, sem_arg);
-+ sem_arg.val = 1;
-+ semctl(ClusterSemid, i, SETVAL, sem_arg);
-+ }
-+ ClusterNum = 0;
-+ /* set cluster db server name into cluster db server table */
-+ for ( i = 0 ; i < Max_DB_Server ; i ++)
-+ {
-+ (Cluster_Tbl + i)->rec_no = i;
-+ }
-+ (Cluster_Tbl + i)->useFlag = TBL_END;
-+ max_connect = 0;
-+ for ( i = 0 ; i <= rec_no ; i ++)
-+ {
-+ cluster_tbl[i].use_num = 0;
-+ cluster_tbl[i].rate = 0;
-+ if (cluster_tbl[i].max_connect < 0)
-+ {
-+ cluster_tbl[i].max_connect = 0;
-+ }
-+ if (max_connect < cluster_tbl[i].max_connect)
-+ {
-+ max_connect = cluster_tbl[i].max_connect;
-+ }
-+ PGRadd_cluster_tbl(&cluster_tbl[i]);
-+ }
-+
-+ /* shared memory allocation for children table */
-+ size = sizeof(ChildTbl) * (Max_DB_Server + 1) * max_connect *
Max_Pool;
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:Child_Tbl size is[%d]",func,size);
-+#endif
-+
-+ ChildShmid = shmget(IPC_PRIVATE,size,IPC_CREAT | IPC_EXCL | 0600);
-+ if (ChildShmid < 0)
-+ {
-+ show_error("%s:ChildShm shmget() failed. (%s)",func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ Child_Tbl = (ChildTbl *)shmat(ChildShmid,0,0);
-+ if (Child_Tbl == (ChildTbl *)-1)
-+ {
-+ show_error("%s:shmat() failed. (%s)", func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(Child_Tbl, 0, size);
-+ (Child_Tbl + ( Max_DB_Server * max_connect * Max_Pool) -1)->useFlag =
TBL_END;
-+
-+ PGR_Free_Conf_Data();
-+
-+ return STATUS_OK;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * pglb_exit()
-+ * NOTES
-+ * Closing of pglb process
-+ * ARGS
-+ * int signal_args: signal number (I)
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+pglb_exit(int signal_args)
-+{
-+ char fname[256];
-+ int rtn;
-+
-+ Child_Tbl->useFlag = TBL_END;
-+ signal(SIGCHLD,SIG_IGN);
-+ signal(signal_args,SIG_IGN);
-+ kill (0,signal_args);
-+ while (wait(NULL) > 0 )
-+ ;
-+
-+ if (ClusterShmid > 0)
-+ {
-+ rtn = shmdt((char *)Cluster_Tbl);
-+ shmctl(ClusterShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ ClusterShmid = 0;
-+ Cluster_Tbl = NULL;
-+ }
-+ if (ChildShmid > 0)
-+ {
-+ rtn = shmdt((char *)Child_Tbl);
-+ shmctl(ChildShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ ChildShmid = 0;
-+ Child_Tbl = NULL;
-+ }
-+ if (ClusterSemid > 0)
-+ {
-+ semctl(ClusterSemid, 0, IPC_RMID);
-+ }
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Write_Path,
PGLB_PID_FILE);
-+ unlink(fname);
-+
-+ if (StatusFp != NULL)
-+ {
-+ fflush(StatusFp);
-+ fclose(StatusFp);
-+ }
-+ if (LogFp != NULL)
-+ {
-+ fflush(LogFp);
-+ fclose(LogFp);
-+ }
-+ if (Frontend_FD.unix_fd != 0)
-+ {
-+ close(Frontend_FD.unix_fd);
-+ snprintf(fname, sizeof(fname), "%s/.s.PGSQL.%d",
Backend_Socket_Dir,Recv_Port_Number);
-+ unlink(fname);
-+ }
-+ if (Frontend_FD.inet_fd != 0)
-+ {
-+ close(Frontend_FD.inet_fd);
-+ }
-+ /*
-+ PGRsyn_quit();
-+ */
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Write_Path,
PGLB_PID_FILE);
-+ unlink(fname);
-+
-+ exit(0);
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * load_balance_main()
-+ * NOTES
-+ * This is a main module of load balance function
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+load_balance_main(void)
-+{
-+ char * func = "load_balance_main()";
-+ int status;
-+ int rtn;
-+ int count = 0;
-+
-+ Frontend_FD.unix_fd =
PGRcreate_unix_domain_socket(Backend_Socket_Dir, Recv_Port_Number);
-+ if (Frontend_FD.unix_fd < 0)
-+ {
-+ show_error("%s:PGRcreate_unix_domain_socket failed",func);
-+ pglb_exit(SIGTERM);
-+ }
-+ Frontend_FD.inet_fd = PGRcreate_recv_socket("", Recv_Port_Number);
-+ if (Frontend_FD.inet_fd < 0)
-+ {
-+ show_error("%s:PGRcreate_recv_socket failed",func);
-+ pglb_exit(SIGTERM);
-+ }
-+ if (Use_Connection_Pool)
-+ {
-+ signal(SIGCHLD,PGRrecreate_child);
-+ rtn = PGRpre_fork_children(Cluster_Tbl);
-+ if (rtn != STATUS_OK)
-+ {
-+ show_error("%s:PGRpre_fork_children failed",func);
-+ pglb_exit(SIGTERM);
-+ }
-+ }
-+
-+ for (;;)
-+ {
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = 60;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(Frontend_FD.unix_fd,&rmask);
-+ if(Frontend_FD.inet_fd)
-+ FD_SET(Frontend_FD.inet_fd,&rmask);
-+ rtn = select(Max(Frontend_FD.unix_fd, Frontend_FD.inet_fd) +
1, &rmask, (fd_set *)NULL, (fd_set *)NULL, &timeout);
-+ if( rtn > 0)
-+ {
-+ if(PGRis_cluster_alive() == STATUS_ERROR) {
-+ show_error("%s:all clusters were dead.",func);
PGRreturn_no_connection_error();
-+ count=0;
-+ }
-+ else
-+ {
-+ if (Use_Connection_Pool)
-+ {
-+ status = PGRload_balance_with_pool();
-+ }
-+ else
-+ {
-+ status = PGRload_balance();
-+ }
-+ if (status != STATUS_OK)
-+ {
-+ show_error("%s:load balance process
failed",func);
-+ if ( count > PGLB_CONNECT_RETRY_TIME)
-+ {
-+ show_error("%s:no cluster
available",func);
-+ PGRreturn_connection_full_error();
-+ count = 0;
-+ }
-+ count ++;
-+ }
-+ else
-+ {
-+ count = 0;
-+ }
-+ }
-+ }
-+ }
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * daemonize()
-+ * NOTES
-+ * Daemonize this process
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+daemonize(void)
-+{
-+ char * func = "daemonize()";
-+ int i;
-+ pid_t pid;
-+
-+ pid = fork();
-+ if (pid == (pid_t) -1)
-+ {
-+ show_error("%s:fork() failed. (%s)",func, strerror(errno));
-+ exit(1);
-+ return; /* not reached */
-+ }
-+ else if (pid > 0)
-+ { /* parent */
-+ exit(0);
-+ }
-+
-+#ifdef HAVE_SETSID
-+ if (setsid() < 0)
-+ {
-+ show_error("%s:setsid() failed. (%s)", func,strerror(errno));
-+ exit(1);
-+ }
-+#endif
-+
-+ i = open("/dev/null", O_RDWR);
-+ dup2(i, 0);
-+ dup2(i, 1);
-+ dup2(i, 2);
-+ close(i);
-+}
-+
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * write_pid_file()
-+ * NOTES
-+ * The process ID is written in the file.
-+ * This process ID is used when finish pglb.
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+write_pid_file(void)
-+{
-+ char * func = "write_pid_file()";
-+ FILE *fd;
-+ char fname[256];
-+ char pidbuf[128];
-+
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Write_Path,
PGLB_PID_FILE);
-+ fd = fopen(fname, "w");
-+ if (!fd)
-+ {
-+ show_error("%s:open() %s file failed. (%s)",
-+ func,fname, strerror(errno));
-+ exit(1);
-+ }
-+ snprintf(pidbuf, sizeof(pidbuf), "%d", getpid());
-+ fwrite(pidbuf, strlen(pidbuf), 1, fd);
-+ if (fclose(fd))
-+ {
-+ show_error("%s:fwrite() %s file failed. (%s)",
-+ func,fname, strerror(errno));
-+ exit(1);
-+ }
-+}
-+
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * stop_pglb()
-+ * NOTES
-+ * Stop the pglb process
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+stop_pglb(void)
-+{
-+ char * func = "stop_pglb()";
-+ FILE *fd;
-+ char fname[256];
-+ char pidbuf[128];
-+ pid_t pid;
-+
-+ if (PGR_Write_Path == NULL)
-+ {
-+ PGR_Write_Path = ".";
-+ }
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Write_Path,
PGLB_PID_FILE);
-+ fd = fopen(fname, "r");
-+ if (!fd)
-+ {
-+ show_error("%s:open() %s file failed. (%s)",
-+ func,fname, strerror(errno));
-+ exit(1);
-+ }
-+ memset(pidbuf,0,sizeof(pidbuf));
-+ fread(pidbuf, sizeof(pidbuf), 1, fd);
-+ fclose(fd);
-+ pid = atoi(pidbuf);
-+ if (kill (pid,SIGTERM) == -1)
-+ {
-+ show_error("%s:could not stop pid: %d
(%s)",func,pid,strerror(errno));
-+ exit(1);
-+ }
-+}
-+
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * is_exist_pid_file()
-+ * NOTES
-+ * Check existence of pid file.
-+ * ARGS
-+ * void
-+ * RETURN
-+ * 1: the pid file is exist
-+ * 0: the pid file is not exist
-+ *--------------------------------------------------------------------
-+ */
-+static int
-+is_exist_pid_file(void)
-+{
-+ char fname[256];
-+ struct stat buf;
-+
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Write_Path,
PGLB_PID_FILE);
-+ if (stat(fname,&buf) == 0)
-+ {
-+ /* pid file is exist */
-+ return 1;
-+ }
-+ else
-+ {
-+ /* pid file is not exist */
-+ return 0;
-+ }
-+}
-+
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRrecreate_child()
-+ * NOTES
-+ * create the child process again which it hunged up
-+ * ARGS
-+ * int signal_args: signal number (expecting the SIGCHLD)
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+void
-+PGRrecreate_child(int signal_args)
-+{
-+ pid_t pid = 0;
-+ int status;
-+ ClusterTbl * cluster_p;
-+
-+ReWait:
-+
-+ errno = 0;
-+#ifdef HAVE_WAITPID
-+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
-+ {
-+#else
-+ while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
-+ {
-+#endif
-+ cluster_p = scan_cluster_by_pid(pid);
-+ pid = PGRcreate_child(cluster_p);
-+ }
-+ if ((pid < 0) && (errno == EINTR))
-+ goto ReWait;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * close_child()
-+ * NOTES
-+ * Hung up child process
-+ * ARGS
-+ * int signal_args: signal number (expecting the SIGUSR2)
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+close_child(int signal_args)
-+{
-+ char * func = "close_child()";
-+ ChildTbl * child;
-+ ClusterTbl * cluster;
-+ int rec_no = -1;
-+
-+ if (( Cluster_Tbl == NULL) || (Child_Tbl == NULL))
-+ {
-+ show_error("%s:Cluster_Tbl or Child_Tbl is not
initialize",func);
-+ return ;
-+ }
-+ cluster = Cluster_Tbl;
-+ while(cluster->useFlag != TBL_END)
-+ {
-+ if (cluster->useFlag == TBL_ERROR_NOTICE)
-+ {
-+ rec_no = cluster->rec_no;
-+ PGRset_status_on_cluster_tbl(TBL_ERROR,cluster);
-+ break;
-+ }
-+ cluster++;
-+ }
-+ if (rec_no < 0)
-+ {
-+ return;
-+ }
-+ child = Child_Tbl;
-+ while(child->useFlag != TBL_END)
-+ {
-+ if (child->rec_no == rec_no)
-+ {
-+ if (kill (child->pid,SIGTERM) == -1)
-+ {
-+ show_error("%s:could not stop pid: %d
(%s)",func,child->pid,strerror(errno));
-+ return;
-+ }
-+ PGRchild_wait(signal_args);
-+ child->useFlag = DATA_FREE;
-+ }
-+ child++;
-+ }
-+ signal(SIGUSR2, close_child);
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * scan_cluster_by_pid()
-+ * NOTES
-+ * get cluster server record from child process id
-+ * ARGS
-+ * pid_t pid: child process id (I)
-+ * RETURN
-+ * OK: pointer of cluster table
-+ * NG: NULL
-+ *--------------------------------------------------------------------
-+ */
-+static ClusterTbl *
-+scan_cluster_by_pid(pid_t pid)
-+{
-+ char * func = "scan_cluster_by_pid()";
-+ ChildTbl * child_p;
-+ ClusterTbl * cluster_p;
-+ int cnt;
-+
-+ child_p = Child_Tbl;
-+ if (child_p == NULL)
-+ {
-+ show_error("%s:Child Table is not initialize",func);
-+ return NULL;
-+ }
-+ cluster_p = Cluster_Tbl;
-+ if (cluster_p == NULL)
-+ {
-+ show_error("%s:Cluster Table is not initialize",func);
-+ return NULL;
-+ }
-+
-+ while (child_p->useFlag != TBL_END)
-+ {
-+ if (child_p->pid == pid)
-+ {
-+ break;
-+ }
-+ child_p++;
-+ }
-+ if (child_p->useFlag == TBL_END)
-+ {
-+ show_error("%s:pid:%d not found in child table",func,pid);
-+ return NULL;
-+ }
-+
-+ cnt = 0;
-+ while ((cluster_p->useFlag != TBL_END) && (cnt < ClusterNum))
-+ {
-+ if (cluster_p->rec_no == child_p->rec_no)
-+ {
-+ return cluster_p;
-+ }
-+ cluster_p++;
-+ cnt ++;
-+ }
-+ return NULL;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * usage()
-+ * NOTES
-+ * show usage of pglb
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+usage(void)
-+{
-+ char * path;
-+
-+ path = getenv("PGDATA");
-+ if (path == NULL)
-+ path = ".";
-+ fprintf(stderr,"pglb version [%s]\n",PGLB_VERSION);
-+ fprintf(stderr,"A load balancer for PostgreSQL\n\n");
-+ fprintf(stderr,"usage: pglb [-D path_of_config_file] [-W
path_of_work_files] [-n][-v][-h][stop | restart]\n");
-+ fprintf(stderr," config file default path: %s/%s\n",path,
PGLB_CONF_FILE);
-+ fprintf(stderr," -l: print error logs in the log file.\n");
-+ fprintf(stderr," -n: don't run in daemon mode.\n");
-+ fprintf(stderr," -v: debug mode. need '-n' flag\n");
-+ fprintf(stderr," -h: print this help\n");
-+ fprintf(stderr," stop: stop pglb\n");
-+ fprintf(stderr," restart: restart pglb\n");
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * main()
-+ * NOTES
-+ * main module of pglb
-+ * ARGS
-+ * int argc: number of parameter
-+ * char ** argv: value of parameter
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+int
-+main(int argc, char ** argv)
-+{
-+ int opt = 0;
-+ pid_t pid,pgid;
-+ char * r_path = NULL;
-+ char * w_path = NULL;
-+ int detach = 1;
-+
-+ signal(SIGHUP, pglb_exit);
-+ signal(SIGINT, pglb_exit);
-+ signal(SIGQUIT, pglb_exit);
-+ signal(SIGTERM, pglb_exit);
-+ signal(SIGALRM, SIG_IGN); /* ignored */
-+ signal(SIGPIPE, SIG_IGN); /* ignored */
-+ signal(SIGTTIN, SIG_IGN); /* ignored */
-+ signal(SIGTTOU, SIG_IGN); /* ignored */
-+ signal(SIGCHLD,PGRchild_wait);
-+ signal(SIGUSR1, SIG_IGN); /* ignored */
-+ signal(SIGUSR2, close_child); /* close child process */
-+ r_path = getenv("PGDATA");
-+ if (r_path == NULL)
-+ r_path = ".";
-+
-+ while ((opt = getopt(argc, argv, "D:W:lvnh")) != -1)
-+ {
-+ switch (opt)
-+ {
-+ case 'D':
-+ if (!optarg)
-+ {
-+ usage();
-+ exit(1);
-+ }
-+ r_path = optarg;
-+ break;
-+ case 'W':
-+ if (!optarg)
-+ {
-+ usage();
-+ exit(1);
-+ }
-+ w_path = optarg;
-+ break;
-+ case 'l':
-+ Log_Print = 1;
-+ break;
-+ case 'v':
-+ Debug_Print = 1;
-+ break;
-+ case 'n':
-+ detach = 0;
-+ break;
-+ case 'h':
-+ usage();
-+ exit(0);
-+ break;
-+ default:
-+ usage();
-+ exit(1);
-+ }
-+ }
-+ PGR_Data_Path = r_path;
-+ if (w_path == NULL)
-+ {
-+ PGR_Write_Path = PGR_Data_Path;
-+ }
-+ else
-+ {
-+ PGR_Write_Path = w_path;
-+ }
-+
-+ if (optind == (argc-1) &&
-+ ((!strcmp(argv[optind],"stop")) ||
-+ (!strcmp(argv[optind],"restart"))))
-+ {
-+ stop_pglb();
-+ if (!strcmp(argv[optind],"stop"))
-+ {
-+ exit(0);
-+ }
-+ }
-+ else if (optind == argc)
-+ {
-+ if (is_exist_pid_file())
-+ {
-+ fprintf(stderr,"pid file %s/%s found. is another pglb
running?", PGR_Write_Path, PGLB_PID_FILE);
-+ exit(1);
-+ }
-+ }
-+ else if (optind < argc)
-+ {
-+ usage();
-+ exit(1);
-+ }
-+
-+ if (detach)
-+ {
-+ daemonize();
-+ }
-+ write_pid_file();
-+
-+ if (init_pglb(PGR_Data_Path) != STATUS_OK)
-+ {
-+ exit(0);
-+ }
-+
-+ pgid = getpgid((pid_t)0);
-+ pid = fork();
-+ if (pid < 0)
-+ {
-+ pglb_exit(0);
-+ }
-+ if (pid == 0)
-+ {
-+ setpgid((pid_t)0,pgid);
-+ PGRrecovery_main();
-+ exit(0);
-+ }
-+ else
-+ {
-+ load_balance_main();
-+ }
-+ pglb_exit(0);
-+ return STATUS_OK;
-+}
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/pglb.conf.sample
pgcluster-1.5.0rc7/src/pgcluster/pglb/pglb.conf.sample
---- postgresql-8.1.2/src/pgcluster/pglb/pglb.conf.sample 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/pglb.conf.sample 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,46 @@
-+#============================================================
-+# Load Balance Server configuration file
-+#-------------------------------------------------------------
-+# file: pglb.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts are db cluster server
-+# o which port use connect to db cluster server
-+# o how many connections are allowed on each DB server
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Max_Connection : maximun number of connection to postmaster
-+#-------------------------------------------------------------
-+#<Cluster_Server_Info>
-+# <Host_Name> master.postgres.jp </Host_Name>
-+# <Port> 5432 </Port>
-+# <Max_Connect> 0 </Max_Connect>
-+#</Cluster_Server_Info>
-+#<Cluster_Server_Info>
-+# <Host_Name> post2.postgres.jp </Host_Name>
-+# <Port> 5432 </Port>
-+# <Max_Connect> 32 </Max_Connect>
-+#</Cluster_Server_Info>
-+#<Cluster_Server_Info>
-+# <Host_Name> post3.postgres.jp </Host_Name>
-+# <Port> 5432 </Port>
-+# <Max_Connect> 32 </Max_Connect>
-+#</Cluster_Server_Info>
-+#-------------------------------------------------------------
-+# set Load Balance server information
-+# o Backend_Socket_Dir : Unix domain socket path for the backend
-+# o Receive_Port : connection from client
-+# o Recovery_Port : connection for recovery process
-+# o Max_Cluster_Num : maximun number of cluster DB servers
-+# o Use_Connection_Pooling : use connection pool [yes/no]
-+# o Max_Pool_Each_Server : number of pool connections/DB server
-+#-------------------------------------------------------------
-+<Backend_Socket_Dir> /tmp </Backend_Socket_Dir>
-+<Receive_Port> 5432 </Receive_Port>
-+<Recovery_Port> 6001 </Recovery_Port>
-+<Max_Cluster_Num> 128 </Max_Cluster_Num>
-+<Use_Connection_Pooling> no </Use_Connection_Pooling>
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/pglb.h
pgcluster-1.5.0rc7/src/pgcluster/pglb/pglb.h
---- postgresql-8.1.2/src/pgcluster/pglb/pglb.h 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/pglb.h 2006-02-09
17:46:26.000000000 +0100
-@@ -0,0 +1,458 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * pglb.h
-+ *
-+ * Portions Copyright (c) 2003-2006 Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#ifndef PGLB_H
-+#define PGLB_H
-+
-+#define PGLB_VERSION "1.5.0rc7"
-+
-+#include "../libpgc/libpgc.h"
-+
-+/*
-+ * from pool.h
-+ */
-+
-+/*
-+ * define this if you do not want to issue RESET ALL at each new
-+ * connection. Also you need to define this for 7.1 or prior
-+ * PostgreSQL since they do not support RESET ALL
-+ */
-+#undef NO_RESET_ALL
-+
-+/* undef this if you have problems with non blocking accept() */
-+#define NONE_BLOCK
-+
-+#define POOLMAXPATHLEN 8192
-+
-+/* configuration file name */
-+#define POOL_CONF_FILE_NAME "pgpool.conf"
-+
-+/* pid file directory */
-+#define DEFAULT_LOGDIR "/tmp"
-+
-+/* Unix domain socket directory */
-+#define DEFAULT_SOCKET_DIR "/tmp"
-+
-+/* pid file name */
-+#define PID_FILE_NAME "pgpool.pid"
-+
-+/* strict mode comment in SQL */
-+#define STRICT_MODE_STR "/*STRICT*/"
-+#define STRICT_MODE(s) (strncasecmp((s), STRICT_MODE_STR,
strlen(STRICT_MODE_STR)) == 0)
-+
-+typedef enum {
-+ POOL_CONTINUE = 0,
-+ POOL_IDLE,
-+ POOL_END,
-+ POOL_ERROR,
-+ POOL_FATAL
-+} POOL_STATUS;
-+
-+/* protocol major version numbers */
-+#define PROTO_MAJOR_V2 2
-+#define PROTO_MAJOR_V3 3
-+
-+/*
-+ * startup packet definitions (v2) stolen from PostgreSQL
-+ */
-+#define SM_DATABASE 64
-+#define SM_USER 32
-+#define SM_OPTIONS 64
-+#define SM_UNUSED 64
-+#define SM_TTY 64
-+
-+typedef struct PGR_StartupPacket_v2
-+{
-+ int protoVersion; /* Protocol version */
-+ char database[SM_DATABASE]; /* Database name */
-+ char user[SM_USER]; /* User name */
-+ char options[SM_OPTIONS]; /* Optional additional args */
-+ char unused[SM_UNUSED]; /* Unused */
-+ char tty[SM_TTY]; /* Tty for debug output */
-+} PGR_StartupPacket_v2;
-+
-+/* startup packet info */
-+typedef struct
-+{
-+ char *startup_packet; /* raw startup packet without packet
length (malloced area) */
-+ int len; /* raw startup packet
length */
-+ int major; /* protocol major version */
-+ int minor; /* protocol minor version */
-+ char *database; /* database name in startup_packet (malloced area) */
-+ char *user; /* user name in startup_packet (malloced area) */
-+} PGR_StartupPacket;
-+
-+typedef struct CancelPacket
-+{
-+ int protoVersion; /* Protocol version */
-+ int pid; /* bcckend process id */
-+ int key; /* cancel key */
-+} CancelPacket;
-+
-+/*
-+ * configuration paramters
-+ */
-+typedef struct {
-+ int inetdomain; /* should we make an INET domain socket too?
*/
-+ int port; /* port # to bind */
-+ char *socket_dir; /* pgpool socket directory */
-+ char *backend_host_name; /* backend host name */
-+ int backend_port; /* backend port # */
-+ char *secondary_backend_host_name; /* secondary backend host
name */
-+ int secondary_backend_port; /* secondary backend port # */
-+ int num_init_children; /* # of children initially pre-forked
*/
-+ int child_life_time; /* if idle for this seconds, child
exits */
-+ int connection_life_time; /* if idle for this seconds,
connection closes */
-+ int max_pool; /* max # of connection pool per child */
-+ char *logdir; /* logging directory */
-+ char *backend_socket_dir; /* Unix domain socket directory for the
PostgreSQL server */
-+ int replication_mode; /* replication mode */
-+ int replication_strict; /* if non 0, wait for completion of the
-+ query sent to master to avoid deadlock */
-+ /*
-+ * if secondary does not respond in this milli seconds, abort this
session.
-+ * this is not compatible with replication_strict = 1. 0 means no
timeout.
-+ */
-+ int replication_timeout;
-+
-+ int load_balance_mode; /* load balance mode */
-+
-+ /* followings do not exist in the configuration file */
-+ char *current_backend_host_name; /* current backend host name
*/
-+ int current_backend_port; /* current backend port # */
-+ int replication_enabled; /* replication mode enabled */
-+
-+ int replication_stop_on_mismatch; /* if there's a data
mismatch between master and secondary
-+
* start degenration to stop replication mode
-+
*/
-+} POOL_CONFIG;
-+
-+#define MAX_PASSWORD_SIZE (1024)
-+
-+typedef struct {
-+ int num; /* number of entries */
-+ char **names; /* parameter names */
-+ char **values; /* values */
-+} ParamStatus;
-+
-+/*
-+ * stream connection structure
-+ */
-+typedef struct {
-+ int fd; /* fd for connection */
-+ FILE *write_fd; /* stream write connection */
-+
-+ char *hp; /* pending data buffer head address */
-+ int po; /* pending data offset */
-+ int bufsz; /* pending data buffer size */
-+ int len; /* pending data length */
-+
-+ char *sbuf; /* buffer for pool_read_string */
-+ int sbufsz; /* its size in bytes */
-+
-+ char *buf2; /* buffer for pool_read2 */
-+ int bufsz2; /* its size in bytes */
-+
-+ int isbackend; /* this connection is for backend if non 0 */
-+ int issecondary_backend; /* this connection is for
secondary backend if non 0 */
-+
-+ char tstate; /* transaction state (V3 only) */
-+
-+ /*
-+ * following are used to remember when re-use the authenticated
connection
-+ */
-+ int auth_kind; /* 3: clear text password, 4: crypt password,
5: md5 password */
-+ int pwd_size; /* password (sent back from frontend) size in
host order */
-+ char password[MAX_PASSWORD_SIZE]; /* password (sent
back from frontend) */
-+ char salt[4]; /* password salt */
-+
-+ /*
-+ * following are used to remember current session paramter status.
-+ * re-used connection will need them (V3 only)
-+ */
-+ ParamStatus params;
-+
-+ int no_forward; /* if non 0, do not write to frontend */
-+
-+} POOL_CONNECTION;
-+
-+/*
-+ * connection pool structure
-+ */
-+typedef struct {
-+ PGR_StartupPacket *sp; /* startup packet info */
-+ int pid; /* backend pid */
-+ int key; /* cancel key */
-+ POOL_CONNECTION *con;
-+ time_t closetime; /* absolute time in second when the
connection closed
-+ * if 0, that means the
connection is under use.
-+ */
-+} POOL_CONNECTION_POOL_SLOT;
-+
-+#define MAX_CONNECTION_SLOTS 2
-+
-+typedef struct {
-+ int num; /* number of slots */
-+ POOL_CONNECTION_POOL_SLOT *slots[MAX_CONNECTION_SLOTS];
-+} POOL_CONNECTION_POOL;
-+
-+#define MASTER_CONNECTION(p) ((p)->slots[0])
-+#define SECONDARY_CONNECTION(p) ((p)->slots[1])
-+#define MASTER(p) MASTER_CONNECTION(p)->con
-+#define SECONDARY(p) SECONDARY_CONNECTION(p)->con
-+#define MAJOR(p) MASTER_CONNECTION(p)->sp->major
-+#define TSTATE(p) MASTER(p)->tstate
-+
-+#define Max(x, y) ((x) > (y) ? (x) : (y))
-+#define Min(x, y) ((x) < (y) ? (x) : (y))
-+
-+/*
-+ * pglb
-+ */
-+
-+typedef struct {
-+ int useFlag;
-+ int sock;
-+}SocketTbl;
-+
-+typedef struct {
-+ int useFlag;
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+ unsigned short port;
-+ short max_connect;
-+ int use_num;
-+ int rate;
-+ int rec_no;
-+}ClusterTbl;
-+
-+typedef struct {
-+ long mtype;
-+ char mdata[1];
-+}MsgData;
-+
-+typedef struct {
-+ int useFlag;
-+ int rec_no;
-+ pid_t pid;
-+}ChildTbl;
-+
-+#define UNIX_DOMAIN_FD (0)
-+#define INET_DOMAIN_FD (1)
-+typedef struct {
-+ int unix_fd;
-+ int inet_fd;
-+}FrontSocket;
-+
-+#define pool_config_inetdomain (0)
-+#define pool_config_replication_mode (0)
-+#define pool_config_replication_strict (0)
-+#define pool_config_replication_timeout (0)
-+#define pool_config_replication_enabled (0)
-+#define pool_config_load_balance_mode (0)
-+#define pool_config_replication_stop_on_mismatch (0)
-+#define pool_config_port (Recv_Port_Number)
-+#define pool_config_socket_dir (Backend_Socket_Dir)
-+#define pool_config_backend_host_name (CurrentCluster->hostName)
-+#define pool_config_backend_port (CurrentCluster->port)
-+#define pool_config_secondary_backend_host_name
(CurrentCluster->hostName)
-+#define pool_config_secondary_backend_port (CurrentCluster->port)
-+#define pool_config_num_init_children (CurrentCluster->max_connect)
-+#define pool_config_child_life_time (Connection_Life_Time)
-+#define pool_config_connection_life_time (Connection_Life_Time)
-+#define pool_config_max_pool (Max_Pool)
-+#define pool_config_logdir "./"
-+#define pool_config_backend_socket_dir (Backend_Socket_Dir)
-+#define pool_config_current_backend_host_name (CurrentCluster->hostName)
-+#define pool_config_current_backend_port (CurrentCluster->port)
-+#define REPLICATION (0)
-+#define IN_LOAD_BALANCE (0)
-+
-+/*
-+ * for pglb
-+ */
-+#define MAX_DB_SERVER (32)
-+#define PGLB_MAX_SOCKET_QUEUE (10000)
-+#define CLUSTER_TBL_SHM_KEY (1010)
-+#define PGLB_CONNECT_RETRY_TIME (3)
-+#define DEFAULT_CONNECT_NUM (32)
-+#define DEFAULT_PORT (5432)
-+#define BUF_SIZE (16384)
-+#define TBL_FREE (0)
-+#define TBL_INIT (1)
-+#define TBL_USE (2)
-+#define TBL_STOP (3)
-+#define TBL_ACCEPT (10)
-+#define TBL_ERROR_NOTICE (98)
-+#define TBL_ERROR (99)
-+#define TBL_END (-1)
-+#define STATUS_OK (0)
-+#define STATUS_ERROR (-1)
-+#ifdef RECOVERY_PREPARE_REQ
-+#define ADD_DB RECOVERY_PREPARE_REQ
-+#else
-+#define ADD_DB (1)
-+#endif
-+#ifdef RECOVERY_PGDATA_ANS
-+#define STOP_DB RECOVERY_PGDATA_ANS
-+#else
-+#define STOP_DB (3)
-+#endif
-+#ifdef RECOVERY_FINISH
-+#define START_DB RECOVERY_FINISH
-+#else
-+#define START_DB (9)
-+#endif
-+#define DELETE_DB (99)
-+#define QUERY_TERMINATE (0x00)
-+#define RESPONSE_TERMINATE (0x5a)
-+#define PGLB_CONF_FILE "pglb.conf"
-+#define PGLB_PID_FILE "pglb.pid"
-+#define PGLB_STATUS_FILE "pglb.sts"
-+#define PGLB_LOG_FILE "pglb.log"
-+#define CLUSTER_SERVER_TAG "Cluster_Server_Info"
-+#define MAX_CONNECT_TAG "Max_Connect"
-+#define RECOVERY_PORT_TAG "Recovery_Port"
-+#define RECV_PORT_TAG "Receive_Port"
-+#define MAX_CLUSTER_TAG "Max_Cluster_Num"
-+#define USE_CONNECTION_POOL_TAG "Use_Connection_Pooling"
-+#define MAX_POOL_TAG "Max_Pool_Each_Server"
-+#define BACKEND_SOCKET_DIR_TAG "Backend_Socket_Dir"
-+#define CONNECTION_LIFE_TIME "Connection_Life_Time"
-+#define NOT_USE_CONNECTION_POOL (0)
-+#define USE_CONNECTION_POOL (1)
-+
-+extern int Recv_Port_Number;
-+extern int Recovery_Port_Number;
-+extern uint16_t LifeCheck_Port_Number;
-+extern int Use_Connection_Pool;
-+extern int Max_Pool;
-+extern int Connection_Life_Time;
-+extern int Msg_Id;
-+extern ClusterTbl * Cluster_Tbl;
-+extern int Max_DB_Server;
-+extern int MaxBackends;
-+extern char * Backend_Socket_Dir;
-+extern int ClusterShmid;
-+extern int ClusterSemid;
-+extern int ChildShmid;
-+extern int ClusterNum;
-+extern ChildTbl * Child_Tbl;
-+extern char * PGR_Data_Path;
-+extern char * PGR_Write_Path;
-+extern char * Backend_Socket_Dir;
-+extern FrontSocket Frontend_FD;
-+extern FILE * StatusFp;
-+
-+/* for child.c */
-+extern POOL_CONNECTION * Frontend;
-+extern ClusterTbl * CurrentCluster;
-+
-+extern char * Function;
-+
-+extern POOL_CONNECTION_POOL *pool_connection_pool; /* connection pool */
-+
-+/* extern of main.c */
-+extern void PGRrecreate_child(int signal_args);
-+
-+/* extern of child.c */
-+extern int PGRpre_fork_children(ClusterTbl * ptr);
-+extern int PGRpre_fork_child(ClusterTbl * ptr);
-+extern int PGRdo_child( int use_pool);
-+extern int PGRcreate_child(ClusterTbl * cluster_p);
-+extern pid_t PGRscan_child_tbl(ClusterTbl * cluster_p);
-+extern void notice_backend_error(void);
-+extern void do_pooling_child(int sig);
-+extern int PGRset_status_to_child_tbl(pid_t pid, int status);
-+extern int PGRadd_child_tbl(ClusterTbl * cluster_p, pid_t pid, int status);
-+extern int PGRget_child_status(pid_t pid);
-+extern void PGRreturn_connection_full_error(void);
-+extern void PGRreturn_no_connection_error(void);
-+extern void PGRquit_children_on_cluster(int rec_no);
-+
-+/* extern of cluster_table.c */
-+extern int PGRis_cluster_alive(void) ;
-+extern ClusterTbl * PGRscan_cluster(void);
-+extern void PGRset_key_of_cluster(ClusterTbl * ptr, RecoveryPacket *
packet);
-+extern ClusterTbl * PGRadd_cluster_tbl (ClusterTbl * conf_data);
-+extern ClusterTbl * PGRset_status_on_cluster_tbl (int status, ClusterTbl *
ptr);
-+extern ClusterTbl * PGRsearch_cluster_tbl(ClusterTbl * conf_data);
-+
-+/* extern of load_balance.c */
-+extern int PGRload_balance(void);
-+extern int PGRload_balance_with_pool(void);
-+extern char PGRis_connection_full(ClusterTbl * ptr);
-+extern void PGRuse_connection(ClusterTbl * ptr);
-+extern void PGRrelease_connection(ClusterTbl * ptr);
-+extern void PGRchild_wait(int sig);
-+
-+/* extern of recovery.c */
-+extern void PGRrecovery_main(void);
-+
-+/* extern of socket.c */
-+extern int PGRcreate_unix_domain_socket(char * sock_dir, unsigned short
port);
-+extern int PGRcreate_recv_socket(char * hostName , unsigned short
portNumber);
-+extern int PGRcreate_acception(int fd, char * hostName , unsigned short
portNumber);
-+extern void PGRclose_sock(int * sock);
-+extern int PGRread_byte(int sock,char * buf,int len, int flag);
-+extern int PGRcreate_cluster_socket( int * sock, ClusterTbl * ptr );
-+
-+/* extern of pool_auth.c */
-+extern int pool_do_auth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*cp);
-+extern int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*cp);
-+extern int pool_read_message_length(POOL_CONNECTION_POOL *cp);
-+extern signed char pool_read_kind(POOL_CONNECTION_POOL *cp);
-+
-+/* extern of pool_connection_pool.c */
-+extern int pool_init_cp(void);
-+extern POOL_CONNECTION_POOL *pool_get_cp(char *user, char *database, int
protoMajor);
-+extern void pool_discard_cp(char *user, char *database, int protoMajor);
-+extern POOL_CONNECTION_POOL *pool_create_cp(void);
-+extern void pool_connection_pool_timer(POOL_CONNECTION_POOL *backend);
-+extern void pool_backend_timer_handler(int sig);
-+extern int connect_inet_domain_socket(int secondary_backend);
-+extern int connect_unix_domain_socket(int secondary_backend);
-+extern char PGRis_same_host(char * host1, char * host2);
-+extern void pool_finish(void);
-+
-+/* extern of pool_process_query.c */
-+extern POOL_STATUS pool_process_query(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend, int connection_reuse);
-+extern POOL_STATUS ErrorResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+extern void pool_enable_timeout();
-+extern void pool_disable_timeout();
-+extern int pool_check_fd(POOL_CONNECTION *cp, int notimeout);
-+extern void pool_send_frontend_exits(POOL_CONNECTION_POOL *backend);
-+extern POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION
*frontend, POOL_CONNECTION_POOL *backend);
-+extern POOL_STATUS SimpleForwardToBackend(char kind, POOL_CONNECTION
*frontend, POOL_CONNECTION_POOL *backend);
-+extern POOL_STATUS ParameterStatus(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+extern void pool_send_error_message(POOL_CONNECTION *frontend, int
protoMajor, char *code, char *message, char *detail, char *hint, char *file,
int line);
-+
-+/* extern of pool_params.c */
-+extern int pool_init_params(ParamStatus *params);
-+extern void pool_discard_params(ParamStatus *params);
-+extern char *pool_find_name(ParamStatus *params, char *name, int *pos);
-+extern int pool_get_param(ParamStatus *params, int index, char **name, char
**value);
-+extern int pool_add_param(ParamStatus *params, char *name, char *value);
-+extern void pool_param_debug_print(ParamStatus *params);
-+
-+/* extern of pool_stream.c */
-+extern POOL_CONNECTION *pool_open(int fd);
-+extern void pool_close(POOL_CONNECTION *cp);
-+extern int pool_read(POOL_CONNECTION *cp, void *buf, int len);
-+extern char *pool_read2(POOL_CONNECTION *cp, int len);
-+extern int pool_write(POOL_CONNECTION *cp, void *buf, int len);
-+extern int pool_flush(POOL_CONNECTION *cp);
-+extern int pool_write_and_flush(POOL_CONNECTION *cp, void *buf, int len);
-+extern char *pool_read_string(POOL_CONNECTION *cp, int *len, int line);
-+
-+/*
-+ * external prototype in show.c
-+ */
-+extern void show_error(const char * fmt,...);
-+extern void show_debug(const char * fmt,...);
-+extern void PGRwrite_log_file(FILE * fp, const char * fmt,...);
-+
-+#endif /* PGLB_H */
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/pool_auth.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_auth.c
---- postgresql-8.1.2/src/pgcluster/pglb/pool_auth.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_auth.c 2006-02-02
22:31:51.000000000 +0100
-@@ -0,0 +1,959 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * pool_auth.c
-+ *
-+ * NOTE:
-+ * authenticaton stuff
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ * Portions Copyright (c) 2003-2006, Tatsuo Ishii
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 <sys/types.h>
-+#include <netinet/in.h>
-+#include <sys/param.h>
-+#include <arpa/inet.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <sys/time.h>
-+#include <stdio.h>
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+int pool_do_auth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp);
-+int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp);
-+int pool_read_message_length(POOL_CONNECTION_POOL *cp);
-+signed char pool_read_kind(POOL_CONNECTION_POOL *cp);
-+
-+static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid,
int key, int protoMajor);
-+static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION
*frontend, int reauth, int protoMajor);
-+static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend,
int reauth, int protoMajor);
-+static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int
reauth, int protoMajor);
-+
-+/*
-+* do authentication against backend. if success return 0 otherwise non 0.
-+*/
-+int pool_do_auth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
-+{
-+ char * func = "pool_do_auth()";
-+ int status;
-+ signed char kind;
-+ int pid, pid1;
-+ int key, key1;
-+ int protoMajor;
-+ int length;
-+
-+ protoMajor = MAJOR(cp);
-+
-+ kind = pool_read_kind(cp);
-+ if (kind < 0)
-+ {
-+ return -1;
-+ }
-+
-+ /* error response? */
-+ if (kind == 'E')
-+ {
-+ /* we assume error response at this stage is likely version
-+ * protocol mismatch (v3 frontend vs. v2 backend). So we throw
-+ * a V2 protocol error response in the hope that v3 frontend
-+ * will negotiate again using v2 protocol.
-+ */
-+ show_error("%s:pool_do_auth: maybe protocol version mismatch
(current version %d)",func, protoMajor);
-+ ErrorResponse(frontend, cp);
-+ return -1;
-+ }
-+ else if (kind != 'R')
-+ {
-+ show_error("%s:pool_do_auth: expect \"R\" got %c",func, kind);
-+ return -1;
-+ }
-+
-+ /*
-+ * message length (v3 only) */
-+ if (protoMajor == PROTO_MAJOR_V3 && pool_read_message_length(cp) < 0)
-+ {
-+ return -1;
-+ }
-+
-+ /*
-+ * read authentication request kind.
-+ *
-+ * 0: authentication ok
-+ * 1: kerberos v4
-+ * 2: kerberos v5
-+ * 3: clear text password
-+ * 4: crypt password
-+ * 5: md5 password
-+ * 6: scm credential
-+ *
-+ * in replication mode, we only supports kind = 0, 3. this is
because to "salt"
-+ * cannot be replicated among master and secondary.
-+ * in non replication mode, we supports kind = 0, 3, 4, 5
-+ */
-+
-+ status = pool_read(MASTER(cp), &pid, sizeof(pid));
-+ if (status < 0)
-+ {
-+ show_error("%s:pool_do_auth: read authentication kind
failed",func);
-+ return -1;
-+ }
-+
-+ if (REPLICATION)
-+ {
-+ status = pool_read(SECONDARY(cp), &pid1, sizeof(pid1));
-+
-+ if (status < 0)
-+ {
-+ show_error("%s:pool_do_auth: read authentication kind
from secondary failed",func);
-+ return -1;
-+ }
-+ }
-+
-+ pid = ntohl(pid);
-+
-+ /* trust? */
-+ if (pid == 0)
-+ {
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ int msglen;
-+
-+ pool_write(frontend, "R", 1);
-+ msglen = htonl(8);
-+ pool_write(frontend, &msglen, sizeof(msglen));
-+ msglen = htonl(0);
-+ if (pool_write_and_flush(frontend, &msglen,
sizeof(msglen)) < 0)
-+ {
-+ return -1;
-+ }
-+ }
-+ MASTER(cp)->auth_kind = 0;
-+ }
-+
-+ /* clear text password authentication? */
-+ else if (pid == 3)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:trying clear text password
authentication",func);
-+#endif
-+
-+ pid = do_clear_text_password(MASTER(cp), frontend, 0,
protoMajor);
-+
-+ if (pid >= 0 && REPLICATION)
-+ {
-+ pid = do_clear_text_password(SECONDARY(cp), frontend,
0, protoMajor);
-+ }
-+ }
-+
-+ /* crypt authentication? */
-+ else if (pid == 4)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:trying crypt authentication",func);
-+#endif
-+
-+ pid = do_crypt(MASTER(cp), frontend, 0, protoMajor);
-+
-+ if (pid >= 0 && REPLICATION)
-+ {
-+ pid = do_crypt(SECONDARY(cp), frontend, 0,
protoMajor);
-+ }
-+ }
-+
-+ /* md5 authentication? */
-+ else if (pid == 5)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:trying md5 authentication",func);
-+#endif
-+
-+ pid = do_md5(MASTER(cp), frontend, 0, protoMajor);
-+
-+ if (pid >= 0 && REPLICATION)
-+ {
-+ pid = do_md5(SECONDARY(cp), frontend, 0, protoMajor);
-+ }
-+ }
-+
-+ if (pid != 0)
-+ {
-+ show_error("%s:pool_do_auth: backend does not return
authenticaton ok",func);
-+ return -1;
-+ }
-+
-+ /*
-+ * authentication ok. now read pid and secret key from the
-+ * backend
-+ */
-+ kind = pool_read_kind(cp);
-+ if (kind < 0)
-+ {
-+ return -1;
-+ }
-+
-+ /* error response? */
-+ if (kind == 'E')
-+ {
-+ if (protoMajor == PROTO_MAJOR_V2)
-+ ErrorResponse(frontend, cp);
-+ else
-+ SimpleForwardToFrontend(kind, frontend, cp);
-+ return -1;
-+ }
-+ else if (kind != 'K')
-+ {
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ /* process parameter status */
-+ while (kind == 'S')
-+ {
-+ if (ParameterStatus(frontend, cp) !=
POOL_CONTINUE)
-+ return -1;
-+
-+ pool_flush(frontend);
-+
-+ kind = pool_read_kind(cp);
-+ if (kind < 0)
-+ {
-+ show_error("%s:pool_do_auth: failed
to read kind while processing ParamterStatus",func);
-+ return -1;
-+ }
-+ }
-+ }
-+ else
-+ {
-+ show_error("%s:pool_do_auth: expect \"K\" got
%c",func, kind);
-+ return -1;
-+ }
-+ }
-+
-+ /*
-+ * message length (V3 only)
-+ */
-+ if (protoMajor == PROTO_MAJOR_V3 && (length =
pool_read_message_length(cp)) != 12)
-+ {
-+ show_error("%s:pool_do_auth: invalid messages length(%d) for
BackendKeyData",func, length);
-+ return -1;
-+ }
-+
-+ /*
-+ * OK, read pid and secret key
-+ */
-+
-+ /* pid */
-+ pool_read(MASTER(cp), &pid, sizeof(pid));
-+ MASTER_CONNECTION(cp)->pid = pid;
-+
-+ /* key */
-+ pool_read(MASTER(cp), &key, sizeof(key));
-+ MASTER_CONNECTION(cp)->key = key;
-+
-+ if (REPLICATION)
-+ {
-+ pool_read(SECONDARY(cp), &pid1, sizeof(pid1));
-+ SECONDARY_CONNECTION(cp)->pid = pid;
-+
-+ /* key */
-+ pool_read(SECONDARY(cp), &key1, sizeof(key1));
-+ SECONDARY_CONNECTION(cp)->key = key;
-+ }
-+
-+ return (pool_send_auth_ok(frontend, pid, key, protoMajor));
-+}
-+
-+/*
-+* do re-authentication for reused connection. if success return 0 otherwise
non 0.
-+*/
-+int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
-+{
-+ char * func = "pool_do_reauth()";
-+ int status;
-+ int protoMajor;
-+
-+ protoMajor = MAJOR(cp);
-+
-+ switch(MASTER(cp)->auth_kind)
-+ {
-+ case 0:
-+ /* trust */
-+ status = 0;
-+ break;
-+
-+ case 3:
-+ /* clear text password */
-+ status = do_clear_text_password(MASTER(cp), frontend,
1, protoMajor);
-+ break;
-+
-+ case 4:
-+ /* crypt password */
-+ status = do_crypt(MASTER(cp), frontend, 1,
protoMajor);
-+ break;
-+
-+ case 5:
-+ /* md5 password */
-+ status = do_md5(MASTER(cp), frontend, 1, protoMajor);
-+ break;
-+
-+ default:
-+ show_error("%s: unknown authentication request code
%d",
-+ func,MASTER(cp)->auth_kind);
-+ return -1;
-+ }
-+
-+ if (status == 0)
-+ {
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ int msglen;
-+
-+ pool_write(frontend, "R", 1);
-+ msglen = htonl(8);
-+ pool_write(frontend, &msglen, sizeof(msglen));
-+ msglen = htonl(0);
-+ if (pool_write_and_flush(frontend, &msglen,
sizeof(msglen)) < 0)
-+ {
-+ return -1;
-+ }
-+ }
-+ }
-+ else
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: authentication failed",func);
-+#endif
-+ return -1;
-+ }
-+
-+ return (pool_send_auth_ok(frontend, MASTER_CONNECTION(cp)->pid,
MASTER_CONNECTION(cp)->key, protoMajor) != POOL_CONTINUE);
-+}
-+
-+/*
-+* send authentication ok to frontend. if success return 0 otherwise non 0.
-+*/
-+static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid,
int key, int protoMajor)
-+{
-+ char kind;
-+ int len;
-+
-+ if (protoMajor == PROTO_MAJOR_V2)
-+ {
-+ /* return "Authentication OK" to the frontend */
-+ kind = 'R';
-+ pool_write(frontend, &kind, 1);
-+ len = htonl(0);
-+ if (pool_write_and_flush(frontend, &len, sizeof(len)) < 0)
-+ {
-+ return -1;
-+ }
-+ }
-+
-+ /* send backend key data */
-+ kind = 'K';
-+ pool_write(frontend, &kind, 1);
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ len = htonl(12);
-+ pool_write(frontend, &len, sizeof(len));
-+ }
-+ pool_write(frontend, &pid, sizeof(pid));
-+ if (pool_write_and_flush(frontend, &key, sizeof(key)) < 0)
-+ {
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * perform clear text password authetication
-+ */
-+static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION
*frontend, int reauth, int protoMajor)
-+{
-+ char * func = "do_clear_text_password()";
-+ static int size;
-+ static char password[MAX_PASSWORD_SIZE];
-+ char response;
-+ int kind;
-+ int len;
-+
-+ /* master? */
-+ if (!backend->issecondary_backend)
-+ {
-+ pool_write(frontend, "R", 1); /* authenticaton */
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ len = htonl(8);
-+ pool_write(frontend, &len, sizeof(len));
-+ }
-+ kind = htonl(3); /* clear text password
authentication */
-+ pool_write_and_flush(frontend, &kind, sizeof(kind)); /*
indicating clear text password authentication */
-+
-+ /* read password packet */
-+ if (protoMajor == PROTO_MAJOR_V2)
-+ {
-+ if (pool_read(frontend, &size, sizeof(size)))
-+ {
-+ show_error("%s: failed to read password
packet size",func);
-+ return -1;
-+ }
-+ }
-+ else
-+ {
-+ char k;
-+
-+ if (pool_read(frontend, &k, sizeof(k)))
-+ {
-+ show_error("%s: failed to read password
packet \"p\"",func);
-+ return -1;
-+ }
-+ if (k != 'p')
-+ {
-+ show_error("%s:packet does not start with
\"p\"",func);
-+ return -1;
-+ }
-+ if (pool_read(frontend, &size, sizeof(size)))
-+ {
-+ show_error("%s: failed to read password
packet size",func);
-+ return -1;
-+ }
-+ }
-+
-+ if ((ntohl(size) - 4) > sizeof(password))
-+ {
-+ show_error("%s: password is too long (size:
%d)",func, ntohl(size) - 4);
-+ return -1;
-+ }
-+
-+ if (pool_read(frontend, password, ntohl(size) - 4))
-+ {
-+ show_error("%s: failed to read password (size:
%d)",func, ntohl(size) - 4);
-+ return -1;
-+ }
-+ }
-+
-+ /* connection reusing? */
-+ if (reauth)
-+ {
-+ if ((ntohl(size) - 4) != backend->pwd_size)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s; password size does not match in
re-authetication",func);
-+#endif
-+ return -1;
-+ }
-+
-+ if (memcmp(password, backend->password, backend->pwd_size) !=
0)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s; password does not match in
re-authetication",func);
-+#endif
-+ return -1;
-+ }
-+
-+ return 0;
-+ }
-+
-+ /* send password packet to backend */
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ pool_write(backend, "p", 1);
-+ pool_write(backend, &size, sizeof(size));
-+ pool_write_and_flush(backend, password, ntohl(size) -4);
-+ if (pool_read(backend, &response, sizeof(response)))
-+ {
-+ show_error("%s: failed to read authentication response",func);
-+ return -1;
-+ }
-+
-+ if (response != 'R')
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: backend does not return R while processing
clear text password authentication",func);
-+#endif
-+ return -1;
-+ }
-+
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ if (pool_read(backend, &len, sizeof(len)))
-+ {
-+ show_error("%s: failed to read authentication packet
size",func);
-+ return -1;
-+ }
-+
-+ if (ntohl(len) != 8)
-+ {
-+ show_error("%s: incorrect authentication packet size
(%d)",func, ntohl(len));
-+ return -1;
-+ }
-+ }
-+
-+ /* expect to read "Authentication OK" response. kind should be 0... */
-+ if (pool_read(backend, &kind, sizeof(kind)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: failed to read Authentication OK
response",func);
-+#endif
-+ return -1;
-+ }
-+
-+ /* if authenticated, save info */
-+ if (!reauth && kind == 0)
-+ {
-+ if (!backend->issecondary_backend && protoMajor ==
PROTO_MAJOR_V3)
-+ {
-+ int msglen;
-+
-+ pool_write(frontend, "R", 1);
-+ msglen = htonl(8);
-+ pool_write(frontend, &msglen, sizeof(msglen));
-+ msglen = htonl(0);
-+ if (pool_write_and_flush(frontend, &msglen,
sizeof(msglen)) < 0)
-+ {
-+ return -1;
-+ }
-+ }
-+
-+ backend->auth_kind = 3;
-+ backend->pwd_size = ntohl(size) - 4;
-+ memcpy(backend->password, password, backend->pwd_size);
-+ }
-+ return kind;
-+}
-+
-+/*
-+ * perform crypt authetication
-+ */
-+static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend,
int reauth, int protoMajor)
-+{
-+ char * func = "do_crypt()";
-+ char salt[2];
-+ static int size;
-+ static char password[MAX_PASSWORD_SIZE];
-+ char response;
-+ int kind;
-+ int len;
-+
-+ if (!reauth)
-+ {
-+ /* read salt */
-+ if (pool_read(backend, salt, sizeof(salt)))
-+ {
-+ show_error("%s: failed to read salt",func);
-+ return -1;
-+ }
-+ }
-+ else
-+ {
-+ memcpy(salt, backend->salt, sizeof(salt));
-+ }
-+
-+ /* master? */
-+ if (!backend->issecondary_backend)
-+ {
-+ pool_write(frontend, "R", 1); /* authenticaton */
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ len = htonl(10);
-+ pool_write(frontend, &len, sizeof(len));
-+ }
-+ kind = htonl(4); /* crypt authentication */
-+ pool_write(frontend, &kind, sizeof(kind)); /* indicating
crypt authentication */
-+ pool_write_and_flush(frontend, salt, sizeof(salt));
/* salt */
-+
-+ /* read password packet */
-+ if (protoMajor == PROTO_MAJOR_V2)
-+ {
-+ if (pool_read(frontend, &size, sizeof(size)))
-+ {
-+ show_error("%s: failed to read password
packet size",func);
-+ return -1;
-+ }
-+ }
-+ else
-+ {
-+ char k;
-+
-+ if (pool_read(frontend, &k, sizeof(k)))
-+ {
-+ show_error("%s: failed to read password
packet",func);
-+ return -1;
-+ }
-+ if (k != 'p')
-+ {
-+ show_error("%s: password packet does not
start with \"p\"",func);
-+ return -1;
-+ }
-+ if (pool_read(frontend, &size, sizeof(size)))
-+ {
-+ show_error("%s: failed to read password
packet size",func);
-+ return -1;
-+ }
-+ }
-+
-+ if ((ntohl(size) - 4) > sizeof(password))
-+ {
-+ show_error("%s: password is too long(size: %d)",
func,ntohl(size) - 4);
-+ return -1;
-+ }
-+
-+ if (pool_read(frontend, password, ntohl(size) - 4))
-+ {
-+ show_error("%s: failed to read password (size: %d)",
func,ntohl(size) - 4);
-+ return -1;
-+ }
-+ }
-+
-+ /* connection reusing? */
-+ if (reauth)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:size: %d saved_size: %d",func, (ntohl(size) -
4), backend->pwd_size);
-+#endif
-+ if ((ntohl(size) - 4) != backend->pwd_size)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: password size does not match in
re-authetication",func);
-+#endif
-+ return -1;
-+ }
-+
-+ if (memcmp(password, backend->password, backend->pwd_size) !=
0)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: password does not match in
re-authetication",func);
-+#endif
-+ return -1;
-+ }
-+
-+ return 0;
-+ }
-+
-+ /* send password packet to backend */
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ pool_write(backend, "p", 1);
-+ pool_write(backend, &size, sizeof(size));
-+ pool_write_and_flush(backend, password, ntohl(size) -4);
-+ if (pool_read(backend, &response, sizeof(response)))
-+ {
-+ show_error("%s: failed to read authentication response",func);
-+ return -1;
-+ }
-+
-+ if (response != 'R')
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: backend does not return R while processing
crypt authentication(%02x) secondary: %d",func, response,
backend->issecondary_backend);
-+#endif
-+ return -1;
-+ }
-+
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ if (pool_read(backend, &len, sizeof(len)))
-+ {
-+ show_error("%s: failed to read authentication packet
size",func);
-+ return -1;
-+ }
-+
-+ if (ntohl(len) != 8)
-+ {
-+ show_error("%s: incorrect authentication packet size
(%d)",func, ntohl(len));
-+ return -1;
-+ }
-+ }
-+
-+ /* expect to read "Authentication OK" response. kind should be 0... */
-+ if (pool_read(backend, &kind, sizeof(kind)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: failed to read Authentication OK
response",func);
-+#endif
-+ return -1;
-+ }
-+
-+ /* if authenticated, save info */
-+ if (!reauth && kind == 0)
-+ {
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ int msglen;
-+
-+ pool_write(frontend, "R", 1);
-+ msglen = htonl(8);
-+ pool_write(frontend, &msglen, sizeof(msglen));
-+ msglen = htonl(0);
-+ if (pool_write_and_flush(frontend, &msglen,
sizeof(msglen)) < 0)
-+ {
-+ return -1;
-+ }
-+ }
-+ backend->auth_kind = 4;
-+ backend->pwd_size = ntohl(size) - 4;
-+ memcpy(backend->password, password, backend->pwd_size);
-+ memcpy(backend->salt, salt, sizeof(salt));
-+ }
-+ return kind;
-+}
-+
-+/*
-+ * perform MD5 authetication
-+ */
-+static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int
reauth, int protoMajor)
-+{
-+ char * func = "do_md5()";
-+ char salt[4];
-+ static int size;
-+ static char password[MAX_PASSWORD_SIZE];
-+ char response;
-+ int kind;
-+ int len;
-+
-+ if (!reauth)
-+ {
-+ /* read salt */
-+ if (pool_read(backend, salt, sizeof(salt)))
-+ {
-+ show_error("%s: failed to read salt",func);
-+ return -1;
-+ }
-+ }
-+ else
-+ {
-+ memcpy(salt, backend->salt, sizeof(salt));
-+ }
-+
-+ /* master? */
-+ if (!backend->issecondary_backend)
-+ {
-+ pool_write(frontend, "R", 1); /* authenticaton */
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ len = htonl(12);
-+ pool_write(frontend, &len, sizeof(len));
-+ }
-+ kind = htonl(5);
-+ pool_write(frontend, &kind, sizeof(kind)); /* indicating
MD5 */
-+ pool_write_and_flush(frontend, salt, sizeof(salt));
/* salt */
-+
-+ /* read password packet */
-+ if (protoMajor == PROTO_MAJOR_V2)
-+ {
-+ if (pool_read(frontend, &size, sizeof(size)))
-+ {
-+ show_error("%s: failed to read password
packet size",func);
-+ return -1;
-+ }
-+ }
-+ else
-+ {
-+ char k;
-+
-+ if (pool_read(frontend, &k, sizeof(k)))
-+ {
-+ show_error("%s: failed to read password
packet \"p\"",func);
-+ return -1;
-+ }
-+ if (k != 'p')
-+ {
-+ show_error("%s: password packet does not
start with \"p\"",func);
-+ return -1;
-+ }
-+ if (pool_read(frontend, &size, sizeof(size)))
-+ {
-+ show_error("%s: failed to read password
packet size",func);
-+ return -1;
-+ }
-+ }
-+
-+ if ((ntohl(size) - 4) > sizeof(password))
-+ {
-+ show_error("%s: password is too long(size: %d)",func,
ntohl(size) - 4);
-+ return -1;
-+ }
-+
-+ if (pool_read(frontend, password, ntohl(size) - 4))
-+ {
-+ show_error("%s: failed to read password (size:
%d)",func, ntohl(size) - 4);
-+ return -1;
-+ }
-+ }
-+
-+ /* connection reusing? */
-+ if (reauth)
-+ {
-+ if ((ntohl(size) - 4) != backend->pwd_size)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s; password size does not match in
re-authetication",func);
-+#endif
-+ return -1;
-+ }
-+
-+ if (memcmp(password, backend->password, backend->pwd_size) !=
0)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s; password does not match in
re-authetication",func);
-+#endif
-+ return -1;
-+ }
-+
-+ return 0;
-+ }
-+
-+ /* send password packet to backend */
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ pool_write(backend, "p", 1);
-+ pool_write(backend, &size, sizeof(size));
-+ pool_write_and_flush(backend, password, ntohl(size) -4);
-+ if (pool_read(backend, &response, sizeof(response)))
-+ {
-+ show_error("%s: failed to read authentication response",func);
-+ return -1;
-+ }
-+
-+ if (response != 'R')
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: backend does not return R while processing
MD5 authentication %c", func,response);
-+#endif
-+ return -1;
-+ }
-+
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ if (pool_read(backend, &len, sizeof(len)))
-+ {
-+ show_error("%s: failed to read authentication packet
size",func);
-+ return -1;
-+ }
-+
-+ if (ntohl(len) != 8)
-+ {
-+ show_error("%s: incorrect authentication packet size
(%d)",func, ntohl(len));
-+ return -1;
-+ }
-+ }
-+
-+ /* expect to read "Authentication OK" response. kind should be 0... */
-+ if (pool_read(backend, &kind, sizeof(kind)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: failed to read Authentication OK
response",func);
-+#endif
-+ return -1;
-+ }
-+
-+ /* if authenticated, save info */
-+ if (!reauth && kind == 0)
-+ {
-+ if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ int msglen;
-+
-+ pool_write(frontend, "R", 1);
-+ msglen = htonl(8);
-+ pool_write(frontend, &msglen, sizeof(msglen));
-+ msglen = htonl(0);
-+ if (pool_write_and_flush(frontend, &msglen,
sizeof(msglen)) < 0)
-+ {
-+ return -1;
-+ }
-+ }
-+ backend->auth_kind = 5;
-+ backend->pwd_size = ntohl(size) - 4;
-+ memcpy(backend->password, password, backend->pwd_size);
-+ memcpy(backend->salt, salt, sizeof(salt));
-+ }
-+ return kind;
-+}
-+
-+/*
-+ * read message length (V3 only)
-+ */
-+int pool_read_message_length(POOL_CONNECTION_POOL *cp)
-+{
-+ char * func = "pool_read_message_length()";
-+ int status;
-+ int length, length1;
-+
-+ status = pool_read(MASTER(cp), &length, sizeof(length));
-+ if (status < 0)
-+ {
-+ show_error("%s: error while reading message length",func);
-+ return -1;
-+ }
-+ length = ntohl(length);
-+
-+ if (REPLICATION)
-+ {
-+ status = pool_read(SECONDARY(cp), &length1, sizeof(length1));
-+ if (status < 0)
-+ {
-+ show_error("%s: error while reading message length
from secondary backend",func);
-+ return -1;
-+ }
-+ length1 = ntohl(length1);
-+
-+ if (length != length1)
-+ {
-+ show_error("%s: length does not match between
backends master(%d) secondary(%d)",
-+ func,length, length1);
-+ return -1;
-+ }
-+ }
-+
-+ if (length < 0)
-+ {
-+ show_error("%s:read_message_length: invalid message length
(%d)", func, length);
-+ return -1;
-+ }
-+
-+ return length;
-+}
-+
-+signed char pool_read_kind(POOL_CONNECTION_POOL *cp)
-+{
-+ char * func = "pool_read_kind()";
-+ int status;
-+ char kind, kind1;
-+
-+ status = pool_read(MASTER(cp), &kind, sizeof(kind));
-+ if (status < 0)
-+ {
-+ show_error("%s:read_message_kind: error while reading message
kind",func);
-+ return -1;
-+ }
-+
-+ if (REPLICATION)
-+ {
-+ status = pool_read(SECONDARY(cp), &kind1, sizeof(kind1));
-+ if (status < 0)
-+ {
-+ show_error("%s: error while reading message kind from
secondary backend",func);
-+ return -1;
-+ }
-+
-+ if (kind != kind1)
-+ {
-+ show_error("%s: kind does not match between backends
master(%d) secondary(%d)",
-+ func, kind, kind1);
-+ return -1;
-+ }
-+ }
-+
-+ return kind;
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/pool_connection_pool.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_connection_pool.c
---- postgresql-8.1.2/src/pgcluster/pglb/pool_connection_pool.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_connection_pool.c
2006-02-02 22:32:25.000000000 +0100
-@@ -0,0 +1,535 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * pool_connection_pool.c
-+ *
-+ * NOTE:
-+ * connection pool stuff
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ * Portions Copyright (c) 2003-2006, Tatsuo Ishii
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 "postgres.h"
-+#include <sys/types.h>
-+#include <sys/socket.h>
-+#include <sys/time.h>
-+#include <sys/un.h>
-+#include <arpa/inet.h>
-+#include <netdb.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <signal.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <time.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+POOL_CONNECTION_POOL *pool_connection_pool; /* connection pool */
-+
-+int pool_init_cp(void);
-+POOL_CONNECTION_POOL *pool_get_cp(char *user, char *database, int
protoMajor);
-+void pool_discard_cp(char *user, char *database, int protoMajor);
-+POOL_CONNECTION_POOL *pool_create_cp(void);
-+void pool_connection_pool_timer(POOL_CONNECTION_POOL *backend);
-+void pool_backend_timer_handler(int sig);
-+int connect_inet_domain_socket(int secondary_backend);
-+int connect_unix_domain_socket(int secondary_backend);
-+char PGRis_same_host(char * host1, char * host2);
-+void pool_finish(void);
-+
-+
-+static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp,
int secondary_backend);
-+static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p);
-+
-+
-+
-+/*
-+* initialize connection pools. this should be called once at the startup.
-+*/
-+int pool_init_cp(void)
-+{
-+ char * func = "pool_init_cp()";
-+ pool_connection_pool = (POOL_CONNECTION_POOL
*)malloc(sizeof(POOL_CONNECTION_POOL)*Max_Pool);
-+ if (pool_connection_pool == NULL)
-+ {
-+ show_error("%s: malloc() failed[%s]",func,strerror(errno));
-+ return -1;
-+ }
-+ memset(pool_connection_pool, 0,
sizeof(POOL_CONNECTION_POOL)*Max_Pool);
-+
-+ return 0;
-+}
-+
-+/*
-+* find connection by user and database
-+*/
-+POOL_CONNECTION_POOL *pool_get_cp(char *user, char *database, int
protoMajor)
-+{
-+ char * func = "pool_get_cp()";
-+ int i;
-+
-+ POOL_CONNECTION_POOL *p = pool_connection_pool;
-+
-+ if (p == NULL)
-+ {
-+ show_error("%s: pool_connection_pool is not
initialized",func);
-+ return NULL;
-+ }
-+
-+ for (i=0;i<Max_Pool;i++)
-+ {
-+ if (MASTER_CONNECTION(p) &&
-+ MASTER_CONNECTION(p)->sp->major == protoMajor &&
-+ MASTER_CONNECTION(p)->sp->user != NULL &&
-+ strcmp(MASTER_CONNECTION(p)->sp->user, user) == 0 &&
-+ strcmp(MASTER_CONNECTION(p)->sp->database, database)
== 0)
-+ {
-+ /* mark this connection is under use */
-+ MASTER_CONNECTION(p)->closetime = 0;
-+ return p;
-+ }
-+ p++;
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * disconnect and release a connection to the database
-+ */
-+void pool_discard_cp(char *user, char *database, int protoMajor)
-+{
-+ char * func = "pool_discard_cp()";
-+ POOL_CONNECTION_POOL *p = pool_get_cp(user, database, protoMajor);
-+
-+ if (p == NULL)
-+ {
-+ show_error("%s: cannot get connection pool for user %s
datbase %s", func,user, database);
-+ return;
-+ }
-+
-+ free(MASTER_CONNECTION(p)->sp->user);
-+ free(MASTER_CONNECTION(p)->sp->database);
-+ free(MASTER_CONNECTION(p)->sp->startup_packet);
-+ pool_close(MASTER_CONNECTION(p)->con);
-+
-+ memset(p, 0, sizeof(POOL_CONNECTION_POOL));
-+}
-+
-+
-+/*
-+* create a connection pool by user and database
-+*/
-+POOL_CONNECTION_POOL *pool_create_cp(void)
-+{
-+ char * func = "pool_create_cp()";
-+ int i;
-+ time_t closetime;
-+ POOL_CONNECTION_POOL *oldestp;
-+
-+ POOL_CONNECTION_POOL *p = pool_connection_pool;
-+
-+ if (p == NULL)
-+ {
-+ show_error("%s: pool_connection_pool is not
initialized",func);
-+ return NULL;
-+ }
-+
-+ for (i=0; i<Max_Pool; i++)
-+ {
-+ if (MASTER_CONNECTION(p) == NULL)
-+ return new_connection(p);
-+ p++;
-+ }
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:no empty connection slot was found",func);
-+#endif
-+
-+ /*
-+ * no empty connection slot was found. look for the oldest connection
and discard it.
-+ */
-+ oldestp = p = pool_connection_pool;
-+ closetime = MASTER_CONNECTION(p)->closetime;
-+ for (i=0; i<Max_Pool; i++)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:user: %s database: %s closetime: %d",
-+ func,
-+ MASTER_CONNECTION(p)->sp->user,
-+ MASTER_CONNECTION(p)->sp->database,
-+ MASTER_CONNECTION(p)->closetime);
-+#endif
-+ if (MASTER_CONNECTION(p)->closetime < closetime)
-+ {
-+ closetime = MASTER_CONNECTION(p)->closetime;
-+ oldestp = p;
-+ }
-+ p++;
-+ }
-+
-+ p = oldestp;
-+ pool_send_frontend_exits(p);
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:discarding old %d th connection. user: %s database:
%s",
-+ func,
-+ oldestp - pool_connection_pool,
-+ MASTER_CONNECTION(p)->sp->user,
-+ MASTER_CONNECTION(p)->sp->database);
-+#endif
-+
-+ free(MASTER_CONNECTION(p)->sp->user);
-+ free(MASTER_CONNECTION(p)->sp->database);
-+ free(MASTER_CONNECTION(p)->sp->startup_packet);
-+ pool_close(MASTER_CONNECTION(p)->con);
-+
-+ memset(p, 0, sizeof(POOL_CONNECTION_POOL));
-+
-+ return new_connection(p);
-+}
-+
-+/*
-+ * set backend connection close timer
-+ */
-+void pool_connection_pool_timer(POOL_CONNECTION_POOL *backend)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "pool_connection_pool_timer()";
-+#endif
-+ POOL_CONNECTION_POOL *p = pool_connection_pool;
-+ int i;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:pool_connection_pool_timer: called",func);
-+#endif
-+
-+ MASTER_CONNECTION(backend)->closetime = time(NULL); /*
set connection close time */
-+
-+ if (Connection_Life_Time == 0)
-+ return;
-+
-+ /* look for any other timeout */
-+ for (i=0;i<Max_Pool;i++, p++)
-+ {
-+ if (!MASTER_CONNECTION(p))
-+ continue;
-+ if (MASTER_CONNECTION(p)->sp->user == NULL)
-+ continue;
-+
-+ if (p != backend && MASTER_CONNECTION(p)->closetime)
-+ return;
-+ }
-+
-+ /* no other timer found. set my timer */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: set alarm after %d seconds",func,
Connection_Life_Time);
-+#endif
-+ signal(SIGALRM, pool_backend_timer_handler);
-+ alarm(Connection_Life_Time);
-+}
-+
-+/*
-+ * backend connection close timer handler
-+ */
-+void pool_backend_timer_handler(int sig)
-+{
-+#define TMINTMAX 0x7fffffff
-+
-+#ifdef PRINT_DEBUG
-+ char * func = "pool_backend_timer_handler()";
-+#endif
-+ POOL_CONNECTION_POOL *p = pool_connection_pool;
-+ int i;
-+ time_t now;
-+ time_t nearest = TMINTMAX;
-+
-+ now = time(NULL);
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:called at %d", func,now);
-+#endif
-+
-+ for (i=0;i<Max_Pool;i++, p++)
-+ {
-+ if (!MASTER_CONNECTION(p))
-+ continue;
-+ if (MASTER_CONNECTION(p)->sp->user == NULL)
-+ continue;
-+
-+ /* timer expire? */
-+ if (MASTER_CONNECTION(p)->closetime)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: expire time: %d",
-+ func,
-+
MASTER_CONNECTION(p)->closetime+Connection_Life_Time);
-+#endif
-+
-+ if (now >=
(MASTER_CONNECTION(p)->closetime+Connection_Life_Time))
-+ {
-+ /* discard expired connection */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: expires user %s database %s",
func, MASTER_CONNECTION(p)->sp->user, MASTER_CONNECTION(p)->sp->database);
-+#endif
-+
-+ pool_send_frontend_exits(p);
-+
-+ free(MASTER_CONNECTION(p)->sp->user);
-+ free(MASTER_CONNECTION(p)->sp->database);
-+
free(MASTER_CONNECTION(p)->sp->startup_packet);
-+ pool_close(MASTER_CONNECTION(p)->con);
-+
-+ memset(p, 0, sizeof(POOL_CONNECTION_POOL));
-+ }
-+ else
-+ {
-+ /* look for nearest timer */
-+ if (MASTER_CONNECTION(p)->closetime < nearest)
-+ nearest =
MASTER_CONNECTION(p)->closetime;
-+ }
-+ }
-+ }
-+
-+ /* any remaining timer */
-+ if (nearest != TMINTMAX)
-+ {
-+ nearest = Connection_Life_Time - (now - nearest);
-+ if (nearest <= 0)
-+ nearest = 1;
-+ signal(SIGALRM, pool_backend_timer_handler);
-+ alarm(nearest);
-+ }
-+}
-+
-+int connect_inet_domain_socket(int secondary_backend)
-+{
-+ char * func = "connect_inet_domain_socket()";
-+ int fd;
-+ int len;
-+ int on = 1;
-+ struct sockaddr_in addr;
-+ struct hostent *hp;
-+
-+ fd = socket(AF_INET, SOCK_STREAM, 0);
-+ if (fd < 0)
-+ {
-+ show_error("%s: socket() failed: %s",func, strerror(errno));
-+ return -1;
-+ }
-+
-+ /* set nodelay */
-+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
-+ (char *) &on,
-+ sizeof(on)) < 0)
-+ {
-+ show_error("%s: setsockopt() failed: %s", func,
strerror(errno));
-+ close(fd);
-+ return -1;
-+ }
-+
-+ memset((char *) &addr, 0, sizeof(addr));
-+ ((struct sockaddr *)&addr)->sa_family = AF_INET;
-+
-+ addr.sin_port = htons(CurrentCluster->port);
-+ len = sizeof(struct sockaddr_in);
-+
-+ hp = gethostbyname(CurrentCluster->hostName);
-+
-+ if ((hp == NULL) || (hp->h_addrtype != AF_INET))
-+ {
-+ show_error("%s: gethostbyname() failed: %s host: %s",func,
strerror(errno), CurrentCluster->hostName);
-+ close(fd);
-+ return -1;
-+ }
-+ memmove((char *) &(addr.sin_addr),
-+ (char *) hp->h_addr,
-+ hp->h_length);
-+
-+ if (connect(fd, (struct sockaddr *)&addr, len) < 0)
-+ {
-+ show_error("%s: connect() failed: %s",func,strerror(errno));
-+ close(fd);
-+ return -1;
-+ }
-+ return fd;
-+}
-+
-+int connect_unix_domain_socket(int secondary_backend)
-+{
-+ char * func = "connect_unix_domain_socket()";
-+ struct sockaddr_un addr;
-+ int fd;
-+ int len;
-+ int port;
-+
-+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
-+ if (fd == -1)
-+ {
-+ show_error("%s: setsockopt() failed: %s",
func,strerror(errno));
-+ return -1;
-+ }
-+
-+ port = CurrentCluster->port;
-+ memset((char *) &addr, 0, sizeof(addr));
-+ ((struct sockaddr *)&addr)->sa_family = AF_UNIX;
-+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/.s.PGSQL.%d",
-+ Backend_Socket_Dir,
-+ CurrentCluster->port);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:postmaster Unix domain socket: %s",func,
addr.sun_path);
-+#endif
-+
-+ len = sizeof(struct sockaddr_un);
-+
-+ if (connect(fd, (struct sockaddr *)&addr, len) < 0)
-+ {
-+ show_error("%s: connect() failed: %s",func, strerror(errno));
-+ close(fd);
-+ return -1;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:connected to postmaster Unix domain socket: %s fd:
%d", func,addr.sun_path, fd);
-+#endif
-+ return fd;
-+}
-+
-+static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp,
int secondary_backend)
-+{
-+ char * func = "create_cp()";
-+ int fd;
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+
-+ if (gethostname(hostName,sizeof(hostName)) < 0)
-+ {
-+ show_error("%s:gethostname() failed.
(%s)",func,strerror(errno));
-+ return NULL;
-+ }
-+ if (PGRis_same_host(hostName,CurrentCluster->hostName) == 1)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:[%s] [%s] is
same",func,hostName,CurrentCluster->hostName);
-+#endif
-+ fd = connect_unix_domain_socket(secondary_backend);
-+ }
-+ else
-+ {
-+ fd = connect_inet_domain_socket(secondary_backend);
-+ }
-+
-+ if (fd < 0)
-+ {
-+ /* fatal error, notice to parent and exit */
-+ notice_backend_error();
-+ exit(1);
-+ }
-+
-+ cp->con = pool_open(fd);
-+ cp->closetime = 0;
-+ return cp;
-+}
-+
-+static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p)
-+{
-+ char * func = "new_connection()";
-+ /* create master connection */
-+ MASTER_CONNECTION(p) = malloc(sizeof(POOL_CONNECTION_POOL_SLOT));
-+ if (MASTER_CONNECTION(p) == NULL)
-+ {
-+ show_error("%s: malloc() failed [%s]",func,strerror(errno));
-+ return NULL;
-+ }
-+ create_cp(MASTER_CONNECTION(p), 0);
-+
-+ /* initialize Paramter Status save structure */
-+ if (pool_init_params(&MASTER(p)->params))
-+ {
-+ return NULL;
-+ }
-+ p->num = 1; /* number of slots */
-+
-+ return p;
-+}
-+
-+char PGRis_same_host(char * host1, char * host2)
-+{
-+ unsigned int ip1, ip2;
-+
-+ if ((host1 == NULL) || (host2 == NULL))
-+ {
-+ return 0;
-+ }
-+ ip1 = PGRget_ip_by_name( host1);
-+ ip2 = PGRget_ip_by_name( host2);
-+ if (ip1 == ip2)
-+ {
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void pool_finish(void)
-+{
-+ char * func = "pool_finish()";
-+ int i;
-+
-+ POOL_CONNECTION_POOL *p = pool_connection_pool;
-+return;
-+ if (p == NULL)
-+ {
-+ show_error("%s:pool_connection_pool is not initialized",func);
-+ return ;
-+ }
-+
-+ for (i=0 ; i<Max_Pool ; i++)
-+ {
-+ if (p == NULL)
-+ break;
-+ /*
-+ if (MASTER_CONNECTION(p)->sp->user != NULL)
-+ {
-+ free(MASTER_CONNECTION(p)->sp->user);
-+ MASTER_CONNECTION(p)->sp->user = NULL;
-+ }
-+ if (MASTER_CONNECTION(p)->sp->database != NULL)
-+ {
-+ free(MASTER_CONNECTION(p)->sp->database);
-+ MASTER_CONNECTION(p)->sp->database = NULL;
-+ }
-+ if (MASTER_CONNECTION(p)->sp->startup_packet != NULL)
-+ {
-+ free(MASTER_CONNECTION(p)->sp->startup_packet);
-+ MASTER_CONNECTION(p)->sp->startup_packet = NULL;
-+ }
-+ */
-+ if (MASTER_CONNECTION(p)->con != NULL)
-+ {
-+ pool_close(MASTER_CONNECTION(p)->con);
-+ MASTER_CONNECTION(p)->con = NULL;
-+ }
-+ memset(p, 0, sizeof(POOL_CONNECTION_POOL));
-+ p++;
-+ }
-+ free((char *)pool_connection_pool);
-+ pool_connection_pool = NULL;
-+}
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/pool_params.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_params.c
---- postgresql-8.1.2/src/pgcluster/pglb/pool_params.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_params.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,184 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * pool_params.c
-+ *
-+ * NOTE:
-+ * connection pool stuff
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ * Portions Copyright (c) 2003-2006 Tatsuo Ishii
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 <sys/time.h>
-+#include <time.h>
-+#include <stdlib.h>
-+#include <string.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+#define MAX_PARAM_ITEMS 128
-+
-+int pool_init_params(ParamStatus *params);
-+void pool_discard_params(ParamStatus *params);
-+char *pool_find_name(ParamStatus *params, char *name, int *pos);
-+int pool_get_param(ParamStatus *params, int index, char **name, char
**value);
-+int pool_add_param(ParamStatus *params, char *name, char *value);
-+void pool_param_debug_print(ParamStatus *params);
-+
-+/*
-+ * initialize parameter structure
-+ */
-+int pool_init_params(ParamStatus *params)
-+{
-+ char * func = "pool_init_params()";
-+
-+ params->num = 0;
-+ params->names = malloc(MAX_PARAM_ITEMS*sizeof(char *));
-+ if (params->names == NULL)
-+ {
-+ show_error("%s: cannot allocate memory",func);
-+ return -1;
-+ }
-+ params->values = malloc(MAX_PARAM_ITEMS*sizeof(char *));
-+ if (params->values == NULL)
-+ {
-+ show_error("%s: cannot allocate memory",func);
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * discard parameter structure
-+ */
-+void pool_discard_params(ParamStatus *params)
-+{
-+ int i;
-+
-+ for (i=0;i<params->num;i++)
-+ {
-+ free(params->names[i]);
-+ free(params->values[i]);
-+ }
-+ free(params->names);
-+ free(params->values);
-+}
-+
-+/*
-+ * find param value by name. if found, its value is returned
-+ * also, pos is set
-+ * if not found, NULL is returned
-+ */
-+char *pool_find_name(ParamStatus *params, char *name, int *pos)
-+{
-+ int i;
-+
-+ for (i=0;i<params->num;i++)
-+ {
-+ if (!strcmp(name, params->names[i]))
-+ {
-+ *pos = i;
-+ return params->values[i];
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * return name and value by index.
-+ */
-+int pool_get_param(ParamStatus *params, int index, char **name, char
**value)
-+{
-+ if (index < 0 || index >= params->num)
-+ return -1;
-+
-+ *name = params->names[index];
-+ *value = params->values[index];
-+
-+ return 0;
-+}
-+
-+/*
-+ * add or replace name/value pair
-+ */
-+int pool_add_param(ParamStatus *params, char *name, char *value)
-+{
-+ char * func = "pool_add_param()";
-+ int pos;
-+
-+ if (pool_find_name(params, name, &pos))
-+ {
-+ /* name already exists */
-+ if (strlen(params->values[pos]) < strlen(value))
-+ {
-+ params->values[pos] = realloc(params->values[pos],
strlen(value) + 1);
-+ if (params->values[pos] == NULL)
-+ {
-+ show_error("%s: cannot allocate memory",func);
-+ return -1;
-+ }
-+ }
-+ strcpy(params->values[pos], value);
-+ }
-+ else
-+ {
-+ int num;
-+
-+ /* add name/value pair */
-+ if (params->num >= MAX_PARAM_ITEMS)
-+ {
-+ show_error("%s: no more room for num",func);
-+ return -1;
-+ }
-+ num = params->num;
-+ params->names[num] = strdup(name);
-+ if (params->names[num] == NULL)
-+ {
-+ show_error("%s: cannot allocate memory",func);
-+ return -1;
-+ }
-+ params->values[num] = strdup(value);
-+ if (params->values[num] == NULL)
-+ {
-+ show_error("%s: cannot allocate memory",func);
-+ return -1;
-+ }
-+ params->num++;
-+ }
-+ return 0;
-+}
-+
-+void pool_param_debug_print(ParamStatus *params)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "pool_param_debug_print()";
-+#endif
-+ int i;
-+
-+ for (i=0;i<params->num;i++)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: No.%d: name: %s value: %s",func, i,
params->names[i], params->values[i]);
-+#endif
-+ }
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/pool_process_query.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_process_query.c
---- postgresql-8.1.2/src/pgcluster/pglb/pool_process_query.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_process_query.c 2006-02-02
22:32:08.000000000 +0100
-@@ -0,0 +1,2100 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * pool_process_query.c
-+ *
-+ * NOTE:
-+ * query processing stuff
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ * Portions Copyright (c) 2003-2006, Tatsuo Ishii
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 <errno.h>
-+#include <sys/types.h>
-+#include <sys/time.h>
-+#include <arpa/inet.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <netinet/in.h>
-+
-+#include "postgres_fe.h"
-+#include "libpq/pqcomm.h"
-+
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+POOL_STATUS pool_process_query(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend, int connection_reuse);
-+POOL_STATUS ErrorResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*backend);
-+void pool_enable_timeout(void);
-+void pool_disable_timeout(void);
-+int pool_check_fd(POOL_CONNECTION *cp, int notimeout);
-+void pool_send_frontend_exits(POOL_CONNECTION_POOL *backend);
-+POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+POOL_STATUS SimpleForwardToBackend(char kind, POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+POOL_STATUS ParameterStatus(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*backend);
-+void pool_send_error_message(POOL_CONNECTION *frontend, int protoMajor,
char *code, char *message, char *detail, char *hint, char *file, int line);
-+
-+
-+static POOL_STATUS Query(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*backend, char *query);
-+static POOL_STATUS ReadyForQuery(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend, int send_ready);
-+static POOL_STATUS CompleteCommandResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static int RowDescription(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*backend);
-+static POOL_STATUS AsciiRow(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*backend, short num_fields);
-+static POOL_STATUS BinaryRow(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend, short num_fields);
-+static POOL_STATUS CursorResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static POOL_STATUS NoticeResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static POOL_STATUS CopyInResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static POOL_STATUS CopyOutResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static POOL_STATUS CopyDataRows(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend, int copyin);
-+static POOL_STATUS EmptyQueryResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static POOL_STATUS FunctionCall(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static POOL_STATUS FunctionResultResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static POOL_STATUS ProcessFrontendResponse(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static int synchronize(POOL_CONNECTION *cp);
-+static void process_reporting(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend);
-+static int reset_backend(POOL_CONNECTION_POOL *backend, int qcnt);
-+static int load_balance_enabled(POOL_CONNECTION_POOL *backend, char *sql);
-+static void start_load_balance(POOL_CONNECTION_POOL *backend);
-+static void end_load_balance(POOL_CONNECTION_POOL *backend);
-+
-+static POOL_CONNECTION_POOL_SLOT *slots[MAX_CONNECTION_SLOTS];
-+
-+POOL_STATUS pool_process_query(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend,
-+ int
connection_reuse)
-+{
-+ char * func = "pool_process_query()";
-+ char kind, kind1; /* packet kind (backend) */
-+ char fkind; /* packet kind (frontend) */
-+ short num_fields = 0;
-+ fd_set readmask;
-+ fd_set writemask;
-+ fd_set exceptmask;
-+ int fds;
-+ POOL_STATUS status;
-+ int state; /* 0: ok to issue commands 1: waiting for "ready for
query" response */
-+ int qcnt;
-+
-+ frontend->no_forward = connection_reuse;
-+ qcnt = 0;
-+ state = 0;
-+
-+ for (;;)
-+ {
-+ kind = kind1 = 0;
-+ fkind = 0;
-+
-+ if (state == 0 && connection_reuse)
-+ {
-+ int st = 0;
-+
-+ /* send query for resetting connection such as
"ROLLBACK" "RESET ALL"... */
-+ st = reset_backend(backend, qcnt);
-+
-+ if (st < 0) /* error? */
-+ return POOL_END;
-+
-+ else if (st == 0) /* no query issued? */
-+ {
-+ qcnt++;
-+ continue;
-+ }
-+
-+ else if (st == 1) /* more query remains */
-+ {
-+ state = 1;
-+ qcnt++;
-+ continue;
-+ }
-+
-+ else if (st == 2) /* no more qury */
-+ {
-+ frontend->no_forward = 0;
-+ return POOL_CONTINUE;
-+ }
-+
-+ }
-+
-+ if ((!REPLICATION && MASTER(backend)->len == 0 &&
frontend->len == 0) ||
-+ (REPLICATION && MASTER(backend)->len == 0 &&
-+ SECONDARY(backend)->len == 0
-+ && frontend->len == 0))
-+ {
-+
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = 1;
-+ timeout.tv_usec = 0;
-+
-+ FD_ZERO(&readmask);
-+ FD_ZERO(&writemask);
-+ FD_ZERO(&exceptmask);
-+ if (!connection_reuse)
-+ FD_SET(frontend->fd, &readmask);
-+ FD_SET(MASTER(backend)->fd, &readmask);
-+ if (REPLICATION)
-+ FD_SET(SECONDARY(backend)->fd, &readmask);
-+ if (!connection_reuse)
-+ FD_SET(frontend->fd, &exceptmask);
-+ FD_SET(MASTER(backend)->fd, &exceptmask);
-+
-+ if (connection_reuse)
-+ {
-+ if (REPLICATION)
-+ fds =
select(Max(SECONDARY(backend)->fd, MASTER(backend)->fd) + 1,
-+ &readmask,
&writemask, &exceptmask, NULL);
-+ else
-+ fds = select(MASTER(backend)->fd+1,
&readmask, &writemask, &exceptmask, NULL);
-+ }
-+ else
-+ {
-+ if (REPLICATION)
-+ fds =
select(Max(SECONDARY(backend)->fd,
-+
Max(frontend->fd, MASTER(backend)->fd)+1),
-+ &readmask,
&writemask, &exceptmask, NULL);
-+ else
-+ fds = select(Max(frontend->fd,
MASTER(backend)->fd)+1,
-+ &readmask,
&writemask, &exceptmask, NULL);
-+ }
-+
-+ if (fds == -1)
-+ {
-+ if (errno == EINTR)
-+ continue;
-+
-+ show_error("%s:select() failed. reason:
%s",func, strerror(errno));
-+ return POOL_ERROR;
-+ }
-+
-+ if (fds == 0)
-+ {
-+ return POOL_CONTINUE;
-+ }
-+
-+ if (FD_ISSET(MASTER(backend)->fd, &readmask))
-+ {
-+ pool_read(MASTER(backend), &kind, 1);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:read kind from backend %c",
func,kind);
-+#endif
-+ }
-+
-+ if (REPLICATION && FD_ISSET(SECONDARY(backend)->fd,
&readmask))
-+ {
-+ pool_read(SECONDARY(backend), &kind1, 1);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:read kind from secondary
backend %c", func,kind1);
-+#endif
-+ }
-+
-+ if (!connection_reuse && FD_ISSET(frontend->fd,
&exceptmask))
-+ {
-+ return POOL_END;
-+ }
-+ if (FD_ISSET(MASTER(backend)->fd, &exceptmask))
-+ {
-+ return POOL_ERROR;
-+ }
-+
-+ if (!connection_reuse && FD_ISSET(frontend->fd,
&readmask))
-+ {
-+ status = ProcessFrontendResponse(frontend,
backend);
-+ if (status != POOL_CONTINUE)
-+ return status;
-+
-+ continue;
-+ }
-+ }
-+ else
-+ {
-+ if (MASTER(backend)->len > 0)
-+ {
-+ pool_read(MASTER(backend), &kind, 1);
-+ if (REPLICATION)
-+ {
-+ pool_read(SECONDARY(backend), &kind1,
1);
-+ if (kind == '\0' || kind != kind1)
-+ {
-+ show_error("%s: kind does not
match between backends master(%c) secondary(%c)",
-+ func,
kind, kind1);
-+
pool_send_error_message(frontend, MAJOR(backend), "XX000",
-+
"kind mismatch between backends", "",
-+
"check data consistency between master and secondary",
__FILE__, __LINE__);
-+
-+ if
(pool_config_replication_stop_on_mismatch)
-+ return POOL_FATAL;
-+ else
-+ return POOL_ERROR;
-+ }
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:read kind from backend pending
data %c len: %d po: %d", func, kind, MASTER(backend)->len,
MASTER(backend)->po);
-+#endif
-+ }
-+ if (frontend->len > 0)
-+ {
-+ status = ProcessFrontendResponse(frontend,
backend);
-+ if (status != POOL_CONTINUE)
-+ return status;
-+
-+ continue;
-+ }
-+ }
-+
-+ /* this is the synchronous point */
-+ if (REPLICATION)
-+ {
-+ if (kind == 0)
-+ {
-+ pool_read(MASTER(backend), &kind, 1);
-+ }
-+ if (kind1 == 0)
-+ {
-+ pool_read(SECONDARY(backend), &kind1, 1);
-+ }
-+ if (kind == '\0' || kind != kind1)
-+ {
-+ show_error("%s: kind does not match between
backends master(%c) secondary(%c)",
-+ func, kind, kind1);
-+ pool_send_error_message(frontend,
MAJOR(backend), "XX000",
-+
"kind mismatch between backends", "",
-+
"check data consistency between master and secondary", __FILE__, __LINE__);
-+
-+ if (pool_config_replication_stop_on_mismatch)
-+ return POOL_FATAL;
-+ else
-+ return POOL_ERROR;
-+ }
-+ }
-+
-+ /*
-+ * Prrocess backend Response
-+ */
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ switch (kind)
-+ {
-+ case 'G':
-+ /* CopyIn response */
-+ status = CopyInResponse(frontend,
backend);
-+ break;
-+ case 'S':
-+ /* Paramter Status */
-+ status = ParameterStatus(frontend,
backend);
-+ break;
-+ case 'Z':
-+ /* Ready for query */
-+ status = ReadyForQuery(frontend,
backend, 1);
-+ break;
-+ default:
-+ status =
SimpleForwardToFrontend(kind, frontend, backend);
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ switch (kind)
-+ {
-+ case 'A':
-+ /* Notification response */
-+ status =
NotificationResponse(frontend, backend);
-+ break;
-+
-+ case 'B':
-+ /* BinaryRow */
-+ status = BinaryRow(frontend, backend,
num_fields);
-+ break;
-+
-+ case 'C':
-+ /* Complete command response */
-+ status =
CompleteCommandResponse(frontend, backend);
-+ break;
-+
-+ case 'D':
-+ /* AsciiRow */
-+ status = AsciiRow(frontend, backend,
num_fields);
-+ break;
-+
-+ case 'E':
-+ /* Error Response */
-+ status = ErrorResponse(frontend,
backend);
-+ break;
-+
-+ case 'G':
-+ /* CopyIn Response */
-+ status = CopyInResponse(frontend,
backend);
-+ break;
-+
-+ case 'H':
-+ /* CopyOut Response */
-+ status = CopyOutResponse(frontend,
backend);
-+ break;
-+
-+ case 'I':
-+ /* Empty Query Response */
-+ status = EmptyQueryResponse(frontend,
backend);
-+ break;
-+
-+ case 'N':
-+ /* Notice Response */
-+ status = NoticeResponse(frontend,
backend);
-+ break;
-+
-+ case 'P':
-+ /* CursorResponse */
-+ status = CursorResponse(frontend,
backend);
-+ break;
-+
-+ case 'T':
-+ /* RowDescription */
-+ status = RowDescription(frontend,
backend);
-+ if (status < 0)
-+ return POOL_ERROR;
-+
-+ num_fields = status;
-+ status = POOL_CONTINUE;
-+ break;
-+
-+ case 'V':
-+ /* FunctionResultResponse and
FunctionVoidResponse */
-+ status =
FunctionResultResponse(frontend, backend);
-+ break;
-+
-+ case 'Z':
-+ /* Ready for query */
-+ status = ReadyForQuery(frontend,
backend, 1);
-+ break;
-+
-+ default:
-+ show_error("%s:Unknown message type
%c(%02x)",func, kind, kind);
-+ exit(1);
-+ }
-+ }
-+
-+ if (status != POOL_CONTINUE)
-+ return status;
-+
-+ if (kind == 'Z' && frontend->no_forward && state == 1)
-+ {
-+ state = 0;
-+ }
-+
-+ }
-+ return POOL_CONTINUE;
-+}
-+
-+static POOL_STATUS Query(POOL_CONNECTION *frontend,
-+ POOL_CONNECTION_POOL
*backend, char *query)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "Query()";
-+#endif
-+ char *string;
-+ int len;
-+ static char *sq = "show pool_status";
-+
-+ if (query == NULL)
-+ {
-+ /* read actual query */
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ if (pool_read(frontend, &len, sizeof(len)) < 0)
-+ return POOL_END;
-+ len = ntohl(len) - 4;
-+ string = pool_read2(frontend, len);
-+ }
-+ else
-+ string = pool_read_string(frontend, &len, 0);
-+
-+ if (string == NULL)
-+ return POOL_END;
-+ }
-+ else
-+ {
-+ len = strlen(query)+1;
-+ string = query;
-+ }
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: %s", func,string);
-+#endif
-+
-+ /* process status reporting? */
-+ if (strncasecmp(sq, string, strlen(sq)) == 0)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:process reporting",func);
-+#endif
-+ process_reporting(frontend, backend);
-+ return POOL_CONTINUE;
-+ }
-+
-+ /* load balance trick */
-+ if (load_balance_enabled(backend, string))
-+ start_load_balance(backend);
-+
-+ /* forward the query to the backend */
-+ pool_write(MASTER(backend), "Q", 1);
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ int sendlen = htonl(len + 4);
-+ pool_write(MASTER(backend), &sendlen, sizeof(sendlen));
-+ }
-+
-+ if (pool_write_and_flush(MASTER(backend), string, len) < 0)
-+ {
-+ return POOL_END;
-+ }
-+
-+ if (REPLICATION)
-+ {
-+ /* in "strict mode" we need to wait for master completing the
query */
-+ if (pool_config_replication_strict || STRICT_MODE(string))
-+ if (synchronize(MASTER(backend)))
-+ return POOL_END;
-+
-+ pool_write(SECONDARY(backend), "Q", 1);
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ int sendlen = htonl(len + 4);
-+ pool_write(SECONDARY(backend), &sendlen,
sizeof(sendlen));
-+ }
-+
-+ if (pool_write_and_flush(SECONDARY(backend), string, len) < 0)
-+ {
-+ return POOL_END;
-+ }
-+ }
-+ return POOL_CONTINUE;
-+}
-+
-+static POOL_STATUS ReadyForQuery(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend, int send_ready)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "ReadyForQuery()";
-+#endif
-+
-+ pool_flush(frontend);
-+
-+ if (send_ready)
-+ {
-+ pool_write(frontend, "Z", 1);
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ int len;
-+ signed char state;
-+
-+ if ((len = pool_read_message_length(backend)) < 0)
-+ return POOL_END;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: message length: %d", func, len);
-+#endif
-+
-+ len = htonl(len);
-+ pool_write(frontend, &len, sizeof(len));
-+
-+ state = pool_read_kind(backend);
-+ if (state < 0)
-+ return POOL_END;
-+
-+ /* set transaction state */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: transaction state: %c", func, state);
-+#endif
-+ MASTER(backend)->tstate = state;
-+ if (REPLICATION)
-+ SECONDARY(backend)->tstate = state;
-+
-+ pool_write(frontend, &state, 1);
-+ }
-+
-+ if (pool_flush(frontend))
-+ return POOL_END;
-+ }
-+
-+ /* end load balance mode */
-+ if (IN_LOAD_BALANCE)
-+ end_load_balance(backend);
-+
-+ return ProcessFrontendResponse(frontend, backend);
-+}
-+
-+static POOL_STATUS CompleteCommandResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ char * func = "CompleteCommandResponse()";
-+ char *string, *string1;
-+ int len, len1;
-+
-+ /* read command tag */
-+ string = pool_read_string(MASTER(backend), &len, 0);
-+ if (string == NULL)
-+ return POOL_END;
-+
-+ if (REPLICATION)
-+ {
-+ string1 = pool_read_string(SECONDARY(backend), &len1, 0);
-+ if (string1 == NULL)
-+ return POOL_END;
-+
-+ if (len != len1)
-+ {
-+ show_error("%s: message length does not match between
master(%d \"%s\",) and secondary(%d \"%s\",)",
-+ func, len, string, len1, string1);
-+ }
-+ }
-+
-+ /* forward to the frontend */
-+ pool_write(frontend, "C", 1);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: string: \"%s\"",func, string);
-+#endif
-+ if (pool_write(frontend, string, len) < 0)
-+ {
-+ return POOL_END;
-+ }
-+ return POOL_CONTINUE;
-+}
-+
-+static int RowDescription(POOL_CONNECTION *frontend,
-+ POOL_CONNECTION_POOL
*backend)
-+{
-+ char * func = "RowDescription()";
-+ short num_fields, num_fields1;
-+ int oid, mod;
-+ int oid1, mod1;
-+ short size, size1;
-+ char *string, *string1;
-+ int len, len1;
-+ int i;
-+
-+ /* # of fields (could be 0) */
-+ pool_read(MASTER(backend), &num_fields, sizeof(short));
-+ if (REPLICATION)
-+ {
-+ pool_read(SECONDARY(backend), &num_fields1, sizeof(short));
-+ if (num_fields != num_fields1)
-+ {
-+ show_error("%s: num_fields deos not match between
backends master(%d) and secondary(%d)",
-+ func, num_fields, num_fields1);
-+ return POOL_FATAL;
-+ }
-+ }
-+
-+ /* forward it to the frontend */
-+ pool_write(frontend, "T", 1);
-+ pool_write(frontend, &num_fields, sizeof(short));
-+
-+ num_fields = ntohs(num_fields);
-+ for (i = 0;i<num_fields;i++)
-+ {
-+ /* field name */
-+ string = pool_read_string(MASTER(backend), &len, 0);
-+ if (string == NULL)
-+ return POOL_END;
-+
-+ if (REPLICATION)
-+ {
-+ string1 = pool_read_string(SECONDARY(backend), &len1,
0);
-+ if (string == NULL)
-+ return POOL_END;
-+ if (len != len1)
-+ {
-+ show_error("%s: field length deos not match
between backends master(%d) and secondary(%d)",
-+ func, ntohl(len),
ntohl(len1));
-+ return POOL_FATAL;
-+ }
-+ }
-+
-+ pool_write(frontend, string, len);
-+
-+ /* oid */
-+ pool_read(MASTER(backend), &oid, sizeof(int));
-+ if (REPLICATION)
-+ {
-+ pool_read(SECONDARY(backend), &oid1, sizeof(int));
-+
-+ /* we do not regard oid mismatch as fatal */
-+ if (oid != oid1)
-+ {
-+ show_error("%s: field oid deos not match
between backends master(%d) and secondary(%d)",
-+ func, ntohl(oid),
ntohl(oid1));
-+ }
-+ }
-+ pool_write(frontend, &oid, sizeof(int));
-+
-+ /* size */
-+ pool_read(MASTER(backend), &size, sizeof(short));
-+ if (REPLICATION)
-+ {
-+ pool_read(SECONDARY(backend), &size1, sizeof(short));
-+ if (size1 != size1)
-+ {
-+ show_error("%s: field size deos not match
between backends master(%d) and secondary(%d)",
-+ func, ntohs(size),
ntohs(size1));
-+ return POOL_FATAL;
-+ }
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: field size:%d", func, ntohs(size));
-+#endif
-+ pool_write(frontend, &size, sizeof(short));
-+
-+ /* modifier */
-+ pool_read(MASTER(backend), &mod, sizeof(int));
-+ if (REPLICATION)
-+ {
-+ pool_read(SECONDARY(backend), &mod1, sizeof(int));
-+ if (mod != mod1)
-+ {
-+ show_error("%s: modifier deos not match
between backends master(%d) and secondary(%d)",
-+ func, ntohl(mod),
ntohl(mod1));
-+ }
-+ }
-+ pool_write(frontend, &mod, sizeof(int));
-+ }
-+
-+ return num_fields;
-+}
-+
-+static POOL_STATUS AsciiRow(POOL_CONNECTION *frontend,
-+ POOL_CONNECTION_POOL
*backend,
-+ short num_fields)
-+{
-+ char * func = "AsciiRow()";
-+ static char nullmap[8192], nullmap1[8192];
-+ int nbytes;
-+ int i;
-+ unsigned char mask;
-+ int size, size1;
-+ char *buf;
-+ char msgbuf[1024];
-+
-+ pool_write(frontend, "D", 1);
-+
-+ nbytes = (num_fields + 7)/8;
-+
-+ if (nbytes <= 0)
-+ return POOL_CONTINUE;
-+
-+ /* NULL map */
-+ pool_read(MASTER(backend), nullmap, nbytes);
-+ if (pool_write(frontend, nullmap, nbytes) < 0)
-+ return POOL_END;
-+
-+ if (REPLICATION)
-+ {
-+ if (pool_read(SECONDARY(backend), nullmap1, nbytes) < 0)
-+ return POOL_END;
-+
-+ if (memcmp(nullmap, nullmap1, nbytes))
-+ {
-+ /* XXX: NULLMAP maybe different among
-+ backends. If we were a paranoid, we have to treat
-+ this as a fatal error. However in the real world
-+ we'd better to adapt this situation. Just throw a
-+ log... */
-+ show_error("%s: NULLMAP differ between master and
secondary",func);
-+ }
-+ }
-+
-+ mask = 0;
-+
-+ for (i = 0;i<num_fields;i++)
-+ {
-+ if (mask == 0)
-+ mask = 0x80;
-+
-+ /* NOT NULL? */
-+ if (mask & nullmap[i/8])
-+ {
-+ /* field size */
-+ if (pool_read(MASTER(backend), &size, sizeof(int)) <
0)
-+ return POOL_END;
-+ }
-+
-+ if (REPLICATION && (mask & nullmap1[i/8]))
-+ {
-+ /* XXX: field size maybe different among
-+ backends. If we were a paranoid, we have to treat
-+ this as a fatal error. However in the real world
-+ we'd better to adapt this situation. Just throw a
-+ log... */
-+
-+ if (pool_read(SECONDARY(backend), &size1,
sizeof(int)) < 0)
-+ return POOL_END;
-+
-+ if (size != size1)
-+ show_error("%s: %d th field size does not
match between master(%d) and secondary(%d)",
-+ func, i, ntohl(size),
ntohl(size1));
-+ size1 = ntohl(size1) - 4;
-+ }
-+
-+ buf = NULL;
-+
-+ if (mask & nullmap[i/8])
-+ {
-+ /* forward to frontend */
-+ pool_write(frontend, &size, sizeof(int));
-+ size = ntohl(size) - 4;
-+
-+ /* read and send actual data only when size > 0 */
-+ if (size > 0)
-+ {
-+ buf = pool_read2(MASTER(backend), size);
-+ if (buf == NULL)
-+ return POOL_END;
-+ }
-+ }
-+
-+ if (REPLICATION && size1 > 0 && (mask & nullmap1[i/8]))
-+ {
-+ /* read and discard secondary data */
-+ if (pool_read2(SECONDARY(backend), size1) == NULL)
-+ return POOL_END;
-+ }
-+
-+ if (buf)
-+ {
-+ pool_write(frontend, buf, size);
-+ snprintf(msgbuf, Min(sizeof(msgbuf), size+1), "%s",
buf);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: len: %d data: %s", func, size,
msgbuf);
-+#endif
-+ }
-+
-+ mask >>= 1;
-+ }
-+
-+ return POOL_CONTINUE;
-+}
-+
-+static POOL_STATUS BinaryRow(POOL_CONNECTION *frontend,
-+ POOL_CONNECTION_POOL
*backend,
-+ short num_fields)
-+{
-+ char * func = "BinaryRow()";
-+ static char nullmap[8192], nullmap1[8192];
-+ int nbytes;
-+ int i;
-+ unsigned char mask;
-+ int size, size1;
-+ char *buf;
-+
-+ pool_write(frontend, "B", 1);
-+
-+ nbytes = (num_fields + 7)/8;
-+
-+ if (nbytes <= 0)
-+ return POOL_CONTINUE;
-+
-+ /* NULL map */
-+ pool_read(MASTER(backend), nullmap, nbytes);
-+ if (pool_write(frontend, nullmap, nbytes) < 0)
-+ return POOL_END;
-+
-+ if (REPLICATION)
-+ {
-+ if (pool_read(SECONDARY(backend), nullmap1, nbytes) < 0)
-+ return POOL_END;
-+
-+ if (memcmp(nullmap, nullmap1, nbytes))
-+ {
-+ /* XXX: NULLMAP maybe different among
-+ backends. If we were a paranoid, we have to treat
-+ this as a fatal error. However in the real world
-+ we'd better to adapt this situation. Just throw a
-+ log... */
-+ show_error("%s: NULLMAP differ between master and
secondary",func);
-+ }
-+ }
-+
-+ mask = 0;
-+
-+ for (i = 0;i<num_fields;i++)
-+ {
-+ if (mask == 0)
-+ mask = 0x80;
-+
-+ /* NOT NULL? */
-+ if (mask & nullmap[i/8])
-+ {
-+ /* field size */
-+ if (pool_read(MASTER(backend), &size, sizeof(int)) <
0)
-+ return POOL_END;
-+ }
-+
-+ if (REPLICATION && (mask & nullmap1[i/8]))
-+ {
-+ /* XXX: field size maybe different among
-+ backends. If we were a paranoid, we have to treat
-+ this as a fatal error. However in the real world
-+ we'd better to adapt this situation. Just throw a
-+ log... */
-+
-+ if (pool_read(SECONDARY(backend), &size1,
sizeof(int)) < 0)
-+ return POOL_END;
-+
-+ if (size != size1)
-+ show_error("%s: %d th field size does not
match between master(%d) and secondary(%d)",
-+ func, i, ntohl(size),
ntohl(size1));
-+ size1 = ntohl(size1) - 4;
-+ }
-+
-+ buf = NULL;
-+
-+ if (mask & nullmap[i/8])
-+ {
-+ /* forward to frontend */
-+ pool_write(frontend, &size, sizeof(int));
-+ size = ntohl(size) - 4;
-+
-+ /* read and send actual data only when size > 0 */
-+ if (size > 0)
-+ {
-+ buf = pool_read2(MASTER(backend), size);
-+ if (buf == NULL)
-+ return POOL_END;
-+ }
-+ }
-+
-+ if (REPLICATION && size1 > 0 && (mask & nullmap1[i/8]))
-+ {
-+ /* read and discard secondary data */
-+ if (pool_read2(SECONDARY(backend), size1) == NULL)
-+ return POOL_END;
-+ }
-+
-+ if (buf)
-+ pool_write(frontend, buf, size);
-+
-+ mask >>= 1;
-+ }
-+ return POOL_CONTINUE;
-+}
-+
-+static POOL_STATUS CursorResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ char * func = "CursorResponse()";
-+ char *string, *string1;
-+ int len, len1;
-+
-+ /* read cursor name */
-+ string = pool_read_string(MASTER(backend), &len, 0);
-+ if (string == NULL)
-+ return POOL_END;
-+ if (REPLICATION)
-+ {
-+ string1 = pool_read_string(SECONDARY(backend), &len1, 0);
-+ if (string1 == NULL)
-+ return POOL_END;
-+ if (len != len1)
-+ {
-+ show_error("%s: length does not match between
master(%d) and secondary(%d)",
-+ func, len, len1);
-+ show_error("%s: master(%s) secondary(%s)", func,
string, string1);
-+ return POOL_END;
-+ }
-+ }
-+
-+ /* forward to the frontend */
-+ pool_write(frontend, "P", 1);
-+ if (pool_write(frontend, string, len) < 0)
-+ {
-+ return POOL_END;
-+ }
-+ return POOL_CONTINUE;
-+}
-+
-+POOL_STATUS ErrorResponse(POOL_CONNECTION *frontend,
-+ POOL_CONNECTION_POOL
*backend)
-+{
-+ char *string;
-+ int len;
-+
-+ /* read error message */
-+ string = pool_read_string(MASTER(backend), &len, 0);
-+ if (string == NULL)
-+ return POOL_END;
-+ if (REPLICATION)
-+ {
-+ string = pool_read_string(SECONDARY(backend), &len, 0);
-+ if (string == NULL)
-+ return POOL_END;
-+ }
-+
-+ /* forward to the frontend */
-+ pool_write(frontend, "E", 1);
-+ if (pool_write_and_flush(frontend, string, len) < 0)
-+ return POOL_END;
-+
-+ return POOL_CONTINUE;
-+}
-+
-+static POOL_STATUS NoticeResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ char *string, *string1;
-+ int len, len1;
-+
-+ /* read notice message */
-+ string = pool_read_string(MASTER(backend), &len, 0);
-+ if (string == NULL)
-+ return POOL_END;
-+ if (REPLICATION)
-+ {
-+ string1 = pool_read_string(SECONDARY(backend), &len1, 0);
-+ if (string1 == NULL)
-+ return POOL_END;
-+ }
-+
-+ /* forward to the frontend */
-+ pool_write(frontend, "N", 1);
-+ if (pool_write_and_flush(frontend, string, len) < 0)
-+ {
-+ return POOL_END;
-+ }
-+ return POOL_CONTINUE;
-+}
-+
-+static POOL_STATUS CopyInResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ POOL_STATUS status;
-+
-+ /* forward to the frontend */
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ if (SimpleForwardToFrontend('G', frontend, backend) !=
POOL_CONTINUE)
-+ return POOL_END;
-+ if (pool_flush(frontend) != POOL_CONTINUE)
-+ return POOL_END;
-+ }
-+ else
-+ if (pool_write_and_flush(frontend, "G", 1) < 0)
-+ return POOL_END;
-+
-+ status = CopyDataRows(frontend, backend, 1);
-+ return status;
-+}
-+
-+static POOL_STATUS CopyOutResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ POOL_STATUS status;
-+
-+ /* forward to the frontend */
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ if (SimpleForwardToFrontend('H', frontend, backend) !=
POOL_CONTINUE)
-+ return POOL_END;
-+ if (pool_flush(frontend) != POOL_CONTINUE)
-+ return POOL_END;
-+ }
-+ else
-+ if (pool_write_and_flush(frontend, "H", 1) < 0)
-+ return POOL_END;
-+
-+ status = CopyDataRows(frontend, backend, 0);
-+ return status;
-+}
-+
-+static POOL_STATUS CopyDataRows(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend, int copyin)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "CopyDataRows()";
-+#endif
-+ char *string;
-+ int len;
-+
-+#ifdef PRINT_DEBUG
-+ int i = 0;
-+ char *buf;
-+#endif
-+
-+ for (;;)
-+ {
-+ if (copyin)
-+ {
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ char kind;
-+ POOL_STATUS status;
-+
-+ if (pool_read(frontend, &kind, 1) < 0)
-+ return POOL_END;
-+
-+ status = SimpleForwardToBackend(kind,
frontend, backend);
-+ if (status == POOL_END)
-+ return status;
-+
-+ /* CopyData? */
-+ if (kind == 'd')
-+ continue;
-+ else
-+ break;
-+ }
-+ else
-+ {
-+ string = pool_read_string(frontend, &len, 1);
-+ if (string == NULL)
-+ return POOL_END;
-+ }
-+ }
-+ else
-+ {
-+ /* CopyOut */
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ signed char kind;
-+ POOL_STATUS status;
-+
-+ if ((kind = pool_read_kind(backend)) < 0)
-+ return POOL_END;
-+
-+ status = SimpleForwardToFrontend(kind,
frontend, backend);
-+ if (status == POOL_END)
-+ return status;
-+
-+ /* CopyData? */
-+ if (kind == 'd')
-+ continue;
-+ else
-+ break;
-+ }
-+ else
-+ {
-+ string = pool_read_string(MASTER(backend),
&len, 1);
-+ if (REPLICATION)
-+ string =
pool_read_string(SECONDARY(backend), &len, 1);
-+ }
-+ }
-+
-+ if (string == NULL)
-+ return POOL_END;
-+
-+#ifdef PRINT_DEBUG
-+ buf = malloc(len + 1);
-+ if (buf == NULL)
-+ {
-+ show_error("CopyDataRows: malloc failed: %s",
strerror(errno));
-+ return POOL_END;
-+ }
-+ strncpy(buf, string, len);
-+ buf[len] = '\0';
-+ show_debug("%s: copy line %d %d bytes :%s:",func, i++, len,
buf);
-+ free(buf);
-+#endif
-+
-+ if (copyin)
-+ {
-+ pool_write(MASTER(backend), string, len);
-+ if (REPLICATION)
-+ pool_write(SECONDARY(backend), string, len);
-+ }
-+ else
-+ pool_write(frontend, string, len);

-+
-+ if (len == PROTO_MAJOR_V3)
-+ {
-+ /* end of copy? */
-+ if (string[0] == '\\' &&
-+ string[1] == '.' &&
-+ string[2] == '\n')
-+ {
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (copyin)
-+ {
-+ if (pool_flush(MASTER(backend)) <0)
-+ return POOL_END;
-+ if (REPLICATION)
-+ {
-+ if (pool_flush(SECONDARY(backend)) <0)
-+ return POOL_END;
-+ }
-+ }
-+ else
-+ if (pool_flush(frontend) <0)
-+ return POOL_END;
-+
-+ return POOL_CONTINUE;
-+}
-+
-+static POOL_STATUS EmptyQueryResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ char c;
-+
-+ if (pool_read(MASTER(backend), &c, sizeof(c)) < 0)
-+ return POOL_END;
-+
-+ if (REPLICATION)
-+ {
-+ if (pool_read(SECONDARY(backend), &c, sizeof(c)) < 0)
-+ return POOL_END;
-+ }
-+
-+ pool_write(frontend, "I", 1);
-+ return pool_write_and_flush(frontend, "", 1);
-+}
-+
-+static POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ int pid, pid1;
-+ char *condition, *condition1;
-+ int len, len1;
-+
-+ pool_write(frontend, "A", 1);
-+
-+ if (pool_read(MASTER(backend), &pid, sizeof(pid)) < 0)
-+ return POOL_ERROR;
-+
-+ if (REPLICATION)
-+ {
-+ if (pool_read(SECONDARY(backend), &pid1, sizeof(pid1)) < 0)
-+ return POOL_ERROR;
-+ }
-+
-+ condition = pool_read_string(MASTER(backend), &len, 0);
-+ if (condition == NULL)
-+ return POOL_END;
-+ if (REPLICATION)
-+ {
-+ condition1 = pool_read_string(SECONDARY(backend), &len1, 0);
-+ if (condition1 == NULL)
-+ return POOL_END;
-+ }
-+
-+ pool_write(frontend, &pid, sizeof(pid));
-+
-+ return pool_write_and_flush(frontend, condition, len);
-+}
-+
-+static POOL_STATUS FunctionCall(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ char dummy[2];
-+ int oid;
-+ int argn;
-+ int i;
-+
-+ pool_write(MASTER(backend), "F", 1);
-+ if (REPLICATION)
-+ pool_write(SECONDARY(backend), "F", 1);
-+
-+ /* dummy */
-+ if (pool_read(frontend, dummy, sizeof(dummy)) < 0)
-+ return POOL_ERROR;
-+ pool_write(MASTER(backend), dummy, sizeof(dummy));
-+ if (REPLICATION)
-+ pool_write(SECONDARY(backend), dummy, sizeof(dummy));
-+
-+ /* function object id */
-+ if (pool_read(frontend, &oid, sizeof(oid)) < 0)
-+ return POOL_ERROR;
-+
-+ pool_write(MASTER(backend), &oid, sizeof(oid));
-+ if (REPLICATION)
-+ pool_write(SECONDARY(backend), &oid, sizeof(oid));
-+
-+ /* number of arguments */
-+ if (pool_read(frontend, &argn, sizeof(argn)) < 0)
-+ return POOL_ERROR;
-+ pool_write(MASTER(backend), &argn, sizeof(argn));
-+ if (REPLICATION)
-+ pool_write(SECONDARY(backend), &argn, sizeof(argn));
-+
-+ argn = ntohl(argn);
-+
-+ for (i=0;i<argn;i++)
-+ {
-+ int len;
-+ char *arg;
-+
-+ /* length of each argument in bytes */
-+ if (pool_read(frontend, &len, sizeof(len)) < 0)
-+ return POOL_ERROR;
-+
-+ pool_write(MASTER(backend), &len, sizeof(len));
-+ if (REPLICATION)
-+ pool_write(SECONDARY(backend), &len, sizeof(len));
-+
-+ len = ntohl(len);
-+
-+ /* argument value itself */
-+ if ((arg = pool_read2(frontend, len)) == NULL)
-+ return POOL_ERROR;
-+ pool_write(MASTER(backend), arg, len);
-+ if (REPLICATION)
-+ pool_write(SECONDARY(backend), arg, len);
-+ }
-+
-+ if (pool_flush(MASTER(backend)))
-+ return POOL_ERROR;
-+ if (REPLICATION)
-+ if (pool_flush(SECONDARY(backend)))
-+ return POOL_ERROR;
-+ return POOL_CONTINUE;
-+}
-+
-+static POOL_STATUS FunctionResultResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ char dummy;
-+ int len;
-+ char *result;
-+
-+ pool_write(frontend, "V", 1);
-+
-+ if (pool_read(MASTER(backend), &dummy, 1) < 0)
-+ return POOL_ERROR;
-+ if (REPLICATION)
-+ if (pool_read(SECONDARY(backend), &dummy, 1) < 0)
-+ return POOL_ERROR;
-+
-+ pool_write(frontend, &dummy, 1);
-+
-+ /* non empty result? */
-+ if (dummy == 'G')
-+ {
-+ /* length of result in bytes */
-+ if (pool_read(MASTER(backend), &len, sizeof(len)) < 0)
-+ return POOL_ERROR;
-+ if (REPLICATION)
-+ if (pool_read(SECONDARY(backend), &len, sizeof(len))
< 0)
-+ return POOL_ERROR;
-+
-+ pool_write(frontend, &len, sizeof(len));
-+
-+ len = ntohl(len);
-+
-+ /* result value itself */
-+ if ((result = pool_read2(MASTER(backend), len)) == NULL)
-+ return POOL_ERROR;
-+ if (REPLICATION)
-+ if (pool_read(SECONDARY(backend), result, len) < 0)
-+ return POOL_ERROR;
-+
-+ pool_write(frontend, result, len);
-+ }
-+
-+ /* unused ('0') */
-+ if (pool_read(MASTER(backend), &dummy, 1) < 0)
-+ return POOL_ERROR;
-+ if (REPLICATION)
-+ if (pool_read(SECONDARY(backend), &dummy, 1) < 0)
-+ return POOL_ERROR;
-+
-+ pool_write(frontend, "0", 1);
-+
-+ return pool_flush(frontend);
-+}
-+
-+static POOL_STATUS ProcessFrontendResponse(POOL_CONNECTION *frontend,
-+
POOL_CONNECTION_POOL *backend)
-+{
-+ char * func = "ProcessFrontendResponse()";
-+ char fkind;
-+ POOL_STATUS status;
-+
-+ if (frontend->len <= 0 && frontend->no_forward != 0)
-+ return POOL_CONTINUE;
-+
-+ if (pool_read(frontend, &fkind, 1) < 0)
-+ {
-+ show_error("%s: failed to read kind",func);
-+ return POOL_END;
-+ }
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:read kind from frontend %c(%02x)", func, fkind, fkind);
-+#endif
-+
-+ switch (fkind)
-+ {
-+ case 'X':
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ int len;
-+ pool_read(frontend, &len, sizeof(len));
-+ }
-+ status = POOL_END;
-+ break;
-+
-+ case 'Q':
-+ status = Query(frontend, backend, NULL);
-+ break;
-+
-+ default:
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ status = SimpleForwardToBackend(fkind,
frontend, backend);
-+ if (pool_flush(MASTER(backend)))
-+ status = POOL_ERROR;
-+ if (REPLICATION)
-+ if (pool_flush(SECONDARY(backend)))
-+ status = POOL_ERROR;
-+ }
-+ else if (MAJOR(backend) == PROTO_MAJOR_V2 && fkind ==
'F')
-+ status = FunctionCall(frontend, backend);
-+ else
-+ {
-+ show_error("%s: unknown message type
%c(%02x)", func, fkind, fkind);
-+ status = POOL_ERROR;
-+ }
-+ break;
-+ }
-+
-+ return status;
-+}
-+
-+static int timeoutmsec;
-+/*
-+ * enable read timeout
-+ */
-+void pool_enable_timeout(void)
-+{
-+ timeoutmsec = pool_config_replication_timeout;
-+}
-+
-+/*
-+ * disable read timeout
-+ */
-+void pool_disable_timeout(void)
-+{
-+ timeoutmsec = 0;
-+}
-+
-+/*
-+ * wait until read data is ready
-+ */
-+static int synchronize(POOL_CONNECTION *cp)
-+{
-+ return pool_check_fd(cp, 1);
-+}
-+
-+/*
-+ * wait until read data is ready
-+ * if notimeout is non 0, wait forever.
-+ */
-+int pool_check_fd(POOL_CONNECTION *cp, int notimeout)
-+{
-+ char * func = "pool_check_fd()";
-+ fd_set readmask;
-+ fd_set exceptmask;
-+ int fd;
-+ int fds;
-+ struct timeval timeout;
-+ struct timeval *tp;
-+
-+ fd = cp->fd;
-+
-+ for (;;)
-+ {
-+ FD_ZERO(&readmask);
-+ FD_ZERO(&exceptmask);
-+ FD_SET(fd, &readmask);
-+ FD_SET(fd, &exceptmask);
-+
-+ if (notimeout || timeoutmsec == 0)
-+ tp = NULL;
-+ else
-+ {
-+ timeout.tv_sec = 0;
-+ timeout.tv_usec =
pool_config_replication_timeout*1000;
-+ tp = &timeout;
-+ }
-+
-+ fds = select(fd+1, &readmask, NULL, &exceptmask, tp);
-+
-+ if (fds == -1)
-+ {
-+ if (errno == EAGAIN || errno == EINTR)
-+ continue;
-+
-+ show_error("%s: select() failed. reason %s",func,
strerror(errno));
-+ break;
-+ }
-+
-+ if (FD_ISSET(fd, &exceptmask))
-+ {
-+ show_error("%s: exception occurred",func);
-+ break;
-+ }
-+
-+ if (fds == 0)
-+ {
-+ show_error("%s: data is not ready tp->tv_sec %d
tp->tp_usec %d", func, tp->tv_sec, tp->tv_usec);
-+ break;
-+ }
-+ return 0;
-+ }
-+ return -1;
-+}
-+
-+static void process_reporting(POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend)
-+{
-+ static char *cursorname = "blank";
-+ static short num_fields = 3;
-+ static char *field_names[] = {"item", "value", "description"};
-+ static int oid = 0;
-+ static short fsize = -1;
-+ static int mod = 0;
-+ short n;
-+ int i;
-+ short s;
-+ int len;
-+ short colnum;
-+
-+ static char nullmap[2] = {0xff, 0xff};
-+ int nbytes = (num_fields + 7)/8;
-+
-+#define MAXVALLEN 512
-+
-+ typedef struct {
-+ char *name;
-+ char value[MAXVALLEN+1];
-+ char *desc;
-+ } POOL_REPORT_STATUS;
-+
-+#define MAXITEMS 128
-+
-+ POOL_REPORT_STATUS status[MAXITEMS];
-+
-+ short nrows;
-+ int size;
-+ int hsize;
-+
-+ i = 0;
-+
-+ status[i].name = "inetdomain";
-+ snprintf(status[i].value, MAXVALLEN, "%d", pool_config_inetdomain);
-+ status[i].desc = "1 if accepting TCP/IP connection";
-+ i++;
-+
-+ status[i].name = "port";
-+ snprintf(status[i].value, MAXVALLEN, "%d", pool_config_port);
-+ status[i].desc = "pgpool accepting port number";
-+ i++;
-+
-+ status[i].name = "socket_dir";
-+ snprintf(status[i].value, MAXVALLEN, "%s", pool_config_socket_dir);
-+ status[i].desc = "pgpool socket directory";
-+ i++;
-+
-+ status[i].name = "backend_host_name";
-+ snprintf(status[i].value, MAXVALLEN, "%s",
pool_config_backend_host_name);
-+ status[i].desc = "master backend host name";
-+ i++;
-+
-+ status[i].name = "backend_port";
-+ snprintf(status[i].value, MAXVALLEN, "%d", pool_config_backend_port);
-+ status[i].desc = "master backend port number";
-+ i++;
-+
-+ status[i].name = "secondary_backend_host_name";
-+ snprintf(status[i].value, MAXVALLEN, "%s",
pool_config_secondary_backend_host_name);
-+ status[i].desc = "secondary backend host name";
-+ i++;
-+
-+ status[i].name = "secondary_backend_port";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_secondary_backend_port);
-+ status[i].desc = "secondary backend port number";
-+ i++;
-+
-+ status[i].name = "num_init_children";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_num_init_children);
-+ status[i].desc = "# of children initially pre-forked";
-+ i++;
-+
-+ status[i].name = "child_life_time";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_child_life_time);
-+ status[i].desc = "if idle for this seconds, child exits (not
implemented yet)";
-+ i++;
-+
-+ status[i].name = "connection_life_time";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_connection_life_time);
-+ status[i].desc = "if idle for this seconds, connection closes";
-+ i++;
-+
-+ status[i].name = "max_pool";
-+ snprintf(status[i].value, MAXVALLEN, "%d", pool_config_max_pool);
-+ status[i].desc = "max # of connection pool per child";
-+ i++;
-+
-+ status[i].name = "logdir";
-+ snprintf(status[i].value, MAXVALLEN, "%s", pool_config_logdir);
-+ status[i].desc = "logging directory";
-+ i++;
-+
-+ status[i].name = "backend_socket_dir";
-+ snprintf(status[i].value, MAXVALLEN, "%s",
pool_config_backend_socket_dir);
-+ status[i].desc = "Unix domain socket directory for the PostgreSQL
server";
-+ i++;
-+
-+ status[i].name = "replication_mode";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_replication_mode);
-+ status[i].desc = "non 0 if operating in replication mode";
-+ i++;
-+
-+ status[i].name = "replication_strict";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_replication_strict);
-+ status[i].desc = "non 0 if operating in strict mode";
-+ i++;
-+
-+ status[i].name = "replication_timeout";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_replication_timeout);
-+ status[i].desc = "if secondary does not respond in this milli
seconds, abort the session";
-+ i++;
-+
-+ status[i].name = "current_backend_host_name";
-+ snprintf(status[i].value, MAXVALLEN, "%s",
pool_config_current_backend_host_name);
-+ status[i].desc = "current master host name";
-+ i++;
-+
-+ status[i].name = "current_backend_port";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_current_backend_port);
-+ status[i].desc = "current master port #";
-+ i++;
-+
-+ status[i].name = "replication_enabled";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_replication_enabled);
-+ status[i].desc = "non 0 if actually operating in replication mode";
-+ i++;
-+
-+ status[i].name = "load_balance_mode";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_load_balance_mode);
-+ status[i].desc = "non 0 if operating in load balancing mode";
-+ i++;
-+
-+ status[i].name = "replication_stop_on_mismatch";
-+ snprintf(status[i].value, MAXVALLEN, "%d",
pool_config_replication_stop_on_mismatch);
-+ status[i].desc = "stop replication mode on fatal error";
-+ i++;
-+
-+ nrows = i;
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V2)
-+ {
-+ /* cursor response */
-+ pool_write(frontend, "P", 1);
-+ pool_write(frontend, cursorname, strlen(cursorname)+1);
-+ }
-+
-+ /* row description */
-+ pool_write(frontend, "T", 1);
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ len = sizeof(num_fields) + sizeof(len);
-+
-+ for (i=0;i<num_fields;i++)
-+ {
-+ char *f = field_names[i];
-+ len += strlen(f)+1;
-+ len += sizeof(oid);
-+ len += sizeof(colnum);
-+ len += sizeof(oid);
-+ len += sizeof(s);
-+ len += sizeof(mod);
-+ len += sizeof(s);
-+ }
-+
-+ len = htonl(len);
-+ pool_write(frontend, &len, sizeof(len));
-+ }
-+
-+ n = htons(num_fields);
-+ pool_write(frontend, &n, sizeof(short));
-+
-+ for (i=0;i<num_fields;i++)
-+ {
-+ char *f = field_names[i];
-+
-+ pool_write(frontend, f, strlen(f)+1); /* field name
*/
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ pool_write(frontend, &oid, sizeof(oid)); /*
table oid */
-+ colnum = htons(i);
-+ pool_write(frontend, &colnum, sizeof(colnum)); /*
column number */
-+ }
-+
-+ pool_write(frontend, &oid, sizeof(oid)); /*
data type oid */
-+ s = htons(fsize);
-+ pool_write(frontend, &s, sizeof(fsize)); /*
field size */
-+ pool_write(frontend, &mod, sizeof(mod)); /*
modifier */
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ s = htons(0);
-+ pool_write(frontend, &s, sizeof(fsize)); /*
field format (text) */
-+ }
-+ }
-+ pool_flush(frontend);
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V2)
-+ {
-+ /* ascii row */
-+ for (i=0;i<nrows;i++)
-+ {
-+ pool_write(frontend, "D", 1);
-+ pool_write_and_flush(frontend, nullmap, nbytes);
-+
-+ size = strlen(status[i].name);
-+ hsize = htonl(size+4);
-+ pool_write(frontend, &hsize, sizeof(hsize));
-+ pool_write(frontend, status[i].name, size);
-+
-+ size = strlen(status[i].value);
-+ hsize = htonl(size+4);
-+ pool_write(frontend, &hsize, sizeof(hsize));
-+ pool_write(frontend, status[i].value, size);
-+
-+ size = strlen(status[i].desc);
-+ hsize = htonl(size+4);
-+ pool_write(frontend, &hsize, sizeof(hsize));
-+ pool_write(frontend, status[i].desc, size);
-+ }
-+ }
-+ else
-+ {
-+ /* data row */
-+ for (i=0;i<nrows;i++)
-+ {
-+ pool_write(frontend, "D", 1);
-+ len = sizeof(len) + sizeof(nrows);
-+ len += sizeof(int) + strlen(status[i].name);
-+ len += sizeof(int) + strlen(status[i].value);
-+ len += sizeof(int) + strlen(status[i].desc);
-+ len = htonl(len);
-+ pool_write(frontend, &len, sizeof(len));
-+ s = htons(3);
-+ pool_write(frontend, &s, sizeof(s));
-+
-+ len = htonl(strlen(status[i].name));
-+ pool_write(frontend, &len, sizeof(len));
-+ pool_write(frontend, status[i].name,
strlen(status[i].name));
-+
-+ len = htonl(strlen(status[i].value));
-+ pool_write(frontend, &len, sizeof(len));
-+ pool_write(frontend, status[i].value,
strlen(status[i].value));
-+
-+ len = htonl(strlen(status[i].desc));
-+ pool_write(frontend, &len, sizeof(len));
-+ pool_write(frontend, status[i].desc,
strlen(status[i].desc));
-+ }
-+ }
-+
-+ /* complete command response */
-+ pool_write(frontend, "C", 1);
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ len = htonl(sizeof(len) + strlen("SELECT")+1);
-+ pool_write(frontend, &len, sizeof(len));
-+ }
-+ pool_write(frontend, "SELECT", strlen("SELECT")+1);
-+
-+ /* ready for query */
-+ pool_write(frontend, "Z", 1);
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ len = htonl(sizeof(len) + 1);
-+ pool_write(frontend, &len, sizeof(len));
-+ pool_write(frontend, "I", 1);
-+ }
-+
-+ pool_flush(frontend);
-+}
-+
-+void pool_send_frontend_exits(POOL_CONNECTION_POOL *backend)
-+{
-+ int len;
-+
-+ pool_write(MASTER(backend), "X", 1);
-+
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ len = htonl(4);
-+ pool_write(MASTER(backend), &len, sizeof(len));
-+ }
-+
-+ /*
-+ * XXX we cannot call pool_flush() here since backend may already
-+ * close the socket and pool_flush() automatically invokes fail
-+ * over handler. This could happen in copy command (remember the
-+ * famouse "lostsynchronization with server, resettin g
-+ * connection" message)
-+ */
-+ fflush(MASTER(backend)->write_fd);
-+
-+ if (REPLICATION)
-+ {
-+ pool_write(SECONDARY(backend), "X", 1);
-+ if (MAJOR(backend) == PROTO_MAJOR_V3)
-+ {
-+ len = htonl(4);
-+ pool_write(MASTER(backend), &len, sizeof(len));
-+ }
-+ fflush(SECONDARY(backend)->write_fd);
-+ }
-+}
-+
-+/*
-+ * -------------------------------------------------------
-+ * V3 functions
-+ * -------------------------------------------------------
-+ */
-+POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend)
-+{
-+ char * func = "SimpleForwardToFrontend()";
-+ int len, len1;
-+ char *p;
-+ int status;
-+
-+ pool_write(frontend, &kind, 1);
-+
-+ status = pool_read(MASTER(backend), &len, sizeof(len));
-+ if (status < 0)
-+ {
-+ show_error("%s: error while reading message length",func);
-+ return POOL_END;
-+ }
-+
-+ if (REPLICATION)
-+ {
-+ status = pool_read(SECONDARY(backend), &len1, sizeof(len1));
-+ if (status < 0)
-+ {
-+ show_error("%s: error while reading message length
from secondary backend",func);
-+ return POOL_END;
-+ }
-+
-+ if (len != len1)
-+ {
-+ show_error("%s: length does not match between
backends master(%d) secondary(%d) kind:(%c)",
-+ func, ntohl(len), ntohl(len1), kind);
-+ }
-+ }
-+
-+ pool_write(frontend, &len, sizeof(len));
-+
-+ len = ntohl(len);
-+ len -= 4;
-+
-+ p = pool_read2(MASTER(backend), len);
-+ if (p == NULL)
-+ return POOL_END;
-+
-+ if (REPLICATION)
-+ {
-+ len1 = ntohl(len1);
-+ len1 -= 4;
-+ if (pool_read2(SECONDARY(backend), len1) == NULL)
-+ return POOL_END;
-+ }
-+
-+ return pool_write(frontend, p, len);
-+}
-+
-+POOL_STATUS SimpleForwardToBackend(char kind, POOL_CONNECTION *frontend,
POOL_CONNECTION_POOL *backend)
-+{
-+ int len;
-+ int sendlen;
-+ char *p;
-+
-+ if (pool_write(MASTER(backend), &kind, 1))
-+ return POOL_END;
-+ if (REPLICATION)
-+ if (pool_write(SECONDARY(backend), &kind, 1))
-+ return POOL_END;
-+
-+ if (pool_read(frontend, &sendlen, sizeof(sendlen)))
-+ {
-+ return POOL_END;
-+ }
-+
-+ len = ntohl(sendlen) - 4;
-+
-+ p = pool_read2(frontend, len);
-+ if (p == NULL)
-+ return POOL_END;
-+
-+ if (pool_write(MASTER(backend), &sendlen, sizeof(sendlen)))
-+ return POOL_END;
-+ if (pool_write(MASTER(backend), p, len))
-+ return POOL_END;
-+
-+ if (REPLICATION)
-+ {
-+ if (pool_write(SECONDARY(backend), &sendlen, sizeof(sendlen)))
-+ return POOL_END;
-+ if (pool_write(SECONDARY(backend), p, len))
-+ return POOL_END;
-+ }
-+
-+ return POOL_CONTINUE;
-+}
-+
-+POOL_STATUS ParameterStatus(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
*backend)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "ParameterStatus()";
-+#endif
-+ int len;
-+ int sendlen;
-+ char *p;
-+ char *name;
-+ char *value;
-+
-+ pool_write(frontend, "S", 1);
-+
-+ len = pool_read_message_length(backend);
-+ if (len < 0)
-+ {
-+ return POOL_END;
-+ }
-+
-+ sendlen = htonl(len);
-+ pool_write(frontend, &sendlen, sizeof(sendlen));
-+
-+ len -= 4;
-+
-+ p = pool_read2(MASTER(backend), len);
-+ if (p == NULL)
-+ return POOL_END;
-+
-+ name = p;
-+ value = p + strlen(name) + 1;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:name: %s value: %s",func, name, value);
-+#endif
-+
-+ pool_add_param(&MASTER(backend)->params, name, value);
-+
-+#ifdef PRINT_DEBUG
-+ pool_param_debug_print(&MASTER(backend)->params);
-+#endif
-+
-+ if (REPLICATION)
-+ if (pool_read2(SECONDARY(backend), len) == NULL)
-+ return POOL_END;
-+
-+ return pool_write(frontend, p, len);
-+
-+}
-+
-+/*
-+ * reset backend status. return values are:
-+ * 0: no query was issued 1: a query was issued 2: no more queries remain
-1: error
-+ */
-+static int reset_backend(POOL_CONNECTION_POOL *backend, int qcnt)
-+{
-+#ifdef NO_RESET_ALL
-+ static char *queries[] = {"ABORT"};
-+#else
-+ static char *queries[] = {"ABORT", "RESET ALL"};
-+#endif
-+
-+ char *query;
-+ int qn = sizeof(queries)/sizeof(char *);
-+
-+ /* for PGCluster */
-+ if (!Use_Connection_Pool)
-+ return 2;
-+
-+ if (qcnt >= qn)
-+ return 2;
-+
-+ query = queries[qcnt];
-+
-+ /* if transaction state is idle, we don't need to issue ABORT */
-+ if (TSTATE(backend) == 'I' && !strcmp("ABORT", query))
-+ return 0;
-+
-+ if (Query(NULL, backend, query) != POOL_CONTINUE)
-+ return -1;
-+
-+ return 1;
-+}
-+
-+/*
-+ * return non 0 if load balance is possible
-+ */
-+static int load_balance_enabled(POOL_CONNECTION_POOL *backend, char *sql)
-+{
-+ if (pool_config_load_balance_mode &&
-+ REPLICATION &&
-+ MAJOR(backend) == PROTO_MAJOR_V3 &&
-+ TSTATE(backend) == 'I' &&
-+ !strncasecmp(sql, "SELECT", 6))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * start load balance mode
-+ */
-+static void start_load_balance(POOL_CONNECTION_POOL *backend)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "start_load_balance()";
-+#endif
-+ int i;
-+ int master;
-+
-+ /* save backend connection slots */
-+ for (i=0;i<backend->num;i++)
-+ {
-+ slots[i] = backend->slots[i];
-+ }
-+
-+ /* temporary turn off replication mode */
-+ /*REPLICATION = 0; */
-+
-+ /* choose a master in random manner */
-+ master = random() % backend->num;
-+ backend->slots[0] = slots[master];
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: selected master is %d", func,master);
-+#endif
-+
-+ /* start load balancing */
-+ /*in_load_balance = 1;*/
-+}
-+
-+/*
-+ * finish load balance mode
-+ */
-+static void end_load_balance(POOL_CONNECTION_POOL *backend)
-+{
-+ int i;
-+
-+ /* restore backend connection slots */
-+ for (i=0;i<backend->num;i++)
-+ {
-+ backend->slots[i] = slots[i];
-+ }
-+
-+ /* turn on replication mode */
-+ /* REPLICATION = 1; */
-+
-+ /*in_load_balance = 0;*/
-+#ifdef PRINT_DEBUG
-+ show_debug("end_load_balance: end load balance mode");
-+#endif
-+}
-+
-+/*
-+ * send error message to frontend
-+ */
-+void pool_send_error_message(POOL_CONNECTION *frontend, int protoMajor,
-+ char *code,
-+ char *message,
-+ char *detail,
-+ char *hint,
-+ char *file,
-+ int line)
-+{
-+#define MAXDATA 1024
-+#define MAXMSGBUF 128
-+ char * func = "pool_send_error_message()";
-+
-+ if (protoMajor == PROTO_MAJOR_V2)
-+ {
-+ pool_write(frontend, "E", 1);
-+ pool_write_and_flush(frontend, message, strlen(message)+1);
-+ }
-+ else if (protoMajor == PROTO_MAJOR_V3)
-+ {
-+ char data[MAXDATA];
-+ char msgbuf[MAXMSGBUF];
-+ int len;
-+ int thislen;
-+ int sendlen;
-+
-+ len = 0;
-+
-+ pool_write(frontend, "E", 1);
-+
-+ /* error level */
-+ thislen = snprintf(msgbuf, MAXMSGBUF, "SERROR");
-+ memcpy(data +len, msgbuf, thislen+1);
-+ len += thislen + 1;
-+
-+ /* code */
-+ thislen = snprintf(msgbuf, MAXMSGBUF, "C%s", code);
-+ memcpy(data +len, msgbuf, thislen+1);
-+ len += thislen + 1;
-+
-+ /* message */
-+ thislen = snprintf(msgbuf, MAXMSGBUF, "M%s", message);
-+ memcpy(data +len, msgbuf, thislen+1);
-+ len += thislen + 1;
-+
-+ /* detail */
-+ if (*detail != '\0')
-+ {
-+ thislen = snprintf(msgbuf, MAXMSGBUF, "D%s", detail);
-+ memcpy(data +len, msgbuf, thislen+1);
-+ len += thislen + 1;
-+ }
-+
-+ /* hint */
-+ if (*hint != '\0')
-+ {
-+ thislen = snprintf(msgbuf, MAXMSGBUF, "H%s", hint);
-+ memcpy(data +len, msgbuf, thislen+1);
-+ len += thislen + 1;
-+ }
-+
-+ /* file */
-+ thislen = snprintf(msgbuf, MAXMSGBUF, "F%s", file);
-+ memcpy(data +len, msgbuf, thislen+1);
-+ len += thislen + 1;
-+
-+ /* line */
-+ thislen = snprintf(msgbuf, MAXMSGBUF, "L%d", line);
-+ memcpy(data +len, msgbuf, thislen+1);
-+ len += thislen + 1;
-+
-+ /* stop null */
-+ len++;
-+ *(data + len) = '\0';
-+
-+ sendlen = len;
-+ len = htonl(len + 4);
-+ pool_write(frontend, &len, sizeof(len));
-+ pool_write_and_flush(frontend, data, sendlen);
-+ }
-+ else
-+ show_error("%s: unknown protocol major %d",func, protoMajor);
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/pool_stream.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_stream.c
---- postgresql-8.1.2/src/pgcluster/pglb/pool_stream.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/pool_stream.c 2006-02-02
22:30:03.000000000 +0100
-@@ -0,0 +1,585 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * pool_stream.c
-+ *
-+ * NOTE:
-+ * stream I/O modules
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ * Portions Copyright (c) 2003-2006 Tatsuo Ishii
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+* 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 <stdlib.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <sys/types.h>
-+#include <unistd.h>
-+#include <sys/time.h>
-+
-+#include "postgres_fe.h"
-+#include "libpq/pqcomm.h"
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+#define READBUFSZ 1024
-+
-+POOL_CONNECTION *pool_open(int fd);
-+void pool_close(POOL_CONNECTION *cp);
-+int pool_read(POOL_CONNECTION *cp, void *buf, int len);
-+char *pool_read2(POOL_CONNECTION *cp, int len);
-+int pool_write(POOL_CONNECTION *cp, void *buf, int len);
-+int pool_flush(POOL_CONNECTION *cp);
-+int pool_write_and_flush(POOL_CONNECTION *cp, void *buf, int len);
-+char *pool_read_string(POOL_CONNECTION *cp, int *len, int line);
-+
-+static int mystrlen(char *str, int upper, int *flag);
-+static int mystrlinelen(char *str, int upper, int *flag);
-+static int save_pending_data(POOL_CONNECTION *cp, void *data, int len);
-+static int consume_pending_data(POOL_CONNECTION *cp, void *data, int len);
-+
-+
-+/*
-+* open read/write file descriptors.
-+* returns POOL_CONNECTION on success otherwise NULL.
-+*/
-+POOL_CONNECTION *pool_open(int fd)
-+{
-+ POOL_CONNECTION *cp;
-+
-+ cp = (POOL_CONNECTION *)malloc(sizeof(POOL_CONNECTION));
-+ if (cp == NULL)
-+ {
-+ show_error("pool_open: malloc failed: %s", strerror(errno));
-+ return NULL;
-+ }
-+
-+ memset(cp, 0, sizeof(*cp));
-+
-+ cp->write_fd = fdopen(fd, "w");
-+ if (cp->write_fd == NULL)
-+ {
-+ show_error("pool_open: fdopen failed: %s",strerror(errno));
-+ free(cp);
-+ return NULL;
-+ }
-+
-+ /* initialize pending data buffer */
-+ cp->hp = malloc(READBUFSZ);
-+ if (cp->hp == NULL)
-+ {
-+ show_error("pool_open: malloc failed");
-+ return NULL;
-+ }
-+ cp->bufsz = READBUFSZ;
-+ cp->po = 0;
-+ cp->len = 0;
-+ cp->sbuf = NULL;
-+ cp->sbufsz = 0;
-+ cp->buf2 = NULL;
-+ cp->sbufsz = 0;
-+
-+ cp->fd = fd;
-+ return cp;
-+}
-+
-+/*
-+* close read/write file descriptors.
-+*/
-+void pool_close(POOL_CONNECTION *cp)
-+{
-+ close(cp->fd);
-+ fclose(cp->write_fd);
-+ free(cp->hp);
-+ if (cp->sbuf)
-+ free(cp->sbuf);
-+ if (cp->buf2)
-+ free(cp->buf2);
-+ pool_discard_params(&cp->params);
-+ free(cp);
-+}
-+
-+/*
-+* read len bytes from cp
-+* returns 0 on success otherwise -1.
-+*/
-+int pool_read(POOL_CONNECTION *cp, void *buf, int len)
-+{
-+ static char readbuf[READBUFSZ];
-+
-+ int consume_size;
-+ int readlen;
-+ char * ptr = (char *)buf;
-+
-+ consume_size = consume_pending_data(cp, ptr, len);
-+ len -= consume_size;
-+ ptr += consume_size;
-+
-+ while (len > 0)
-+ {
-+ if (cp->issecondary_backend)
-+ {
-+ if (pool_check_fd(cp, 0))
-+ {
-+ show_error("pool_read: secondary data is not
ready. abort this session");
-+ exit(1);
-+ }
-+ }
-+
-+ readlen = read(cp->fd, readbuf, READBUFSZ);
-+ if (readlen == -1)
-+ {
-+ show_error("pool_read: read failed (%s)",
strerror(errno));
-+
-+ if (cp->isbackend)
-+ {
-+ /* fatal error, notice to parent and exit */
-+ notice_backend_error();
-+ exit(1);
-+ }
-+ else
-+ {
-+ return -1;
-+ }
-+ }
-+ else if (readlen == 0)
-+ {
-+ show_error("pool_read: EOF encountered");
-+
-+ if (cp->isbackend)
-+ {
-+ /* fatal error, notice to parent and exit */
-+ notice_backend_error();
-+ exit(1);
-+ }
-+ else
-+ {
-+ /*
-+ * if backend offers authentication method,
frontend could close connection
-+ */
-+ return -1;
-+ }
-+ }
-+
-+ if (len < readlen)
-+ {
-+ /* overrun. we need to save remaining data to pending
buffer */
-+ if (save_pending_data(cp, readbuf+len, readlen-len))
-+ return -1;
-+ memmove(ptr, readbuf, len);
-+ break;
-+ }
-+
-+ memmove(ptr, readbuf, readlen);
-+ ptr += readlen;
-+ len -= readlen;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+* read exactly len bytes from cp
-+* returns buffer address on success otherwise NULL.
-+*/
-+char *pool_read2(POOL_CONNECTION *cp, int len)
-+{
-+ char *buf;
-+ int req_size;
-+ int alloc_size;
-+ int consume_size;
-+ int readlen;
-+
-+ req_size = cp->len + len;
-+
-+ if (req_size > cp->bufsz2)
-+ {
-+ alloc_size = ((req_size+1)/READBUFSZ+1)*READBUFSZ;
-+ cp->buf2 = realloc(cp->buf2, alloc_size);
-+ if (cp->buf2 == NULL)
-+ {
-+ show_error("pool_read2: failed to realloc");
-+ exit(1);
-+ }
-+ cp->bufsz2 = alloc_size;
-+ }
-+
-+ buf = cp->buf2;
-+
-+ consume_size = consume_pending_data(cp, buf, len);
-+ len -= consume_size;
-+ buf += consume_size;
-+
-+ while (len > 0)
-+ {
-+ if (cp->issecondary_backend)
-+ {
-+ if (pool_check_fd(cp, 0))
-+ {
-+ show_error("pool_read2: secondary data is not
ready. abort this session");
-+ exit(1);
-+ }
-+ }
-+
-+ readlen = read(cp->fd, buf, len);
-+ if (readlen == -1)
-+ {
-+ show_error("pool_read2: read failed (%s)",
strerror(errno));
-+
-+ if (cp->isbackend)
-+ {
-+ /* fatal error, notice to parent and exit */
-+ notice_backend_error();
-+ exit(1);
-+ }
-+ else
-+ {
-+ return NULL;
-+ }
-+ }
-+ else if (readlen == 0)
-+ {
-+ show_error("pool_read2: EOF encountered");
-+
-+ if (cp->isbackend)
-+ {
-+ /* fatal error, notice to parent and exit */
-+ notice_backend_error();
-+ exit(1);
-+ }
-+ else
-+ {
-+ /*
-+ * if backend offers authentication method,
frontend could close connection
-+ */
-+ return NULL;
-+ }
-+ }
-+
-+ buf += readlen;
-+ len -= readlen;
-+ }
-+
-+ return cp->buf2;
-+}
-+
-+/*
-+* write len bytes from cp
-+* returns 0 on success otherwise -1.
-+*/
-+int pool_write(POOL_CONNECTION *cp, void *buf, int len)
-+{
-+ if (!cp->no_forward)
-+ fwrite(buf, len, 1, cp->write_fd);
-+
-+ return 0;
-+}
-+
-+/*
-+* flush write buffer
-+*/
-+int pool_flush(POOL_CONNECTION *cp)
-+{
-+ if (fflush(cp->write_fd) != 0)
-+ {
-+ show_error("pool_flush: fflush failed (%s)", strerror(errno));
-+
-+ if (cp->isbackend)
-+ {
-+ notice_backend_error();
-+ exit(1);
-+ }
-+ else
-+ {
-+ return -1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/*
-+* combo of pool_write and pool_flush
-+*/
-+int pool_write_and_flush(POOL_CONNECTION *cp, void *buf, int len)
-+{
-+ if (pool_write(cp, buf, len))
-+ return -1;
-+ return pool_flush(cp);
-+}
-+
-+/*
-+ * read a string until EOF or NULL is encountered.
-+ * if line is not 0, read until new line is encountered.
-+*/
-+char *pool_read_string(POOL_CONNECTION *cp, int *len, int line)
-+{
-+ int readp;
-+ int readsize;
-+ int readlen;
-+ int strlength;
-+ int flag;
-+ int consume_size;
-+
-+#ifdef DEBUG
-+ static char pbuf[READBUFSZ];
-+#endif
-+
-+ *len = 0;
-+ readp = 0;
-+
-+ /* initialize read buffer */
-+ if (cp->sbufsz == 0)
-+ {
-+ cp->sbuf = malloc(READBUFSZ);
-+ if (cp->sbuf == NULL)
-+ {
-+ show_error("pool_read_string: malloc failed");
-+ return NULL;
-+ }
-+ cp->sbufsz = READBUFSZ;
-+ *cp->sbuf = '\0';
-+ }
-+
-+ /* any pending data? */
-+ if (cp->len)
-+ {
-+ if (line)
-+ strlength = mystrlinelen(cp->hp+cp->po, cp->len,
&flag);
-+ else
-+ strlength = mystrlen(cp->hp+cp->po, cp->len, &flag);
-+
-+ /* buffer is too small? */
-+ if ((strlength + 1) > cp->sbufsz)
-+ {
-+ cp->sbufsz = ((strlength+1)/READBUFSZ+1)*READBUFSZ;
-+ cp->sbuf = realloc(cp->sbuf, cp->sbufsz);
-+ if (cp->sbuf == NULL)
-+ {
-+ show_error("pool_read_string: realloc
failed");
-+ return NULL;
-+ }
-+ }
-+
-+ /* consume pending and save to read string buffer */
-+ consume_size = consume_pending_data(cp, cp->sbuf, strlength);
-+
-+ *len = strlength;
-+
-+ /* is the string null terminated? */
-+ if (consume_size == strlength && !flag)
-+ {
-+ /* not null or line terminated.
-+ * we need to read more since we have not encountered
NULL or new line yet
-+ */
-+ readsize = cp->sbufsz - strlength;
-+ readp = strlength;
-+ }
-+ else
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("pool_read_string: read all from pending
data. po:%d len:%d",
-+ cp->po, cp->len);
-+#endif
-+ return cp->sbuf;
-+ }
-+ } else
-+ {
-+ readsize = cp->sbufsz;
-+ }
-+
-+
-+ for (;;)
-+ {
-+ readlen = read(cp->fd, cp->sbuf+readp, readsize);
-+ if (readlen == -1)
-+ {
-+ show_error("pool_read_string: read() failed.
reason:%s", strerror(errno));
-+
-+ if (cp->isbackend)
-+ {
-+ notice_backend_error();
-+ exit(1);
-+ }
-+ else
-+ {
-+ return NULL;
-+ }
-+ }
-+
-+ if (readlen == 0)
-+ return NULL;
-+
-+ /* check overrun */
-+ if (line)
-+ strlength = mystrlinelen(cp->sbuf+readp, readlen,
&flag);
-+ else
-+ strlength = mystrlen(cp->sbuf+readp, readlen, &flag);
-+
-+ if (strlength < readlen)
-+ {
-+ save_pending_data(cp, cp->sbuf+readp+strlength,
readlen-strlength);
-+ *len += strlength;
-+#ifdef PRINT_DEBUG
-+ show_debug("pool_read_string: total result %d with
pending data po:%d len:%d", *len, cp->po, cp->len);
-+#endif
-+ return cp->sbuf;
-+ }
-+
-+ *len += readlen;
-+
-+ /* encountered null or newline? */
-+ if (flag)
-+ {
-+ /* ok we have read all data */
-+#ifdef PRINT_DEBUG
-+ show_debug("pool_read_string: total result %d ",
*len);
-+#endif
-+ break;
-+ }
-+
-+ readp += readlen;
-+ readsize = READBUFSZ;
-+
-+ if ((*len+readsize) > cp->sbufsz)
-+ {
-+ cp->sbufsz += READBUFSZ;
-+
-+ cp->sbuf = realloc(cp->sbuf, cp->sbufsz);
-+ if (cp->sbuf == NULL)
-+ {
-+ show_error("pool_read_string: realloc
failed");
-+ return NULL;
-+ }
-+ }
-+ }
-+ return cp->sbuf;
-+}
-+
-+/*
-+ * returns the byte length of str, including \0, no more than upper.
-+ * if encountered \0, flag is set to non 0.
-+ * example:
-+ * mystrlen("abc", 2) returns 2
-+ * mystrlen("abc", 3) returns 3
-+ * mystrlen("abc", 4) returns 4
-+ * mystrlen("abc", 5) returns 4
-+ */
-+static int mystrlen(char *str, int upper, int *flag)
-+{
-+ int len;
-+
-+ *flag = 0;
-+
-+ for (len = 0;len < upper; len++, str++)
-+ {
-+ if (!*str)
-+ {
-+ len++;
-+ *flag = 1;
-+ break;
-+ }
-+ }
-+ return len;
-+}
-+
-+/*
-+ * returns the byte length of str terminated by \n or \0 (including \n or
\0), no more than upper.
-+ * if encountered \0 or \n, flag is set to non 0.
-+ * example:
-+ * mystrlinelen("abc", 2) returns 2
-+ * mystrlinelen("abc", 3) returns 3
-+ * mystrlinelen("abc", 4) returns 4
-+ * mystrlinelen("abc", 5) returns 4
-+ * mystrlinelen("abcd\nefg", 4) returns 4
-+ * mystrlinelen("abcd\nefg", 5) returns 5
-+ * mystrlinelen("abcd\nefg", 6) returns 5
-+ */
-+static int mystrlinelen(char *str, int upper, int *flag)
-+{
-+ int len;
-+
-+ *flag = 0;
-+
-+ for (len = 0;len < upper; len++, str++)
-+ {
-+ if (!*str || *str == '\n')
-+ {
-+ len++;
-+ *flag = 1;
-+ break;
-+ }
-+ }
-+ return len;
-+}
-+
-+/*
-+ * save pending data
-+ */
-+static int save_pending_data(POOL_CONNECTION *cp, void *data, int len)
-+{
-+ int reqlen;
-+ size_t realloc_size;
-+ char *p;
-+
-+ /* to be safe */
-+ if (cp->len == 0)
-+ cp->po = 0;
-+
-+ reqlen = cp->po + cp->len + len;
-+
-+ /* pending buffer is enough? */
-+ if (reqlen > cp->bufsz)
-+ {
-+ /* too small, enlarge it */
-+ realloc_size = (reqlen/READBUFSZ+1)*READBUFSZ;
-+ p = realloc(cp->hp, realloc_size);
-+ if (p == NULL)
-+ {
-+ show_error("save_pending_data: realloc failed");
-+ return -1;
-+ }
-+
-+ cp->bufsz = realloc_size;
-+ cp->hp = p;
-+ }
-+
-+ memmove(cp->hp + cp->po + cp->len, data, len);
-+ cp->len += len;
-+
-+ return 0;
-+}
-+
-+/*
-+ * consume pending data. returns actually consumed data length.
-+ */
-+static int consume_pending_data(POOL_CONNECTION *cp, void *data, int len)
-+{
-+ int consume_size;
-+
-+ if (cp->len <= 0)
-+ return 0;
-+
-+ consume_size = Min(len, cp->len);
-+ memmove(data, cp->hp + cp->po, consume_size);
-+ cp->len -= consume_size;
-+
-+ if (cp->len <= 0)
-+ cp->po = 0;
-+ else
-+ cp->po += consume_size;
-+
-+ return consume_size;
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/recovery.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/recovery.c
---- postgresql-8.1.2/src/pgcluster/pglb/recovery.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/recovery.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,234 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * recovery.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at pglb for the recovery.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 <unistd.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <ctype.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/msg.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <sys/param.h>
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#ifdef HAVE_SYS_SELECT_H
-+#include <sys/select.h>
-+#endif
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+void PGRrecovery_main(void);
-+
-+static int set_recovery(RecoveryPacket *packet);
-+static int receive_recovery(int fd);
-+
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRrecovery_main()
-+ * NOTES
-+ * main module of recovery function
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+void
-+PGRrecovery_main(void)
-+{
-+ char * func = "PGRrecovery_main()";
-+ int fd = -1;
-+ int rtn;
-+
-+ fd = PGRcreate_recv_socket("", Recovery_Port_Number);
-+ if (fd < 0)
-+ {
-+ show_error("%s:PGRcreate_recv_socket failed",func);
-+ exit(1);
-+ }
-+
-+ for (;;)
-+ {
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = 60;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(fd,&rmask);
-+ rtn = select(fd+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+ if (rtn && FD_ISSET(fd, &rmask))
-+ {
-+ receive_recovery(fd);
-+ }
-+ }
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * set_recovery()
-+ * NOTES
-+ * check a recovery request from replication server
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static int
-+set_recovery(RecoveryPacket *packet)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "set_recovery()";
-+#endif
-+ int status = STATUS_OK;
-+ ClusterTbl key;
-+ ClusterTbl * ptr;
-+
-+ PGRset_key_of_cluster(&key,packet);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:received no:%d",func, ntohs(packet->packet_no));
-+#endif
-+ switch (ntohs(packet->packet_no))
-+ {
-+ case RECOVERY_PREPARE_REQ:
-+ /* add cluster db */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:add_db host:%s port:%d max:%d",
-+ func,
packet->hostName,ntohs(packet->port),ntohs(packet->max_connect));
-+#endif
-+ ptr = PGRsearch_cluster_tbl(&key);
-+ if (ptr == NULL)
-+ {
-+ ptr = PGRadd_cluster_tbl(&key);
-+ }
-+ if (ptr != NULL)
-+ {
-+ PGRset_status_on_cluster_tbl(TBL_STOP,ptr);
-+ if (Use_Connection_Pool)
-+ {
-+ signal(SIGCHLD,PGRrecreate_child);
-+ status = PGRpre_fork_child(ptr);
-+ }
-+ }
-+ break;
-+ case RECOVERY_FINISH:
-+ /* start cluster db */
-+ ptr = PGRsearch_cluster_tbl(&key);
-+ if (ptr != NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:start_db host:%s port:%d max:%d",
-+
func,packet->hostName,ntohs(packet->port),ntohs(packet->max_connect));
-+#endif
-+ PGRset_status_on_cluster_tbl(TBL_USE,ptr);
-+ }
-+ break;
-+ case RECOVERY_PGDATA_ANS:
-+ /* stop cluster db */
-+ ptr = PGRsearch_cluster_tbl(&key);
-+ if (ptr != NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:stop_db host:%s port:%d max:%d",
-+ func,
packet->hostName,ntohs(packet->port),ntohs(packet->max_connect));
-+#endif
-+ PGRset_status_on_cluster_tbl(TBL_STOP,ptr);
-+ }
-+ break;
-+ case RECOVERY_ERROR:
-+ /* delete cluster db */
-+ ptr = PGRsearch_cluster_tbl(&key);
-+ if (ptr != NULL)
-+ {
-+ PGRset_status_on_cluster_tbl(TBL_FREE,ptr);
-+ if (Use_Connection_Pool)
-+ {
-+ PGRquit_children_on_cluster(ptr->rec_no);
-+ }
-+ }
-+ break;
-+ /* cluster db has error */
-+ case RECOVERY_ERROR_CONNECTION:
-+ /* set error cluster db */
-+ ptr = PGRsearch_cluster_tbl(&key);
-+ if (ptr != NULL)
-+ {
-+ PGRset_status_on_cluster_tbl(TBL_ERROR,ptr);
-+ if (Use_Connection_Pool)
-+ {
-+ PGRquit_children_on_cluster(ptr->rec_no);
-+ }
-+ }
-+ break;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+receive_recovery(int fd)
-+{
-+ int status = STATUS_ERROR;
-+ int r_size = -1;
-+ int recv_sock = -1;
-+ RecoveryPacket packet;
-+
-+ recv_sock = PGRcreate_acception(fd,"",Recovery_Port_Number);
-+ if (recv_sock >= 0 )
-+ {
-+ memset(&packet,0, sizeof(RecoveryPacket));
-+ r_size = PGRread_byte(recv_sock,(char
*)&packet,sizeof(RecoveryPacket),MSG_WAITALL);
-+ if ( r_size == sizeof(RecoveryPacket) )
-+ {
-+ status = set_recovery(&packet);
-+ }
-+ }
-+ PGRclose_sock(&recv_sock);
-+ return status;
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pglb/socket.c
pgcluster-1.5.0rc7/src/pgcluster/pglb/socket.c
---- postgresql-8.1.2/src/pgcluster/pglb/socket.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pglb/socket.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,395 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * socket.c
-+ *
-+ * NOTE:
-+ * This file is composed of the communication modules
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+/*
-+ * 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 "postgres.h"
-+#include <stdio.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <sys/wait.h>
-+#include <ctype.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/un.h>
-+#include <sys/ipc.h>
-+#include <netdb.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <sys/param.h>
-+#include <sys/file.h>
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+
-+#ifdef HAVE_SYS_SELECT_H
-+#include <sys/select.h>
-+#endif
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#include "replicate_com.h"
-+#include "pglb.h"
-+
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+int PGRcreate_unix_domain_socket(char * sock_dir, unsigned short port);
-+int PGRcreate_recv_socket(char * hostName , unsigned short portNumber);
-+int PGRcreate_acception(int fd, char * hostName , unsigned short
portNumber);
-+void PGRclose_sock(int * sock);
-+int PGRread_byte(int sock,char * buf,int len, int flag);
-+int PGRcreate_cluster_socket( int * sock, ClusterTbl * ptr );
-+
-+static int create_send_socket(int * fdP, char * hostName , unsigned short
portNumber);
-+
-+
-+/*
-+* create UNIX domain socket
-+*/
-+int
-+PGRcreate_unix_domain_socket(char * sock_dir, unsigned short port)
-+{
-+ char * func = "PGRcreate_unix_domain_socket()";
-+ struct sockaddr_un addr;
-+ int fd;
-+ int status;
-+ int len;
-+
-+ /* set unix domain socket path */
-+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
-+ if (fd == -1)
-+ {
-+ show_error("%s:Failed to create UNIX domain socket. reason:
%s",func, strerror(errno));
-+ return -1;
-+ }
-+ memset((char *) &addr, 0, sizeof(addr));
-+ ((struct sockaddr *)&addr)->sa_family = AF_UNIX;
-+ snprintf(addr.sun_path, sizeof(addr.sun_path),
"%s/.s.PGSQL.%d",sock_dir,port);
-+ len = sizeof(struct sockaddr_un);
-+ status = bind(fd, (struct sockaddr *)&addr, len);
-+ if (status == -1)
-+ {
-+ show_error("%s: bind() failed. reason: %s", func,
strerror(errno));
-+ return -1;
-+ }
-+
-+ if (chmod(addr.sun_path, 0777) == -1)
-+ {
-+ show_error("%s: chmod() failed. reason: %s", func,
strerror(errno));
-+ return -1;
-+ }
-+
-+ status = listen(fd, PGLB_MAX_SOCKET_QUEUE);
-+ if (status < 0)
-+ {
-+ show_error("%s: listen() failed. reason: %s", func,
strerror(errno));
-+ return -1;
-+ }
-+ return fd;
-+}
-+
-+int
-+PGRcreate_recv_socket(char * hostName , unsigned short portNumber)
-+{
-+ char * func = "PGRcreate_recv_socket()";
-+ int fd,err;
-+ size_t len = 0;
-+ struct sockaddr_in addr;
-+ int one = 1;
-+
-+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-+ {
-+ show_error("%s: socket() failed. (%s)", func,
strerror(errno));
-+ return -1;
-+ }
-+ if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one))) == -1)
-+ {
-+ PGRclose_sock(&fd);
-+ show_error("%s: setsockopt() failed. (%s)",func,
strerror(errno));
-+ return -1;
-+ }
-+ addr.sin_family = AF_INET;
-+ if (hostName[0] == '\0')
-+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
-+ else
-+ {
-+ struct hostent *hp;
-+
-+ hp = gethostbyname(hostName);
-+ if ((hp == NULL) || (hp->h_addrtype != AF_INET))
-+ {
-+ PGRclose_sock(&fd);
-+ return -1;
-+ }
-+ memmove((char *) &(addr.sin_addr), (char *) hp->h_addr,
hp->h_length);
-+ }
-+
-+ addr.sin_port = htons(portNumber);
-+ len = sizeof(struct sockaddr_in);
-+
-+ err = bind(fd, (struct sockaddr *) & addr, len);
-+ if (err < 0)
-+ {
-+ PGRclose_sock(&fd);
-+ show_error("%s: bind() failed. (%s)",func, strerror(errno));
-+ return -1;
-+ }
-+ err = listen(fd, PGLB_MAX_SOCKET_QUEUE);
-+ if (err < 0)
-+ {
-+ PGRclose_sock(&fd);
-+ show_error("%s: listen() failed. (%s)", func,
strerror(errno));
-+ return -1;
-+ }
-+ return fd;
-+}
-+
-+int
-+PGRcreate_acception(int fd, char * hostName , unsigned short portNumber)
-+{
-+ char * func = "PGRcreate_acception()";
-+ int sock;
-+ struct sockaddr addr;
-+ size_t len = 0;
-+ int one = 1;
-+ int count;
-+
-+ len = sizeof(struct sockaddr);
-+ count = 0;
-+ while ((sock = accept(fd,&addr,&len)) < 0)
-+ {
-+ show_error("%s:accept error",func);
-+ PGRclose_sock(&fd);
-+ if ( count > PGLB_CONNECT_RETRY_TIME)
-+ {
-+ return -1;
-+ }
-+ fd = PGRcreate_recv_socket(hostName , portNumber);
-+ count ++;
-+ }
-+
-+ count = 0;
-+ while (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &one,
sizeof(one)) < 0)
-+ {
-+ show_error("%s: setsockopt TCP_NODELAY error (%s)",func,
strerror(errno));
-+ if ( count > PGLB_CONNECT_RETRY_TIME)
-+ {
-+ return -1;
-+ }
-+ count ++;
-+ }
-+ count = 0;
-+ while (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
sizeof(one)) < 0)
-+ {
-+ show_error("%s:setsockopt SO_KEEPALIVE error
(%s)",func,strerror(errno));
-+ if ( count > PGLB_CONNECT_RETRY_TIME)
-+ {
-+ return -1;
-+ }
-+ count ++;
-+ }
-+
-+ return sock;
-+}
-+
-+void
-+PGRclose_sock(int * sock)
-+{
-+ close(*sock);
-+ *sock = -1;
-+}
-+
-+int
-+PGRread_byte(int sock,char * buf,int len, int flag)
-+{
-+ char * func = "PGRread_byte()";
-+ int r;
-+ char * read_ptr;
-+ int read_size = 0;
-+ int max_buf_size ;
-+ int pid;
-+
-+ pid = getpid();
-+ max_buf_size = len;
-+ read_ptr = (char*)buf;
-+ for (;;)
-+ {
-+ r = recv(sock,read_ptr + read_size ,max_buf_size - read_size,
flag);
-+ if (r < 0)
-+ {
-+ if (errno == EINTR)
-+ {
-+ continue;
-+ }
-+#ifdef EAGAIN
-+ if (errno == EAGAIN)
-+ {
-+ return read_size;
-+ }
-+#endif
-+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
-+ if (errno == EWOULDBLOCK)
-+ {
-+ show_error("%s:no data
(%s)",func,strerror(errno));
-+ return read_size;
-+ }
-+#endif
-+#ifdef ECONNRESET
-+ if (errno == ECONNRESET)
-+ {
-+ PGRclose_sock(&sock);
-+ show_error("%s:connection reset (%s)",func,
strerror(errno));
-+ return -1;
-+ }
-+#endif
-+ show_error("%s:recv() failed.
(%s)",func,strerror(errno));
-+ read_size = -1;
-+ break;
-+ }
-+ if (r > 0)
-+ {
-+ read_size += r;
-+ if (max_buf_size == read_size)
-+ {
-+ break;
-+ }
-+ break;
-+ }
-+ if (read_size)
-+ {
-+ return read_size;
-+ }
-+ else
-+ {
-+ return -1;
-+ }
-+ }
-+
-+ return read_size;
-+}
-+
-+int
-+PGRcreate_cluster_socket( int * sock, ClusterTbl * ptr )
-+{
-+ char * func = "PGRcreate_cluster_socket()";
-+ int status = STATUS_ERROR;
-+
-+ /*
-+ if (PGRis_connection_full(ptr) == 1)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ */
-+ if (ptr != (ClusterTbl *) NULL)
-+ {
-+ status = create_send_socket(sock, ptr->hostName, ptr->port)
;
-+ }
-+ else
-+ {
-+ show_error("%s:ClusterTbl is not initialize",func);
-+ }
-+ return status;
-+}
-+
-+static int
-+create_send_socket(int * fdP, char * hostName , unsigned short portNumber)
-+{
-+ char * func = "create_send_socket()";
-+ int sock;
-+ size_t len = 0;
-+ struct sockaddr_in addr;
-+ int fd;
-+ int one = 1;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: host:%s port:%d",func, hostName,portNumber);
-+#endif
-+
-+ memset((char *)&addr,0,sizeof(addr));
-+
-+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-+ {
-+ * fdP = -1;
-+
-+ show_error("%s:socket() failed. (%s)",func, strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one))) == -1)
-+ {
-+ PGRclose_sock(&fd);
-+ * fdP = -1;
-+ show_error("%s:setsockopt() failed. (%s)", func,
strerror(errno));
-+ return STATUS_ERROR;
-+ return STATUS_ERROR;
-+ }
-+ if ((setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
sizeof(one))) == -1)
-+ {
-+ PGRclose_sock(&fd);
-+ * fdP = -1;
-+ show_error("%s:setsockopt() failed. (%s)", func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one,
sizeof(one)) < 0)
-+ {
-+ PGRclose_sock(&fd);
-+ * fdP = -1;
-+ show_error("%s:setsockopt() failed. (%s)",func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+
-+ addr.sin_family = AF_INET;
-+ if (hostName[0] == '\0')
-+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
-+ else
-+ {
-+ struct hostent *hp;
-+
-+ hp = gethostbyname(hostName);
-+ if ((hp == NULL) || (hp->h_addrtype != AF_INET))
-+ {
-+ PGRclose_sock(&fd);
-+ * fdP = -1;
-+ return STATUS_ERROR;
-+ }
-+ memmove((char *) &(addr.sin_addr), (char *) hp->h_addr,
hp->h_length);
-+ }
-+
-+ addr.sin_port = htons(portNumber);
-+ len = sizeof(struct sockaddr_in);
-+
-+ if ((sock = connect(fd,(struct sockaddr*)&addr,len)) < 0)
-+ {
-+ PGRclose_sock(&fd);
-+ * fdP = -1;
-+ return STATUS_ERROR;
-+ }
-+
-+ * fdP = fd;
-+ return STATUS_OK;
-+}
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/AUTHORS
pgcluster-1.5.0rc7/src/pgcluster/pgrp/AUTHORS
---- postgresql-8.1.2/src/pgcluster/pgrp/AUTHORS 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/AUTHORS 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,3 @@
-+Authors of pglb
-+
-+pglb was written by Atsushi Mitani
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/COPYING
pgcluster-1.5.0rc7/src/pgcluster/pgrp/COPYING
---- postgresql-8.1.2/src/pgcluster/pgrp/COPYING 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/COPYING 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,12 @@
-+Copyright (c) 2003 Atsushi Mitani
-+
-+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.
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/Makefile
pgcluster-1.5.0rc7/src/pgcluster/pgrp/Makefile
---- postgresql-8.1.2/src/pgcluster/pgrp/Makefile 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/Makefile 2006-01-31
15:14:33.000000000 +0100
-@@ -0,0 +1,39 @@
-+#-------------------------------------------------------------------------
-+#
-+# Makefile for src/pgcluster/pgrp
-+#
-+#-------------------------------------------------------------------------
-+
-+subdir = src/pgcluster/pgrp
-+top_builddir = ../../..
-+include $(top_builddir)/src/Makefile.global
-+
-+OBJS= pqformat.o cascade.o conf.o main.o recovery.o replicate.o rlog.o
-+
-+EXTRA_OBJS = $(top_builddir)/src/backend/libpq/replicate_com.o
-+EXTRA_OBJS += ../libpgc/SUBSYS.o
-+
-+CFLAGS += -DPRINT_DEBUG -g
-+override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) -DBINDIR=\"$(bindir)\"
-+all: pgreplicate
-+
-+pgreplicate: $(OBJS) $(libpq_builddir)/libpq.a
-+ $(CC) $(CFLAGS) $(OBJS) $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o
$@
-+
-+install: all installdirs
-+ $(INSTALL_PROGRAM) pgreplicate$(X) $(DESTDIR)$(bindir)/pgreplicate$(X)
-+ $(INSTALL_DATA) pgreplicate.conf.sample
$(DESTDIR)$(datadir)/pgreplicate.conf.sample
-+
-+installdirs:
-+ $(mkinstalldirs) $(DESTDIR)$(bindir)
-+ $(mkinstalldirs) $(DESTDIR)$(datadir)
-+
-+uninstall:
-+ rm -f $(addprefix $(DESTDIR)$(bindir)/, pgreplicate$(X))
-+ rm -f $(DESTDIR)$(datadir)/pgreplicate.conf.sample
-+
-+clean distclean maintainer-clean:
-+ rm -f pgreplicate$(X) $(OBJS)
-+
-+clean_obj:
-+ rm -f $(OBJS)
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/README
pgcluster-1.5.0rc7/src/pgcluster/pgrp/README
---- postgresql-8.1.2/src/pgcluster/pgrp/README 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/README 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,275 @@
-+=============================================================
-+1. Installation
-+=============================================================
-+
-+1-1. Install Cluster DB Server, Replication Server & Load Balancer
-+----------------------------------------------------------------
-+$ cd $source_dir
-+$ ./configure
-+$ gmake
-+$ su
-+# gmake install
-+# chown -R postgres /usr/local/pgsql
-+----------------------------------------------------------------
-+
-+=============================================================
-+2. Initialize DB
-+=============================================================
-+$ su
-+# adduser postgres
-+# mkdir /usr/local/pgsql/data
-+# chown postgres /usr/local/pgsql/data
-+# su - postgres
-+$ /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
-+
-+
-+=============================================================
-+3. Configuration
-+=============================================================
-+(EX.System Composition)
-+
-+ |
-+ ((Load Balance Server))
-+ ( hostname: lb.hoo.com)
-+ ( receive port:5432 )
-+ ( recovery port:6001 )
-+ |
-+----------+-------------+------------+----------
-+ | |
-+ (( Cluster DB 1 )) (( Cluster DB 2 ))
-+ ( hostname:c1.hoo.com) ( hostname:c2.hoo.com)
-+ ( receive port: 5432 ) ( receive port:5432 )
-+ ( recovery port:7001 ) ( recovery port 7002 )
-+ | |
-+----------+-------------+------------+----------
-+ |
-+ ((Replication Server))
-+ ( hostname:pgr.hoo.com)
-+ ( receive port:8001 )
-+ ( recovery port:8101 )
-+
-+
-+3-1. Load Balance Server
-+
-+The setup file of load balance server is copied from the sample file and
edited.
-+(the sample file is installed '/usr/local/pgsql/etc' in default)
-+----------------------------------------------------------------
-+$cd /usr/local/pgsql/etc
-+$cp pglb.conf.sample pglb.conf
-+----------------------------------------------------------------
-+
-+In the case of the above system composition example,
-+the setup example of pglb.conf file is as the following
-+
-+#============================================================
-+# Load Balance Server configuration file
-+#-------------------------------------------------------------
-+# file: pglb.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts are db cluster server
-+# o which port use connect to db cluster server
-+# o how many connections are allowed on each DB server
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Max_Connection : maximun number of connection to postmaster
-+#-------------------------------------------------------------
-+<Cluster_Server_Info>
-+ <Host_Name> c1.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Max_Connect> 32 </Max_Connect>
-+</Cluster_Server_Info>
-+<Cluster_Server_Info>
-+ <Host_Name> c2.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Max_Connect> 32 </Max_Connect>
-+</Cluster_Server_Info>
-+#-------------------------------------------------------------
-+# set Load Balance server information
-+# o Receive_Port : connection from client
-+# o Recovery_Port : connection for recovery process
-+# o Max_Cluster_Num : maximun number of cluster DB servers
-+# o Use_Connection_Pooling : use connection pool [yes/no]
-+# o Max_Pool_Each_Server : number of pool connections/DB server
-+#-------------------------------------------------------------
-+<Receive_Port> 5432 </Receive_Port>
-+<Recovery_Port> 6001 </Recovery_Port>
-+<Max_Cluster_Num> 128 </Max_Cluster_Num>
-+<Use_Connection_Pooling> yes </Use_Connection_Pooling>
-+<Max_Pool_Each_Server> 1 </Max_Pool_Each_Server>
-+
-+3-2. Cluster DB Server
-+
-+The Cluster DB server need edit two configuration files
-+('pg_hba.conf' and 'cluster.conf').
-+These files are create under the $PG_DATA directory after 'initdb'.
-+
-+A. pg_hba.conf
-+Permission to connect DB via IP connectoins is need for this system.
-+
-+B. cluster.conf
-+In the case of the above system composition example,
-+the setup example of cluster.conf file is as the following
-+
-+#============================================================
-+# Cluster DB Server configuration file
-+#-------------------------------------------------------------
-+# file: cluster.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts & port are replication server
-+# o which port use for replication request to replication server
-+# o which command use for recovery function
-+#
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Recovery_Port : connection for recovery process
-+#-------------------------------------------------------------
-+<Replicate_Server_Info>
-+ <Host_Name> pgr.hoo.com </Host_Name>
-+ <Port> 8001 </Port>
-+ <Recovery_Port> 8101 </Recovery_Port>
-+</Replicate_Server_Info>
-+#-------------------------------------------------------------
-+# set Cluster DB Server information
-+# o Recovery_Port : connection for recovery
-+# o Rsync_Path : path of rsync command
-+# o Rsync_Option : file transfer option for rsync
-+# o When_Stand_Alone : When all replication servers fell,
-+# you can set up two kinds of permittion,
-+# "real_only" or "read_write".
-+#-------------------------------------------------------------
-+<Recovery_Port> 7001 </Recovery_Port>
-+<Rsync_Path> /usr/bin/rsync </Rsync_Path>
-+<Rsync_Option> ssh -1 </Rsync_Option>
-+<Rsync_Compress> yes </Rsync_Compress>
-+<When_Stand_Alone> read_only </When_Stand_Alone>
-+#-------------------------------------------------------------
-+# set partitional replicate control information
-+# set DB name and Table name to stop reprication
-+# o DB_Name : DB name
-+# o Table_Name : table name
-+#-------------------------------------------------------------
-+#<Not_Replicate_Info>
-+# <DB_Name> test_db </DB_Name>
-+# <Table_Name> log_table </Table_Name>
-+#</Not_Replicate_Info>
-+
-+3-3. Replication Server
-+
-+The setup file of replication server is copied from the sample file and
edited.
-+(the sample file is installed '/usr/local/pgsql/etc' in default)
-+----------------------------------------------------------------
-+$cd /usr/local/pgsql/etc
-+$cp pgreplicate.conf.sample pgreplicate.conf
-+----------------------------------------------------------------
-+In the case of the above system composition example,
-+the setup example of pgreplicate.conf file is as the following
-+
-+#============================================================
-+# PGReplicate configuration file
-+#-------------------------------------------------------------
-+# file: pgreplicate.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts & port are cluster server
-+# o which port use for replication request from cluster server
-+#============================================================
-+#-------------------------------------------------------------
-+# set cluster DB server information
-+# o Host_Name : hostname
-+# o Port : connection for postmaster
-+# o Recovery_Port : connection for recovery
-+#-------------------------------------------------------------
-+<Cluster_Server_Info>
-+ <Host_Name> c1.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Recovery_Port> 7001 </Recovery_Port>
-+</Cluster_Server_Info>
-+<Cluster_Server_Info>
-+ <Host_Name> c2.hoo.com </Host_Name>
-+ <Port> 5432 </Port>
-+ <Recovery_Port> 7001 </Recovery_Port>
-+</Cluster_Server_Info>
-+#-------------------------------------------------------------
-+# set Load Balance server information
-+# o Host_Name : hostname
-+# o Recovery_Port : connection for recovery
-+#-------------------------------------------------------------
-+<LoadBalance_Server_Info>
-+ <Host_Name> lb.hoo.com </Host_Name>
-+ <Recovery_Port> 6001 </Recovery_Port>
-+</LoadBalance_Server_Info>
-+#-------------------------------------------------------------
-+# set PGReplicate server information
-+# o Replicate_Port : connection for reprication
-+# o Recovery_Port : connection for recovery
-+#-------------------------------------------------------------
-+<Replication_Port> 8001 </Replication_Port>
-+<Recovery_Port> 8101 </Recovery_Port>
-+
-+
-+=============================================================
-+4. Start Up / Stop
-+=============================================================
-+
-+4-1. replication server
-+
-+A. Start replication server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pgreplicate -D /usr/local/pgsql/etc
-+----------------------------------------------------------------
-+
-+B. Stop replication server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pgreplicate -D /usr/local/pgsql/etc stop
-+----------------------------------------------------------------
-+
-+usage: pgreplicate [-D path_of_config_file] [-W path_of_work_files] [-U
login us
-+er][-l][-n][-v][-h][stop]
-+ -l: print error logs in the log file.
-+ -n: don't run in daemon mode.
-+ -v: debug mode. need '-n' flag
-+ -h: print this help
-+ stop: stop pgreplicate
-+(config file default path: ./pgreplicate.conf)
-+
-+4-2. cluster DB server
-+$PG_HOME = /usr/local/pgsql
-+$PG_DATA = /usr/local/pgsql/data
-+
-+A. Start cluster DB server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -o "-i" start
-+----------------------------------------------------------------
-+
-+B. Stop cluster DB server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data stop
-+----------------------------------------------------------------
-+
-+4-3. load balance server
-+
-+A. Start load balance server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pglb -D /usr/local/pgsql/etc
-+----------------------------------------------------------------
-+
-+B. Stop load balance server
-+----------------------------------------------------------------
-+$ /usr/local/pgsql/bin/pglb -D /usr/local/pgsql/etc stop
-+----------------------------------------------------------------
-+
-+usage: pglb [-D path_of_config_file] [-W path_of_work_files]
[-n][-v][-h][stop]
-+ -l: print error logs in the log file.
-+ -n: don't run in daemon mode.
-+ -v: debug mode. need '-n' flag
-+ -h: print this help
-+ stop: stop pglb
-+ (config file default path: ./pglb.conf)
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/cascade.c
pgcluster-1.5.0rc7/src/pgcluster/pgrp/cascade.c
---- postgresql-8.1.2/src/pgcluster/pgrp/cascade.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/cascade.c 2006-01-31
23:41:36.000000000 +0100
-@@ -0,0 +1,948 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * cascade.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at pgreplicate for backup and cascade .
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#ifdef USE_REPLICATION
-+
-+#include "postgres.h"
-+#include "postgres_fe.h"
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#ifdef HAVE_SYS_TYPES_H
-+#include <sys/types.h>
-+#endif
-+#ifdef HAVE_FCNTL_H
-+#include <fcntl.h>
-+#endif
-+#include <errno.h>
-+#include <ctype.h>
-+#include <time.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <sys/sem.h>
-+#include <signal.h>
-+#include <sys/socket.h>
-+#ifdef HAVE_UNISTD_H
-+#include <unistd.h>
-+#endif
-+#include <netdb.h>
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+#include <dirent.h>
-+#include <arpa/inet.h>
-+
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+#ifdef MULTIBYTE
-+#include "mb/pg_wchar.h"
-+#endif
-+
-+#include "libpq-fe.h"
-+#include "libpq-int.h"
-+#include "fe-auth.h"
-+
-+#include "access/xact.h"
-+#include "replicate_com.h"
-+#include "pgreplicate.h"
-+
-+void PGRinit_cascade_child(void);
-+int PGRstartup_cascade(void);
-+int PGRsend_lower_cascade(ReplicateHeader * header, char * query);
-+int PGRsend_upper_cascade(ReplicateHeader * header, char * query);
-+int PGRwait_answer_cascade(int sock);
-+ReplicateServerInfo * PGRget_lower_cascade(void);
-+ReplicateServerInfo * PGRget_upper_cascade(void);
-+void PGRset_cascade_server_status(ReplicateServerInfo * cascade, int
status);
-+ReplicateServerInfo * PGRrecv_cascade_answer(ReplicateServerInfo *
cascade,ReplicateHeader * header);
-+int PGRsend_cascade(int sock , ReplicateHeader * header, char * query);
-+int PGRcascade_main(int sock, ReplicateHeader * header, char * query);
-+int PGRwait_notice_rlog_done(void);
-+int PGRsend_notice_rlog_done(int sock);
-+int PGRsend_notice_quit(void);
-+
-+#if 0
-+static int count_cascade(int flag);
-+#endif
-+
-+static int fixup_socket_for_cascades(int *sock ,ReplicateServerInfo *
target);
-+static ReplicateServerInfo * get_cascade_data(int * cnt, int flag);
-+static int add_cascade_data(ReplicateHeader * header, ReplicateServerInfo *
add_data);
-+static int update_cascade_data(ReplicateHeader * header,
ReplicateServerInfo * update_data);
-+static void write_cascade_status_file(ReplicateServerInfo * cascade);
-+static int notice_cascade_data(int sock);
-+static int notice_cascade_data_to_cluster_db(void);
-+
-+/**
-+ * socket variables, moved from Cascade_Inf->(lower|upper)->sock.
-+ * Cascade->Inf is in shared memory, so sometimes cascades returns EBADF
due to not initialized socket in specified process.
-+ * 05/10/05 tanida AT sraoss.co.jp
-+ */
-+
-+int lsock=-1; /* socket for lower-cascade. */
-+int usock=-1; /* socket for upper-cascade. */
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+
-+#if 0
-+static int
-+count_cascade(int flag)
-+{
-+ int cnt = 0;
-+ int cascade_cnt = 0;
-+ ReplicateServerInfo * cascade = NULL;
-+
-+ if ((Cascade_Tbl == NULL) || (Cascade_Inf == NULL))
-+ {
-+ return 0;
-+ }
-+
-+ /* count cascadeing replication server */
-+ switch (flag)
-+ {
-+ case UPPER_CASCADE:
-+ case ALL_CASCADE:
-+ cascade = Cascade_Tbl;
-+ break;
-+ case LOWER_CASCADE:
-+ cascade = Cascade_Inf->myself;
-+ break;
-+ }
-+
-+ if (cascade == NULL)
-+ {
-+ return 0;
-+ }
-+ while (cascade->useFlag != DB_TBL_END)
-+ {
-+ if (cascade->useFlag == DB_TBL_USE)
-+ {
-+ cascade_cnt ++;
-+ }
-+ if ((flag == UPPER_CASCADE) &&
-+ (cascade == Cascade_Inf->myself))
-+ {
-+ break;
-+ }
-+ cnt ++;
-+ if (cnt >= MAX_DB_SERVER -1 )
-+ {
-+ break;
-+ }
-+ cascade ++;
-+ }
-+ return cascade_cnt;
-+}
-+#endif /* if 0 */
-+
-+void
-+PGRinit_cascade_child(void) {
-+ fixup_socket_for_cascades(&usock,NULL);
-+ fixup_socket_for_cascades(&lsock,NULL);
-+}
-+
-+static ReplicateServerInfo *
-+get_cascade_data(int * cnt, int flag)
-+{
-+ char * func = "get_cascade_data()";
-+ int i = 0;
-+ int loop_cnt = 0;
-+ int size = 0;
-+ ReplicateServerInfo * buf = NULL;
-+ ReplicateServerInfo * cascade = NULL;
-+
-+ size = sizeof(ReplicateServerInfo) * MAX_DB_SERVER;
-+ buf = (ReplicateServerInfo *)malloc(size);
-+ if (buf == (ReplicateServerInfo *)NULL)
-+ {
-+ show_error("%s:malloc failed: (%s)",func,strerror(errno));
-+ *cnt = 0;
-+ return NULL;
-+ }
-+ memset(buf,0,size);
-+
-+ switch (flag)
-+ {
-+ case UPPER_CASCADE:
-+ case ALL_CASCADE:
-+ cascade = Cascade_Tbl;
-+ break;
-+ case LOWER_CASCADE:
-+ cascade = Cascade_Inf->myself;
-+ break;
-+ default:
-+ free(buf);
-+ *cnt = 0;
-+ return NULL;
-+
-+ }
-+
-+ if (cascade == NULL)
-+ {
-+ free(buf);
-+ *cnt = 0;
-+ return NULL;
-+ }
-+ PGRsem_lock(CascadeSemID,1);
-+ i = 0;
-+ loop_cnt = 0;
-+ while (cascade->useFlag != DB_TBL_END)
-+ {
-+ if (cascade->useFlag == DB_TBL_USE)
-+ {
-+ (buf + i)->useFlag = htonl(cascade->useFlag);
-+ strncpy((buf +
i)->hostName,cascade->hostName,sizeof(cascade->hostName));
-+ (buf + i)->portNumber = htons(cascade->portNumber);
-+ (buf + i)->recoveryPortNumber =
htons(cascade->recoveryPortNumber);
-+ (buf + i)->lifecheckPortNumber =
htons(cascade->lifecheckPortNumber);
-+ i++;
-+ }
-+ if ((flag == UPPER_CASCADE) &&
-+ (cascade == Cascade_Inf->myself))
-+ {
-+ break;
-+ }
-+ loop_cnt ++;
-+ if (loop_cnt >= MAX_DB_SERVER -1 )
-+ {
-+ break;
-+ }
-+ if (Cascade_Inf->end == cascade)
-+ {
-+ break;
-+ }
-+ cascade ++;
-+ }
-+ *cnt = i;
-+ PGRsem_unlock(CascadeSemID,1);
-+
-+ return buf;
-+}
-+
-+static int
-+update_cascade_data(ReplicateHeader * header, ReplicateServerInfo *
update_data)
-+{
-+ char * func = "update_cascade_data()";
-+ int size = 0;
-+ int cnt = 0;
-+ ReplicateServerInfo * ptr = NULL;
-+ ReplicateServerInfo * cascade = NULL;
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("executing %s",func);
-+#endif
-+ if ((header == NULL ) || ( update_data == NULL))
-+ {
-+ show_error("%s:receive data is wrong",func);
-+ return STATUS_ERROR;
-+ }
-+ if ((Cascade_Tbl == NULL) || (Cascade_Inf == NULL))
-+ {
-+ show_error("%s:config data read error",func);
-+ return STATUS_ERROR;
-+ }
-+
-+
-+ size = ntohl(header->query_size);
-+ cnt = size / sizeof(ReplicateServerInfo);
-+ if (cnt >= MAX_DB_SERVER)
-+ {
-+ show_error("%s:update cascade data is too large. it's more
than %d", func,MAX_DB_SERVER);
-+ return STATUS_ERROR;
-+ }
-+
-+ Cascade_Inf->useFlag = DB_TBL_INIT;
-+ fixup_socket_for_cascades(&usock,NULL);
-+ fixup_socket_for_cascades(&lsock,NULL);
-+
-+ Cascade_Inf->upper = NULL;
-+ Cascade_Inf->lower = NULL;
-+
-+ gethostname(hostName,sizeof(hostName));
-+ ptr = update_data;
-+ cascade = Cascade_Tbl;
-+ memset(cascade,0,(sizeof(ReplicateServerInfo)*MAX_DB_SERVER));
-+ Cascade_Inf->top = cascade;
-+ while (cnt > 0)
-+ {
-+
-+ cascade->useFlag = ntohl(ptr->useFlag);
-+
strncpy(cascade->hostName,ptr->hostName,sizeof(cascade->hostName));
-+ cascade->portNumber = ntohs(ptr->portNumber);
-+ cascade->recoveryPortNumber = ntohs(ptr->recoveryPortNumber);
-+ cascade->lifecheckPortNumber =
ntohs(ptr->lifecheckPortNumber);
-+
-+ if
((!strncmp(cascade->hostName,hostName,sizeof(cascade->hostName))) &&
-+ (cascade->portNumber == Port_Number) &&
-+ (cascade->recoveryPortNumber == Recovery_Port_Number))
-+ {
-+ Cascade_Inf->myself = cascade;
-+ }
-+
-+ Cascade_Inf->end = cascade;
-+ cascade ++;
-+ ptr ++;
-+ cnt --;
-+ cascade->useFlag = DB_TBL_END;
-+ }
-+ Cascade_Inf->useFlag = DB_TBL_USE;
-+
-+ return STATUS_OK;
-+}
-+
-+static int
-+add_cascade_data(ReplicateHeader * header, ReplicateServerInfo * add_data)
-+{
-+ char *func = "add_cascade_data()";
-+ int size = 0;
-+ int cnt = 0;
-+ ReplicateServerInfo * ptr = NULL;
-+ ReplicateServerInfo * cascade = NULL;
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+
-+ if ((header == NULL ) || ( add_data == NULL))
-+ {
-+ show_error("%s:receive data is wrong",func);
-+ return STATUS_ERROR;
-+ }
-+ if ((Cascade_Tbl == NULL) || (Cascade_Inf == NULL))
-+ {
-+ show_error("%s:config data read error",func);
-+ return STATUS_ERROR;
-+ }
-+ size = ntohl(header->query_size);
-+ cnt = size / sizeof(ReplicateServerInfo);
-+ if (cnt >= MAX_DB_SERVER)
-+ {
-+ show_error("%s:addtional cascade data is too large. it's more
than %d", func,MAX_DB_SERVER);
-+ return STATUS_ERROR;
-+ }
-+
-+ Cascade_Inf->useFlag = DB_TBL_INIT;
-+ fixup_socket_for_cascades(&lsock,NULL);
-+ Cascade_Inf->lower = NULL;
-+
-+ gethostname(hostName,sizeof(hostName));
-+ ptr = add_data;
-+ cascade = Cascade_Inf->myself;
-+ cascade ++;
-+ while (cnt > 0)
-+ {
-+ cascade->useFlag = ntohl(ptr->useFlag);
-+
strncpy(cascade->hostName,ptr->hostName,sizeof(cascade->hostName));
-+ cascade->portNumber = ntohs(ptr->portNumber);
-+ cascade->recoveryPortNumber = ntohs(ptr->recoveryPortNumber);
-+ cascade->lifecheckPortNumber =
ntohs(ptr->lifecheckPortNumber);
-+ cascade->replicate_id=-1;
-+ cascade->response_mode=-1;
-+
-+ Cascade_Inf->end = cascade;
-+
-+ if
((!strncmp(cascade->hostName,hostName,sizeof(cascade->hostName))) &&
-+ (cascade->portNumber == Port_Number) &&
-+ (cascade->recoveryPortNumber == Recovery_Port_Number))
-+ {
-+ ptr ++;
-+ cnt --;
-+ continue;
-+ }
-+ cascade ++;
-+ cascade->useFlag = DB_TBL_END;
-+ ptr ++;
-+ cnt --;
-+ }
-+ Cascade_Inf->useFlag = DB_TBL_USE;
-+ return STATUS_OK;
-+}
-+
-+int
-+PGRstartup_cascade(void)
-+{
-+ char * func = "PGRstartup_cascade()";
-+ int cnt = 0;
-+ int status = STATUS_OK;
-+ ReplicateHeader header;
-+ ReplicateServerInfo * cascade = NULL;
-+ ReplicateServerInfo * buf = NULL;
-+
-+ if ((Cascade_Tbl == NULL) || (Cascade_Inf == NULL))
-+ {
-+ show_error("%s:config data read error",func);
-+ return STATUS_ERROR;
-+ }
-+
-+ /* count lower server */
-+ cascade = Cascade_Inf->myself;
-+ if (cascade == NULL)
-+ {
-+ show_error("%s:cascade data initialize error",func);
-+ return STATUS_ERROR;
-+ }
-+ buf = get_cascade_data(&cnt,LOWER_CASCADE);
-+ if (cnt <= 0)
-+ {
-+ show_error("%s:cascade data get error",func);
-+ return STATUS_ERROR;
-+ }
-+
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ header.cmdSys = CMD_SYS_CASCADE;
-+ header.cmdSts = CMD_STS_TO_UPPER;
-+ header.cmdType = CMD_TYPE_ADD;
-+ header.query_size = htonl(sizeof(ReplicateServerInfo) * cnt);
-+
-+ status = PGRsend_upper_cascade(&header, (char *)buf);
-+ if (buf != NULL)
-+ {
-+ free(buf);
-+ }
-+ if (status == STATUS_OK)
-+ {
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ buf = PGRrecv_cascade_answer( Cascade_Inf->upper, &header);
-+ if (buf == NULL)
-+ {
-+ status=STATUS_ERROR;
-+ }
-+ else if((header.cmdSys == CMD_SYS_CASCADE) &&
-+ (header.cmdSts == CMD_STS_TO_LOWER) &&
-+ (header.cmdType == CMD_TYPE_UPDATE_ALL))
-+ {
-+ status = update_cascade_data(&header,buf);
-+ free(buf);
-+ }
-+
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:startup packet result is %d",func,status);
-+#endif
-+ return status;
-+}
-+
-+int
-+PGRsend_lower_cascade(ReplicateHeader * header, char * query)
-+{
-+
-+
-+ char * func = "PGRsend_lower_cascade()";
-+ ReplicateServerInfo *lower = PGRget_lower_cascade();
-+
-+
-+ while(lower!=NULL)
-+ {
-+ /**
-+ * check lower_cascade validaty.
-+ *
-+ */
-+ if(lsock!=-1 &&
-+
PGRsend_cascade(lsock,header,query)==STATUS_OK)
-+ {
-+ return STATUS_OK;
-+ }
-+ else
-+ {
-+ /**
-+ * current lower cascade is
missing.
-+ * fix socket , or go to next
one.
-+ *
-+ */
-+ while( lower!=NULL &&
-+
fixup_socket_for_cascades(&lsock,lower)!=STATUS_OK)
-+ {
-+
show_error("%s:lower cascade maybe down,challenge new one.",func);
-+
PGRset_cascade_server_status(lower,DB_TBL_ERROR);
-+ lower
=PGRget_lower_cascade();
-+ }
-+ }
-+ Cascade_Inf->lower=lower;
-+ }
-+
-+
-+ return STATUS_ERROR;
-+}
-+
-+
-+int
-+PGRsend_upper_cascade(ReplicateHeader * header, char * query)
-+{
-+ char * func = "PGRsend_upper_cascade()";
-+ ReplicateServerInfo *upper = PGRget_upper_cascade();
-+
-+
-+ while(upper!=NULL)
-+ {
-+ /**
-+ * check upper_cascade validaty.
-+ *
-+ */
-+ if(usock!=-1 &&
-+ PGRsend_cascade(usock,header,query)==STATUS_OK)
-+ {
-+ return STATUS_OK;
-+ }
-+ else
-+ {
-+ /**
-+ * current upper cascade is missing.
-+ * fix socket , or go to next one.
-+ *
-+ */
-+ while( upper!=NULL &&
-+
fixup_socket_for_cascades(&usock,upper)!=STATUS_OK)
-+ {
-+ show_error("%s:upper
cascade maybe down,challenge new one.",func);
-+
PGRset_cascade_server_status(upper,DB_TBL_ERROR);
-+ upper
=PGRget_upper_cascade();
-+ }
-+ }
-+ Cascade_Inf->upper=upper;
-+ }
-+
-+ return STATUS_ERROR;
-+}
-+
-+ReplicateServerInfo *
-+PGRget_lower_cascade(void)
-+{
-+ char * func = "PGRget_lower_cascade()";
-+ ReplicateServerInfo * cascade = NULL;
-+
-+ if ((Cascade_Tbl == NULL) || (Cascade_Inf == NULL))
-+ {
-+ show_error("%s:config data read error",func);
-+ return NULL;
-+ }
-+
-+ /* count lower server */
-+
-+ cascade = Cascade_Inf->myself;
-+ if (cascade == NULL)
-+ {
-+ show_error("%s:cascade data initialize error",func);
-+ return NULL;
-+ }
-+ if (cascade->useFlag != DB_TBL_END)
-+ {
-+ cascade ++;
-+ }
-+ while (cascade->useFlag != DB_TBL_END)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:lower cascade search[%d]@[%s] use[%d]",
-+ func,
-+ cascade->portNumber,
-+ cascade->hostName,
-+ cascade->useFlag);
-+#endif
-+ if (cascade->useFlag == DB_TBL_USE)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:find lower cascade",func);
-+#endif
-+ return cascade;
-+ }
-+ cascade ++;
-+ }
-+ return NULL;
-+}
-+
-+ReplicateServerInfo *
-+PGRget_upper_cascade(void)
-+{
-+ char * func = "PGRget_upper_cascade()";
-+ ReplicateServerInfo * cascade = NULL;
-+
-+ if ((Cascade_Tbl == NULL) || (Cascade_Inf == NULL))
-+ {
-+ show_error("%s:config data read error",func);
-+ return NULL;
-+ }
-+
-+
-+ /* count lower server */
-+ cascade = Cascade_Inf->myself;
-+ if ((cascade == NULL) || (Cascade_Inf->top == cascade))
-+ {
-+ return NULL;
-+ }
-+ cascade --;
-+ while (cascade != NULL)
-+ {
-+ if (cascade->useFlag == DB_TBL_USE)
-+ {
-+ return cascade;
-+ }
-+ if (Cascade_Inf->top == cascade)
-+ {
-+ break;
-+ }
-+ cascade --;
-+ }
-+ return NULL;
-+}
-+
-+static void
-+write_cascade_status_file(ReplicateServerInfo * cascade)
-+{
-+ switch( cascade->useFlag)
-+ {
-+ case DB_TBL_FREE:
-+ PGRwrite_log_file(StatusFp,"cascade(%s) port(%d)
free",
-+ cascade->hostName,
-+ cascade->portNumber);
-+ break;
-+ case DB_TBL_INIT:
-+ PGRwrite_log_file(StatusFp,"cascade(%s) port(%d)
initialize",
-+ cascade->hostName,
-+ cascade->portNumber);
-+ break;
-+ case DB_TBL_USE:
-+ PGRwrite_log_file(StatusFp,"cascade(%s) port(%d)
start use",
-+ cascade->hostName,
-+ cascade->portNumber);
-+ break;
-+ case DB_TBL_ERROR:
-+ PGRwrite_log_file(StatusFp,"cascade(%s) port(%d)
error",
-+ cascade->hostName,
-+ cascade->portNumber);
-+ break;
-+ case DB_TBL_TOP:
-+ PGRwrite_log_file(StatusFp,"cascade(%s) port(%d)
become top",
-+ cascade->hostName,
-+ cascade->portNumber);
-+ break;
-+ }
-+}
-+
-+void
-+PGRset_cascade_server_status(ReplicateServerInfo * cascade, int status)
-+{
-+ if (cascade == NULL)
-+ {
-+ return;
-+ }
-+ if (cascade->useFlag != status)
-+ {
-+ cascade->useFlag = status;
-+ write_cascade_status_file(cascade);
-+ }
-+}
-+
-+ReplicateServerInfo *
-+PGRrecv_cascade_answer(ReplicateServerInfo * cascade,ReplicateHeader *
header)
-+{
-+ ReplicateServerInfo * answer = NULL;
-+ int sock;
-+
-+ if ((cascade == NULL) || (header == NULL))
-+ {
-+ return NULL;
-+ }
-+
-+ /* FIXME: ReplicateServerInfo->sock must be removed in cascading. */
-+ if(cascade == Cascade_Inf->upper )
-+ {
-+ sock=usock;
-+ }
-+ else if (cascade == Cascade_Inf->lower )
-+ {
-+ sock=lsock;
-+ }
-+ else
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("PGRrecv_cascade_answer:receiving packet from sock not
belogs to cascade->upper / lower. maybe missing .");
-+#endif
-+ sock=cascade->sock;
-+ }
-+ answer = (ReplicateServerInfo*)PGRread_packet(sock,header);
-+ return answer;
-+}
-+
-+int
-+PGRsend_cascade(int sock , ReplicateHeader * header, char * query)
-+{
-+ char * func ="PGRsend_cascade()";
-+ int s;
-+ char * send_ptr;
-+ char * buf;
-+ int send_size = 0;
-+ int buf_size;
-+ int header_size;
-+ int rtn;
-+ fd_set wmask;
-+ struct timeval timeout;
-+ int query_size = 0;
-+
-+ /* check parameter */
-+ if ((header == NULL) || (sock == -1))
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PGRsend_cascade sock[%d]",func,sock);
-+#endif
-+ query_size = ntohl(header->query_size);
-+ header_size = sizeof(ReplicateHeader);
-+ buf_size = header_size + query_size + 4;
-+ buf = malloc(buf_size);
-+ memset(buf,0,buf_size);
-+ buf_size -= 4;
-+ memcpy(buf,header,header_size);
-+ if (query_size > 0)
-+ {
-+ memcpy((char *)(buf+header_size),query,query_size+1);
-+ }
-+ send_ptr = buf;
-+
-+ for (;;)
-+ {
-+ timeout.tv_sec = 10;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&wmask);
-+ FD_SET(sock,&wmask);
-+ rtn = select(sock+1, (fd_set *)NULL, &wmask, (fd_set *)NULL,
&timeout);
-+
-+ if (rtn < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+
-+ show_error("%s:select failed ,errno is %s",func ,
strerror(errno));
-+ free(buf);
-+ return STATUS_ERROR;
-+ }
-+
-+ if (rtn && FD_ISSET(sock, &wmask))
-+ {
-+ s = send(sock,send_ptr + send_size,buf_size -
send_size ,0);
-+ if (s < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+ else
-+ {
-+ show_error("%s:send failed:
%d(%s)",func, errno, strerror(errno));
-+ free(buf);
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else if (s == 0)
-+ {
-+ show_error("%s:unexpected EOF", func);
-+ free(buf);
-+ return STATUS_ERROR;
-+ }
-+ send_size += s;
-+ if (send_size == buf_size)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:send[%s]
size[%d]",func,query,send_size);
-+#endif
-+ free(buf);
-+ return STATUS_OK;
-+ }
-+ }
-+ }
-+ return STATUS_OK;
-+}
-+
-+int
-+PGRwait_answer_cascade(int sock)
-+{
-+ ReplicateHeader header;
-+ char * answer = NULL;
-+
-+ answer = PGRread_packet(sock,&header);
-+ if (answer != NULL)
-+ {
-+ free(answer);
-+ return STATUS_OK;
-+ }
-+ return STATUS_ERROR;
-+}
-+/**
-+ * fixup_socket_for_cascades checks socket's validaty.
-+ * returns STATUS_OK if succeeded , or STATUS_ERROR if some error occured.
-+ * if target is null , only close socket.
-+ *
-+ * originally written by tanida AT sraoss.co.jp
-+ */
-+static int
-+fixup_socket_for_cascades(int *sock, ReplicateServerInfo *target)
-+{
-+ if (*sock > 0)
-+ {
-+ close(*sock);
-+ *sock=-1;
-+ }
-+ if(target!=NULL) {
-+ return
PGR_Create_Socket_Connect(sock,target->hostName,target->portNumber);
-+ }
-+ return STATUS_OK;
-+}
-+
-+
-+static int
-+notice_cascade_data(int sock)
-+{
-+ char * func = "notice_cascade_data";
-+ ReplicateServerInfo *cascade_data = NULL;
-+ ReplicateHeader header;
-+ int cnt = 0;
-+ int size = 0;
-+
-+ if (sock <= 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ cascade_data = get_cascade_data(&cnt, ALL_CASCADE );
-+ if (cnt <= 0)
-+ {
-+ show_error("%s:cascade data is wrong",func);
-+ return STATUS_ERROR;
-+ }
-+ size = sizeof (ReplicateServerInfo) * cnt ;
-+
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ header.cmdSys = CMD_SYS_CASCADE ;
-+ header.cmdSts = CMD_STS_TO_LOWER ;
-+ header.cmdType = CMD_TYPE_UPDATE_ALL;
-+ header.query_size = htonl(size);
-+ PGRsend_cascade(sock, &header, (char *)cascade_data );
-+ if (cascade_data != NULL)
-+ {
-+ free(cascade_data);
-+ }
-+ return STATUS_OK;
-+}
-+
-+int
-+PGRcascade_main(int sock, ReplicateHeader * header, char * query)
-+{
-+ switch (header->cmdSts)
-+ {
-+ case CMD_STS_TO_UPPER:
-+ if (header->cmdType == CMD_TYPE_ADD)
-+ {
-+ /* add lower cascade data to myself */
-+
add_cascade_data(header,(ReplicateServerInfo*)query);
-+ /* send cascade data to upper */
-+ /* and receive new cascade data from upper */
-+ PGRstartup_cascade();
-+ /* return to lower with new cascade data */
-+ notice_cascade_data(sock);
-+ /* notifies a cascade server's information to
Cluster DBs */
-+ notice_cascade_data_to_cluster_db();
-+ }
-+ break;
-+ case CMD_STS_TO_LOWER:
-+ /*
-+ * use for cascading replication
-+ */
-+ break;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+notice_cascade_data_to_cluster_db(void)
-+{
-+ char userName[USERNAME_MAX_LENGTH];
-+ ReplicateServerInfo *s=NULL;
-+
-+ if (Cascade_Inf->lower == NULL)
-+ {
-+ Cascade_Inf->lower = PGRget_lower_cascade();
-+ }
-+ if (Cascade_Inf->lower == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ s=Cascade_Inf->lower;
-+ memset(userName,0,sizeof(userName));
-+ strncpy(userName ,getenv("LOGNAME"),sizeof(userName)-1);
-+
-+ PGRnotice_replication_server(s->hostName,
-+
s->portNumber,
-+
s->recoveryPortNumber,
-+
s->lifecheckPortNumber,
-+ userName);
-+
-+ return STATUS_OK;
-+}
-+
-+int
-+PGRwait_notice_rlog_done(void)
-+{
-+ ReplicateHeader header;
-+ if (lsock != -1)
-+ {
-+ PGRread_packet(lsock,&header);
-+ return STATUS_OK;
-+ }
-+ return STATUS_ERROR;
-+
-+}
-+
-+
-+int
-+PGRsend_notice_quit(void )
-+{
-+ ReplicateHeader header;
-+ int size = 0;
-+
-+ size = strlen("QUIT_SAFELY");
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ header.cmdSys = CMD_SYS_CALL ;
-+ header.cmdSts = CMD_STS_RESPONSE ;
-+ header.cmdType = CMD_TYPE_FRONTEND_CLOSED;
-+ header.query_size = htonl(size);
-+ PGRsend_lower_cascade(&header, "QUIT_SAFELY");
-+ PGRwait_notice_rlog_done();
-+ return STATUS_OK;
-+}
-+
-+int
-+PGRsend_notice_rlog_done(int sock)
-+{
-+ ReplicateHeader header;
-+ int size = 0;
-+
-+ if (sock <= 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ size = strlen(PGR_QUERY_DONE_NOTICE_CMD);
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ header.cmdSys = CMD_SYS_CASCADE ;
-+ header.cmdSts = CMD_STS_RESPONSE ;
-+ header.cmdType = 0;
-+ header.query_size = htonl(size);
-+ PGRsend_cascade(sock, &header, PGR_QUERY_DONE_NOTICE_CMD);
-+ return STATUS_OK;
-+
-+}
-+#endif /* USE_REPLICATION */
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/conf.c
pgcluster-1.5.0rc7/src/pgcluster/pgrp/conf.c
---- postgresql-8.1.2/src/pgcluster/pgrp/conf.c 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/conf.c 2006-01-31
23:42:41.000000000 +0100
-@@ -0,0 +1,602 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * conf.c
-+ * Replication server for PostgreSQL
-+ *
-+ * NOTE:
-+ * Read and set configuration data in this modul.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#include "postgres.h"
-+
-+#include <stdio.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <sys/types.h>
-+#include <fcntl.h>
-+#include <ctype.h>
-+#include <sys/stat.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <sys/sem.h>
-+#include <netdb.h>
-+#include <errno.h>
-+#include <sys/file.h>
-+
-+
-+
-+#include "libpq-fe.h"
-+#include "libpq-int.h"
-+#include "fe-auth.h"
-+
-+#include "replicate_com.h"
-+#include "pgreplicate.h"
-+
-+int PGRget_Conf_Data(char * path);
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRget_Conf_Data()
-+ * NOTES
-+ * Initialize mamory and tables
-+ * ARGS
-+ * char * path: path of the setup file (I)
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGRget_Conf_Data(char * path)
-+{
-+ char * func = "PGRget_Conf_Data()";
-+ HostTbl host_tbl[MAX_DB_SERVER];
-+ ConfDataType * conf = NULL;
-+ int cnt = 0;
-+ int lb_cnt = 0;
-+ int cascade_cnt = 0;
-+ int rec_no = 0;
-+ int lb_rec_no = 0;
-+ int cascade_rec_no = -1;
-+ int i = 0;
-+ int size = 0;
-+ char fname[256];
-+ union semun sem_arg;
-+
-+ /*
-+ * open log file
-+ */
-+ if (path == NULL)
-+ {
-+ path = ".";
-+ }
-+
-+ LogFp = NULL;
-+ if (Log_Print)
-+ {
-+
snprintf(fname,sizeof(fname),"%s/%s",path,PGREPLICATE_LOG_FILE);
-+ LogFp = fopen(fname,"a");
-+ if (LogFp == NULL)
-+ {
-+ show_error("%s:fopen failed:
(%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s open ok\n",fname);
-+#endif
-+ }
-+
-+ snprintf(fname,sizeof(fname),"%s/%s",path,PGREPLICATE_STATUS_FILE);
-+ StatusFp = fopen(fname,"a");
-+ if (StatusFp == NULL)
-+ {
-+ show_error("%s:fopen failed: (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+
-+ snprintf(fname,sizeof(fname),"%s/%s",path,PGREPLICATE_RID_FILE);
-+ RidFp = fopen(fname,"r+");
-+ if (RidFp == NULL)
-+ {
-+ RidFp = fopen(fname,"w+");
-+ if (RidFp == NULL)
-+ {
-+ show_error("%s:fopen failed:
(%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ }
-+
-+ /*
-+ * read configuration file
-+ */
-+ if (PGR_Get_Conf_Data(path,PGREPLICATE_CONF_FILE) != STATUS_OK)
-+ {
-+ show_error("%s:PGR_Get_Conf_Data failed",func);
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("PGR_Get_Conf_Data ok");
-+#endif
-+
-+ /* allocate response information table */
-+ PGR_Response_Inf = (ResponseInf *)malloc(sizeof(ResponseInf));
-+ if (PGR_Response_Inf == NULL)
-+ {
-+ show_error("%s:malloc() failed. reason: %s",
func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ PGR_Response_Inf->response_mode = PGR_NORMAL_MODE;
-+ PGR_Response_Inf->current_cluster = 0;
-+
-+ /*
-+ * memory allocate load balance table buffer
-+ */
-+ LoadBalanceTbl = (RecoveryTbl
*)malloc(sizeof(RecoveryTbl)*MAX_DB_SERVER);
-+ if (LoadBalanceTbl == (RecoveryTbl *)NULL)
-+ {
-+ show_error("%s:malloc failed: (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("LoadBalanceTbl allocate ok");
-+#endif
-+
-+ /*
-+ * memory allocate cascade server table buffer
-+ */
-+ size = sizeof(ReplicateServerInfo) * MAX_DB_SERVER;
-+ CascadeTblShmid = shmget(IPC_PRIVATE,size,IPC_CREAT | IPC_EXCL |
0600);
-+ if (CascadeTblShmid < 0)
-+ {
-+ show_error("%s:shmget() failed. reason: %s",
func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:CascadeTbl shmget ok",func);
-+#endif
-+ Cascade_Tbl = (ReplicateServerInfo *)shmat(CascadeTblShmid,0,0);
-+ if (Cascade_Tbl == (ReplicateServerInfo *)-1)
-+ {
-+ show_error("%s:shmat() failed. reason: %s",
func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:CascadeTbl shmat ok",func);
-+#endif
-+ memset(Cascade_Tbl , 0 , size );
-+
-+ /*
-+ * memory allocate cascade index
-+ */
-+ size = sizeof(CascadeInf);
-+ CascadeInfShmid = shmget(IPC_PRIVATE,size,IPC_CREAT | IPC_EXCL |
0600);
-+ if (CascadeInfShmid < 0)
-+ {
-+ show_error("%s:shmget() failed. reason: %s",
func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:CascadeInf shmget ok",func);
-+#endif
-+ Cascade_Inf = (CascadeInf *)shmat(CascadeInfShmid,0,0);
-+ if (Cascade_Inf == (CascadeInf *)-1)
-+ {
-+ show_error("%s:shmat() failed. reason: %s",func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:CascadeInf shmat ok",func);
-+#endif
-+ memset(Cascade_Inf , 0 , size );
-+
-+ /*
-+ * memory allocate replication commit log buffer
-+ */
-+ size = sizeof(CommitLogInf) * MAX_DB_SERVER * MAX_CONNECTIONS;
-+ CommitLogShmid = shmget(IPC_PRIVATE,size,IPC_CREAT | IPC_EXCL | 0600);
-+ if (CommitLogShmid < 0)
-+ {
-+ show_error("%s:shmget() failed. reason: %s", func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:CommitLog shmget ok",func);
-+#endif
-+ Commit_Log_Tbl = (CommitLogInf *)shmat(CommitLogShmid,0,0);
-+ if (Commit_Log_Tbl == (CommitLogInf *)-1)
-+ {
-+ show_error("%s:shmat() failed. reason: %s",func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:Commit_Log_Tbl shmat ok",func);
-+#endif
-+ memset(Commit_Log_Tbl , 0 , size );
-+ (Commit_Log_Tbl + (MAX_DB_SERVER * MAX_CONNECTIONS) -1)->inf.useFlag
= DB_TBL_END;
-+
-+ /* create semapho */
-+ if ((SemID = semget(IPC_PRIVATE,2,IPC_CREAT | IPC_EXCL | 0600)) < 0)
-+ {
-+ show_error("%s:semget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ for ( i = 0 ; i < 2 ; i ++)
-+ {
-+ semctl(SemID, i, GETVAL, sem_arg);
-+ sem_arg.val = 1;
-+ semctl(SemID, i, SETVAL, sem_arg);
-+ }
-+
-+ /* create semapho */
-+ if ((CascadeSemID = semget(IPC_PRIVATE,2,IPC_CREAT | IPC_EXCL |
0600)) < 0)
-+ {
-+ show_error("%s:semget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ for ( i = 0 ; i < 2 ; i ++)
-+ {
-+ semctl(CascadeSemID, i, GETVAL, sem_arg);
-+ sem_arg.val = 1;
-+ semctl(CascadeSemID, i, SETVAL, sem_arg);
-+ }
-+
-+
-+ if ((VacuumSemID = semget(IPC_PRIVATE,2,IPC_CREAT | IPC_EXCL | 0600))
< 0)
-+ {
-+ show_error("%s:semget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ for ( i = 0 ; i < 2 ; i ++)
-+ {
-+ semctl(VacuumSemID, i, GETVAL, sem_arg);
-+ sem_arg.val = 1;
-+ semctl(VacuumSemID, i, SETVAL, sem_arg);
-+ }
-+ size = sizeof(ReplicationLogInf);
-+ Replicateion_Log = malloc(size);
-+ if (Replicateion_Log == NULL)
-+ {
-+ show_error("%s:malloc failed: (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(Replicateion_Log , 0 , size );
-+ Replicateion_Log->RLog_Sock_Path = NULL;
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:RLog Memory Allocation ok",func);
-+#endif
-+
-+
-+ /*
-+ * set each datas into the tables
-+ */
-+ conf = ConfData_Top;
-+ while (conf != (ConfDataType *)NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("registering
(key,value)=(%s,%s)",conf->key,conf->value);
-+#endif
-+ /* get cluster db data */
-+ if (!strcmp(conf->table,CLUSTER_SERVER_TAG))
-+ {
-+ rec_no = conf->rec_no;
-+ if (cnt < rec_no)
-+ {
-+ cnt = rec_no;
-+ if (cnt >= MAX_DB_SERVER)
-+ {
-+ continue;
-+ }
-+ }
-+ if (!strcmp(conf->key,HOST_NAME_TAG))
-+ {
-+ int ip;
-+
memcpy(host_tbl[rec_no].hostName,conf->value,sizeof(host_tbl[rec_no].hostName));
-+#ifdef PRINT_DEBUG
-+ show_debug("registering hostname
%s",host_tbl[rec_no].hostName);
-+#endif
-+ ip=PGRget_ip_by_name(conf->value);
-+
-+ sprintf(host_tbl[rec_no].resolvedName,
-+ "%d.%d.%d.%d",
-+ (ip ) & 0xff ,
-+ (ip >> 8) & 0xff ,
-+ (ip >> 16) & 0xff ,
-+ (ip >> 24) & 0xff );
-+#ifdef PRINT_DEBUG
-+ show_debug("resolved name is
%s",host_tbl[rec_no].resolvedName);
-+#endif
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,PORT_TAG))
-+ {
-+ host_tbl[rec_no].port = atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,RECOVERY_PORT_TAG))
-+ {
-+ host_tbl[rec_no].recoveryPort =
atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ }
-+ /* get cascade server data */
-+ else if (!strcmp(conf->table, REPLICATION_SERVER_INFO_TAG))
-+ {
-+ cascade_rec_no = conf->rec_no ;
-+ if (cascade_cnt < cascade_rec_no)
-+ {
-+ cascade_cnt = cascade_rec_no;
-+ if (cascade_cnt >= MAX_DB_SERVER)
-+ {
-+ continue;
-+ }
-+ }
-+ if (!strcmp(conf->key,HOST_NAME_TAG))
-+ {
-+
memcpy((Cascade_Tbl+cascade_rec_no)->hostName,conf->value,sizeof(Cascade_Tbl->hostName));
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,PORT_TAG))
-+ {
-+ if (atoi(conf->value) > 0)
-+ {
-+
(Cascade_Tbl+cascade_rec_no)->portNumber = atoi(conf->value);
-+ }
-+ else
-+ {
-+
(Cascade_Tbl+cascade_rec_no)->portNumber = DEFAULT_PGRP_PORT;
-+ }
-+ (Cascade_Tbl+cascade_rec_no)->sock = -1;
-+
-+ conf = (ConfDataType*)conf->next;
-+
PGRset_cascade_server_status(Cascade_Tbl+cascade_rec_no,DB_TBL_USE);
-+ if (cascade_rec_no == 0)
-+ {
-+ Cascade_Inf->top = Cascade_Tbl;
-+ }
-+ continue;
-+ }
-+ if (!strcmp(conf->key,RECOVERY_PORT_TAG))
-+ {
-+ if (atoi(conf->value) > 0)
-+ {
-+
(Cascade_Tbl+cascade_rec_no)->recoveryPortNumber = atoi(conf->value);
-+ }
-+ else
-+ {
-+
(Cascade_Tbl+cascade_rec_no)->recoveryPortNumber = DEFAULT_PGRP_RECOVERY_PORT;
-+ }
-+ (Cascade_Tbl+cascade_rec_no)->rlog_sock=-1;
-+ (Cascade_Tbl+cascade_rec_no +1)->useFlag =
DB_TBL_END;
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ }
-+ /* get loadbalancer table data */
-+ else if (!strcmp(conf->table,LOAD_BALANCE_SERVER_TAG))
-+ {
-+ lb_rec_no = conf->rec_no;
-+ if (lb_cnt < lb_rec_no)
-+ {
-+ lb_cnt = lb_rec_no;
-+ if (lb_cnt >= MAX_DB_SERVER)
-+ {
-+ continue;
-+ }
-+ }
-+ if (!strcmp(conf->key,HOST_NAME_TAG))
-+ {
-+ memcpy((LoadBalanceTbl +
lb_rec_no)->hostName, conf->value,sizeof(LoadBalanceTbl->hostName));
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!strcmp(conf->key,RECOVERY_PORT_TAG))
-+ {
-+ (LoadBalanceTbl + lb_rec_no)->recoveryPort =
atoi(conf->value);
-+ (LoadBalanceTbl + lb_rec_no)->sock = -1;
-+ (LoadBalanceTbl + lb_rec_no)->recovery_sock =
-1;
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ }
-+ else
-+ {
-+ if (!strcmp(conf->key,REPLICATE_PORT_TAG))
-+ {
-+ Port_Number = atoi(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ /* get port number for recovery cluster db server */
-+ if (!strcmp(conf->key,RECOVERY_PORT_TAG))
-+ {
-+ if (atoi(conf->value) > 0)
-+ {
-+ Recovery_Port_Number =
atoi(conf->value);
-+ }
-+ else
-+ {
-+ Recovery_Port_Number
=DEFAULT_PGRP_RECOVERY_PORT;
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!STRCMP(conf->key,LIFECHECK_PORT_TAG))
-+ {
-+ if (atoi(conf->value) > 0)
-+ {
-+ LifeCheck_Port_Number =
atoi(conf->value);
-+ }
-+ else
-+ {
-+ LifeCheck_Port_Number =
DEFAULT_PGRP_LIFECHECK_PORT;
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!STRCMP(conf->key,RLOG_PORT_TAG))
-+ {
-+ if (atoi(conf->value) > 0)
-+ {
-+ Replicateion_Log->RLog_Port_Number =
atoi(conf->value);
-+ }
-+ else
-+ {
-+ Replicateion_Log->RLog_Port_Number =
DEFAULT_PGRP_RLOG_PORT;
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ /*
-+ if (!STRCMP(conf->key,STATUS_LOG_FILE_TAG))
-+ {
-+ Com_Info.Log_Info.PGRStatusFileName =
strdup(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ if (!STRCMP(conf->key,ERROR_LOG_FILE_TAG))
-+ {
-+ Com_Info.Log_Info.PGRLogFileName =
strdup(conf->value);
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ */
-+ /* get response mode */
-+ if (!strcmp(conf->key,RESPONSE_MODE_TAG))
-+ {
-+ if
(!strcmp(conf->value,RESPONSE_MODE_RELIABLE))
-+ {
-+ PGR_Response_Inf->response_mode =
PGR_RELIABLE_MODE;
-+ }
-+ else if
(!strcmp(conf->value,RESPONSE_MODE_FAST))
-+ {
-+ PGR_Response_Inf->response_mode =
PGR_FAST_MODE;
-+ }
-+ else
-+ {
-+ PGR_Response_Inf->response_mode =
PGR_NORMAL_MODE;
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ /* get replication log use or not */
-+ if (!strcmp(conf->key,USE_REPLICATION_LOG_TAG))
-+ {
-+ if (!strcmp(conf->value,"yes"))
-+ {
-+ PGR_Use_Replication_Log = true;
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ continue;
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ }
-+ conf = (ConfDataType*)conf->next;
-+ }
-+
-+
-+ /* create cluster db server table */
-+ Host_Tbl_Begin = (HostTbl *)NULL;
-+
-+ size = sizeof(HostTbl) * MAX_DB_SERVER;
-+ HostTblShmid = shmget(IPC_PRIVATE,size,IPC_CREAT | IPC_EXCL | 0600);
-+ if (HostTblShmid < 0)
-+ {
-+ show_error("%s:shmget() failed. reason: %s",
func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:HostTbl shmget ok",func);
-+#endif
-+ Host_Tbl_Begin = (HostTbl *)shmat(HostTblShmid,0,0);
-+ if (Host_Tbl_Begin == (HostTbl *)-1)
-+ {
-+ show_error("%s:shmat() failed. reason: %s", func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:HostTbl shmat ok",func);
-+#endif
-+ memset(Host_Tbl_Begin , 0 , size );
-+ Host_Tbl_Begin -> useFlag = DB_TBL_END;
-+
-+ for ( i = 0 ; i <= cnt ; i ++)
-+ {
-+ PGRadd_HostTbl(&host_tbl[i],DB_TBL_USE);
-+ }
-+ /* set load balance table */
-+ for ( i = 0 ; i <= lb_cnt ; i ++)
-+ {
-+ (LoadBalanceTbl + i)->port = -1;
-+ (LoadBalanceTbl + i)->sock = -1;
-+ }
-+ memset((LoadBalanceTbl + i),0,sizeof(RecoveryTbl));
-+ PGR_Free_Conf_Data();
-+
-+ /* allocate result buffer of query */
-+ PGR_Result = malloc(PGR_MESSAGE_BUFSIZE);
-+ if (PGR_Result == NULL)
-+ {
-+ show_error("%s:malloc() failed. reason: %s", func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(PGR_Result,0,PGR_MESSAGE_BUFSIZE);
-+
-+ /* allocate log_data */
-+ PGR_Log_Header = malloc(sizeof(ReplicateHeader));
-+ if (PGR_Log_Header == NULL)
-+ {
-+ show_error("%s:malloc() failed. reason: %s", func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(PGR_Log_Header,0,sizeof(ReplicateHeader));
-+
-+ /* allocate send query id */
-+ size = sizeof(unsigned int) * (MAX_DB_SERVER +1);
-+ PGR_Send_Query_ID = malloc (size);
-+ if (PGR_Send_Query_ID == NULL)
-+ {
-+ show_error("%s:malloc() failed. reason: %s", func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(PGR_Send_Query_ID, 0, size);
-+ for ( i = 0 ; i < MAX_DB_SERVER ; i ++)
-+ {
-+ StartReplication[i] = true;
-+ }
-+
-+ /* set self data into cascade table */
-+
-+ cascade_rec_no ++;
-+
gethostname((Cascade_Tbl+cascade_rec_no)->hostName,sizeof(Cascade_Tbl->hostName));
-+ (Cascade_Tbl+cascade_rec_no)->portNumber = Port_Number;
-+ (Cascade_Tbl+cascade_rec_no)->recoveryPortNumber =
Recovery_Port_Number;
-+ (Cascade_Tbl+cascade_rec_no)->sock = -1;
-+
-+ PGRset_cascade_server_status(Cascade_Tbl+cascade_rec_no,DB_TBL_USE);
-+ /* terminate */
-+ (Cascade_Tbl+(cascade_rec_no+1))->useFlag = DB_TBL_END;
-+
-+ Cascade_Inf->top = Cascade_Tbl;
-+ Cascade_Inf->end = Cascade_Tbl+cascade_rec_no;
-+ Cascade_Inf->upper = NULL;
-+ Cascade_Inf->lower = NULL;
-+ if (cascade_rec_no >= 1)
-+ {
-+ Cascade_Inf->upper = (Cascade_Tbl+cascade_rec_no - 1);
-+ }
-+ (Cascade_Tbl+(cascade_rec_no+1))->useFlag = DB_TBL_END;
-+
-+ Cascade_Inf->myself = (Cascade_Tbl+cascade_rec_no);
-+ Cascade_Inf->useFlag = DB_TBL_USE;
-+
-+ PGR_Response_Inf->response_mode = PGR_NORMAL_MODE;
-+
-+ return STATUS_OK;
-+}
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/main.c
pgcluster-1.5.0rc7/src/pgcluster/pgrp/main.c
---- postgresql-8.1.2/src/pgcluster/pgrp/main.c 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/main.c 2006-01-31
23:40:32.000000000 +0100
-@@ -0,0 +1,1001 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * main.c
-+ * Replication server for PostgreSQL
-+ *
-+ * NOTE:
-+ * This is the main module of the replication server.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#include "postgres.h"
-+
-+#include <stdio.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <sys/time.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <ctype.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <sys/param.h>
-+#include <arpa/inet.h>
-+#include <sys/file.h>
-+#include <pthread.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+#ifdef HAVE_SYS_SELECT_H
-+#include <sys/select.h>
-+#endif
-+
-+#ifdef HAVE_GETOPT_H
-+#include <getopt.h>
-+#endif
-+
-+#include "miscadmin.h"
-+#include "nodes/nodes.h"
-+
-+#include "libpq-fe.h"
-+#include "libpq/libpq-fs.h"
-+#include "libpq-int.h"
-+#include "fe-auth.h"
-+
-+
-+#include "access/xact.h"
-+#include "replicate_com.h"
-+#include "pgreplicate.h"
-+
-+#ifdef WIN32
-+#include "win32.h"
-+#endif
-+#include <arpa/inet.h>
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+#ifdef MULTIBYTE
-+#include "mb/pg_wchar.h"
-+#endif
-+
-+/*--------------------------------------
-+ * GLOBAL VARIABLE DECLARATION
-+ *--------------------------------------
-+ */
-+/* for replicate_com.h */
-+
-+ConfDataType * ConfData_Top = (ConfDataType *)NULL;
-+ConfDataType * ConfData_End = (ConfDataType *)NULL;
-+
-+/* replication server data */
-+uint16_t Port_Number = 0;
-+uint16_t LifeCheck_Port_Number = 0;
-+uint16_t Recovery_Port_Number = 0;
-+bool PGR_Parse_Session_Started = false;
-+
-+/* global table data */
-+HostTbl *Host_Tbl_Begin = NULL;
-+Dllist * Transaction_Tbl_Begin = NULL;
-+TransactionTbl * Transaction_Tbl_End = NULL;
-+RecoveryTbl * LoadBalanceTbl = NULL;
-+RecoveryStatusInf * Recovery_Status_Inf = NULL;
-+ReplicateHeader * PGR_Log_Header = NULL;
-+ReplicateServerInfo * Cascade_Tbl = NULL;;
-+CommitLogInf * Commit_Log_Tbl = NULL;
-+QueryLogType * Query_Log_Top = NULL;
-+QueryLogType * Query_Log_End = NULL;
-+CascadeInf * Cascade_Inf = NULL;
-+ReplicationLogInf * Replicateion_Log = NULL;
-+/* IPC's id data */
-+int RecoveryShmid = 0;
-+int ReplicateSerializationShmid=0;
-+int RecoveryMsgShmid = 0;
-+int *RecoveryMsgid = NULL;
-+int HostTblShmid = 0;
-+int LockWaitTblShmid = 0;
-+int LoadBalanceTblShmid = 0;
-+int CascadeTblShmid = 0;
-+int CascadeInfShmid = 0;
-+int CommitLogShmid = 0;
-+int QueryLogMsgid = 0;
-+int QueryLogAnsMsgid = 0;
-+int PGconnMsgid = 0;
-+int MaxBackends = 0;
-+char * PGR_Result = NULL;
-+int SemID = 0;
-+int RecoverySemID= 0;
-+int RecovErysemid = 0;
-+int VacuumSemID = 0;
-+int CascadeSemID= 0;
-+char * PGR_Data_Path = NULL;
-+char * PGR_Write_Path = NULL;
-+int IS_SESSION_AUTHORIZATION = 0;
-+ResponseInf * PGR_Response_Inf = NULL;
-+bool StartReplication[MAX_DB_SERVER];
-+bool PGR_Cascade = false;
-+bool PGR_Use_Replication_Log = false;
-+bool PGR_AutoCommit = true;
-+unsigned int * PGR_Send_Query_ID = NULL;
-+unsigned int PGR_Query_ID = 0;
-+bool exit_processing = false;
-+int pgreplicate_pid = 0;
-+
-+int ReplicateSock = -1;
-+
-+RecoveryQueueInf RecoveryQueue;
-+char * Backend_Socket_Dir = NULL;
-+
-+unsigned int * PGR_ReplicateSerializationID = NULL;
-+
-+int Log_Print = 0;
-+int Debug_Print = 0;
-+FILE * LogFp = (FILE *)NULL;
-+FILE * StatusFp = (FILE *)NULL;
-+FILE * RidFp = (FILE *)NULL;
-+
-+extern char *optarg;
-+char * PGRuserName = NULL;
-+
-+int fork_wait_time = 0;
-+int Idle_Flag = IDLE_MODE;
-+bool Exit_Request = false;
-+
-+pthread_mutex_t transaction_table_mutex;
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+static void startup_replication_server(void);
-+static int replicate_loop(int fd);
-+static void replicate_main(void);
-+static void quick_exit(SIGNAL_ARGS);
-+static void daemonize(void);
-+static void write_pid_file(void);
-+static void stop_pgreplicate(void);
-+static bool is_exist_pid_file(void);
-+static void usage(void);
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * replicate_loop()
-+ * NOTES
-+ * replication module
-+ * ARGS
-+ * int fd :
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ *--------------------------------------------------------------------
-+ */
-+static int
-+replicate_loop(int fd)
-+{
-+ char * func = "replicate_loop()";
-+ pid_t pgid = 0;
-+ pid_t pid = 0;
-+ int sock = -1;
-+ int rtn = 0;
-+ int cnt = 0;
-+ int result;
-+ bool exist_sys_log=false;
-+ bool exist_replicate=false;
-+
-+
-+ result = PGR_Create_Acception(fd,&sock,"",Port_Number);
-+ if (result == STATUS_ERROR)
-+ {
-+ show_error("%s: accept failed (%s)", func, strerror(errno));
-+ if (sock != -1)
-+ close(sock);
-+ return 1;
-+ }
-+
-+ pgid = getpgid(0);
-+ pid = fork();
-+ if (pid <0)
-+ {
-+ show_error("%s:fork failed (%s)",func,strerror(errno));
-+ PGRreplicate_exit(0);
-+ }
-+ if (pid == 0)
-+ {
-+ int status = LOOP_CONTINUE;
-+ bool PGR_Cascade = false;
-+ ReplicateHeader header;
-+ ReplicateHeader header_save_for_recovering;
-+ char * query = NULL;
-+
-+ if (fork_wait_time > 0) {
-+#ifdef PRINT_DEBUG
-+ show_debug("wait fork(): pid = %d", getpid());
-+#endif
-+ sleep(fork_wait_time);
-+ }
-+
-+ close(fd);
-+
-+ signal(SIGHUP, quick_exit);
-+ signal(SIGINT, quick_exit);
-+ signal(SIGQUIT, quick_exit);
-+ signal(SIGTERM, quick_exit);
-+ signal(SIGALRM, quick_exit);
-+ signal(SIGPIPE, SIG_IGN);
-+ setpgid(0,pgid);
-+
-+ if (PGRinit_transaction_table() != STATUS_OK)
-+ {
-+ show_error("transaction table memory allocate
failed");
-+ PGR_Close_Sock(&sock);
-+ exit(1);
-+ }
-+
-+ pthread_mutex_init(&transaction_table_mutex, NULL);
-+
-+ /* child loop */
-+ for (;;)
-+ {
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = PGR_RECV_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ if (query != NULL)
-+ {
-+ free(query);
-+ query = NULL;
-+ }
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(sock,&rmask);
-+ rtn = select(sock+1, &rmask, (fd_set *)NULL, (fd_set
*)NULL, &timeout);
-+ if (rtn < 0)
-+ {
-+ if (errno == EINTR)
-+ continue;
-+ }
-+
-+ if (rtn && FD_ISSET(sock, &rmask))
-+ {
-+ query = NULL;
-+ query = PGRread_packet(sock,&header);

-+ if ((query == NULL) || (header.cmdSts == 0))
-+ {
-+
-+ if (exist_sys_log)
-+ {
-+ show_error("%s:upper cascade
closed? , errno=%d(%s)",func,errno,strerror(errno));
-+ memset(&header, 0,
sizeof(ReplicateHeader));
-+ header.cmdSys = CMD_SYS_CALL;
-+ header.cmdSts =
CMD_STS_QUERY_SUSPEND;
-+ header.query_size = htonl(0);
-+
PGRsend_rlog_to_local(&header, NULL);
-+ exist_sys_log = false;
-+ }
-+ else
-+ {
-+ int recovery_status =
PGRget_recovery_status();
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:session
closed",func);
-+#endif
-+ if (recovery_status ==
RECOVERY_START)
-+ {
-+
header_save_for_recovering.cmdSts=CMD_TYPE_OTHER;
-+
header_save_for_recovering.cmdType=CMD_TYPE_CONNECTION_CLOSE;
-+
header_save_for_recovering.query_size = htonl(21);
-+
PGRdo_replicate(sock,&header_save_for_recovering,"PGR_CLOSE_CONNECTION");
-+ }
-+
-+ if(exist_replicate)
-+ {
-+ int recovery_status =
0;
-+
-+
PGRsem_lock(RecoverySemID,SEM_NUM_OF_RECOVERY);
-+ if
(Recovery_Status_Inf->transaction_count > 0)
-+ {
-+
Recovery_Status_Inf->transaction_count --;
-+ }
-+
PGRsem_unlock(RecoverySemID, SEM_NUM_OF_RECOVERY);

-+#ifdef PRINT_DEBUG
-+
show_debug("transaction_status: %d",Recovery_Status_Inf->transaction_count);
-+#endif
-+
recovery_status=PGRget_recovery_status();
-+
header_save_for_recovering.cmdSts=CMD_TYPE_OTHER;
-+
header_save_for_recovering.cmdType=CMD_TYPE_CONNECTION_CLOSE;
-+
header_save_for_recovering.query_size = htonl(21);
-+
PGRdo_replicate(sock,&header_save_for_recovering,"PGR_CLOSE_CONNECTION");
-+ }
-+ PGRsend_notice_quit();
-+ }
-+ break;
-+ }
-+ cnt = 0;
-+ memcpy(&header_save_for_recovering,
-+ &header,
-+ sizeof(ReplicateHeader));
-+ switch (header.cmdSys)
-+ {
-+ case CMD_SYS_PREREPLICATE:
-+
if(Cascade_Inf!=NULL ||
-+
Cascade_Inf->upper == NULL)
-+ {
-+
/* 1 means "I am primary replicate server." */
-+
PGRreturn_result(sock,"1", PGR_NOWAIT_ANSWER);
-+ }
-+ else
-+ {
-+
/* 1 means "I am not primary replicate server." */
-+
PGRreturn_result(sock,"0", PGR_NOWAIT_ANSWER);
-+ }
-+ break;
-+ case CMD_SYS_REPLICATE:
-+ status =
PGRdo_replicate(sock,&header,query);
-+ if
(header.cmdSts == CMD_STS_TRANSACTION )
-+ {
-+
switch(header.cmdType)
-+
{
-+
case CMD_TYPE_BEGIN:
-+
exist_replicate=true;
-+
memcpy(&header_save_for_recovering,
-+
&header,
-+
sizeof(ReplicateHeader));
-+
break;
-+
case CMD_TYPE_COMMIT:
-+
case CMD_TYPE_ROLLBACK:
-+
exist_replicate=false;
-+
break;
-+
}
-+ }
-+ else
-+ {
-+
if ( header.cmdType == CMD_TYPE_COPY )
-+
{
-+
exist_replicate=true;
-+
memcpy(&header_save_for_recovering,
-+
&header,
-+
sizeof(ReplicateHeader));
-+
}
-+
else if (header.cmdType == CMD_TYPE_COPY_DATA_END)
-+
{
-+
exist_replicate=false;
-+
}
-+ }
-+
-+ break;
-+ case CMD_SYS_LOG:
-+ exist_sys_log
= true;
-+
PGRsend_rlog_to_local(&header, query);
-+ /* set own
replicate id by rlog */
-+
PGRset_replication_id(ntohl(header.replicate_id));
-+
PGRsend_notice_rlog_done(sock);
-+ break;
-+ case CMD_SYS_CASCADE:
-+ PGR_Cascade =
true;
-+
PGRcascade_main(sock,&header,query);
-+ break;
-+ case CMD_SYS_CALL:
-+ if
(header.cmdSts == CMD_STS_TRANSACTION_ABORT)
-+ {
-+
if (header.cmdType == CMD_TYPE_FRONTEND_CLOSED)
-+
{
-+
header_save_for_recovering.cmdSts=CMD_TYPE_OTHER;
-+
header_save_for_recovering.cmdType=CMD_TYPE_CONNECTION_CLOSE;
-+
header_save_for_recovering.query_size = htonl(21);
-+

PGRdo_replicate(sock,&header_save_for_recovering,"PGR_CLOSE_CONNECTION");
-+
}
-+
else
-+
{
-+
PGRreconfirm_commit(sock,&header);
-+
}
-+ }
-+ else if
(header.cmdSts == CMD_STS_NOTICE)
-+ {
-+
-+ }
-+ else if
(header.cmdSts == CMD_STS_RESPONSE)
-+ {
-+
if (header.cmdType == CMD_TYPE_FRONTEND_CLOSED)
-+
{
-+#ifdef PRINT_DEBUG
-+
show_debug("replicate_loop ends due to frontend_closed.");
-+#endif
-+
PGRsend_notice_rlog_done(sock);
-+
status = LOOP_END;
-+
}
-+ }
-+ break;
-+ default:
-+#ifdef PRINT_DEBUG
-+
show_debug("WARNING: unknown Header->cmdSys %c",header.cmdSys);
-+#endif
-+ }
-+ }
-+ if (status == LOOP_END)
-+ {
-+ break;
-+ }
-+ }
-+
-+ pthread_mutex_destroy(&transaction_table_mutex);
-+ PGR_Close_Sock(&sock);
-+ if (query != NULL)
-+ {
-+ free(query);
-+ query = NULL;
-+ }
-+ PGRclear_connections();
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:replicate loop exit",func);
-+#endif
-+ exit(0);
-+ }
-+ else
-+ {
-+ PGR_Close_Sock(&sock);
-+ return 0;
-+ }
-+}
-+
-+static void
-+startup_replication_server(void)
-+{
-+ ReplicateHeader header;
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+ char userName[USERNAME_MAX_LENGTH];
-+ char query[256];
-+
-+ if (PGRuserName == NULL)
-+ {
-+ PGRuserName = getenv("LOGNAME");
-+ if (PGRuserName == NULL)
-+ {
-+ PGRuserName = getenv("USER");
-+ if (PGRuserName == NULL)
-+ PGRuserName = "postgres";
-+ }
-+ }
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ memset(query,0,sizeof(query));
-+ memset(hostName,0,sizeof(hostName));
-+ memset(userName,0,sizeof(userName));
-+ gethostname(hostName,sizeof(hostName)-1);
-+ strncpy(userName ,PGRuserName,sizeof(userName)-1);
-+ snprintf(query,sizeof(query)-1,"SELECT %s(%d,'%s',%d,%d)",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_STARTUP_REPLICATION_SERVER_FUNC_NO,
-+ hostName,
-+ Port_Number,
-+ Recovery_Port_Number);
-+ header.cmdSts = CMD_STS_NOTICE;
-+ header.query_id = htonl(PGRget_next_query_id());
-+ header.query_size = htonl(strlen(query));
-+ memcpy(header.from_host,hostName,sizeof(header.from_host));
-+ memcpy(header.userName,userName,sizeof(header.userName));
-+ strcpy(header.dbName,"template1");
-+ replicate_packet_send_internal( &header,
query,-1,PGRget_recovery_status(),true);
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * replicate_main()
-+ * NOTES
-+ * Replication main module
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+replicate_main(void)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "replicate_main()";
-+#endif
-+ int status;
-+ int rtn;
-+
-+ /* cascade start up notice */
-+ if (Cascade_Inf->upper != NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("initialize cascade information");
-+#endif
-+ PGRstartup_cascade();
-+ }
-+
-+ status = PGR_Create_Socket_Bind(&ReplicateSock, "", Port_Number);
-+
-+ if (status != STATUS_OK)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s %d port bind failed. quit.",func,Port_Number);
-+#endif
-+ stop_pgreplicate();
-+ PGRreplicate_exit(0);
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s %d port bind OK",func,Port_Number);
-+#endif
-+
-+
-+ /* replication start up notice */
-+ startup_replication_server();
-+
-+ for (;;)
-+ {
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ if (exit_processing == true)
-+ PGRreplicate_exit(0);
-+
-+ timeout.tv_sec = PGR_RECV_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(ReplicateSock,&rmask);
-+ rtn = select(ReplicateSock+1, &rmask, (fd_set *)NULL, (fd_set
*)NULL, &timeout);
-+ if (rtn < 0)
-+ continue;
-+
-+ if (rtn && FD_ISSET(ReplicateSock, &rmask))
-+ {
-+ /*
-+ * get recovery status.
-+ */
-+ PGRcheck_recovered_host();
-+
-+ if (exit_processing == true)
-+ break;
-+
-+ /*
-+ * call replication module
-+ */
-+ replicate_loop(ReplicateSock);
-+ }
-+ }
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * quick_exit()
-+ * NOTES
-+ * Exit child process
-+ * ARGS
-+ * SIGNAL_ARGS: receive signal number(I)
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+quick_exit(SIGNAL_ARGS)
-+{
-+#ifdef PRINT_DEBUG
-+ show_debug("quick_exit:signo = %d", postgres_signal_arg);
-+#endif
-+ exit(0);
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * daemonize()
-+ * NOTES
-+ * Daemonize this process
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+daemonize(void)
-+{
-+ char * func = "daemonize()";
-+ int i;
-+ pid_t pid;
-+
-+ pid = fork();
-+ if (pid == (pid_t) -1)
-+ {
-+ show_error("%s:fork() failed. reason: %s",func,
strerror(errno));
-+ exit(1);
-+ return; /* not reached */
-+ }
-+ else if (pid > 0)
-+ { /* parent */
-+ exit(0);
-+ }
-+
-+#ifdef HAVE_SETSID
-+ if (setsid() < 0)
-+ {
-+ show_error("%s:setsid() failed. reason:%s",
func,strerror(errno));
-+ exit(1);
-+ }
-+#endif
-+
-+ i = open("/dev/null", O_RDWR);
-+ dup2(i, 0);
-+ dup2(i, 1);
-+ dup2(i, 2);
-+ close(i);
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * write_pid_file()
-+ * NOTES
-+ * The process ID is written in the file.
-+ * This process ID is used when finish pglb.
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+write_pid_file(void)
-+{
-+ char * func = "write_pid_file()";
-+ FILE *fd;
-+ char fname[256];
-+ char pidbuf[128];
-+
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Write_Path,
PGREPLICATE_PID_FILE);
-+ fd = fopen(fname, "w");
-+ if (!fd)
-+ {
-+ show_error("%s:could not open pid file as %s. reason: %s",
-+ func, fname, strerror(errno));
-+ exit(1);
-+ }
-+ snprintf(pidbuf, sizeof(pidbuf), "%d", getpid());
-+ fwrite(pidbuf, strlen(pidbuf), 1, fd);
-+ if (fclose(fd))
-+ {
-+ show_error("%s:could not write pid file as %s. reason: %s",
-+ func,fname, strerror(errno));
-+ exit(1);
-+ }
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * stop_pgreplicate()
-+ * NOTES
-+ * Stop the pgreplicate process
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+stop_pgreplicate(void)
-+{
-+ char * func = "stop_pgreplicate()";
-+ FILE *fd;
-+ char fname[256];
-+ char pidbuf[128];
-+ pid_t pid;
-+
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Write_Path,
PGREPLICATE_PID_FILE);
-+ fd = fopen(fname, "r");
-+ if (!fd)
-+ {
-+ show_error("%s:could not open pid file as %s. reason: %s",
-+ func,fname, strerror(errno));
-+ exit(1);
-+ }
-+ memset(pidbuf,0,sizeof(pidbuf));
-+ fread(pidbuf, sizeof(pidbuf), 1, fd);
-+ fclose(fd);
-+ pid = atoi(pidbuf);
-+
-+ if (kill (pid,SIGTERM) == -1)
-+ {
-+ show_error("%s:could not stop pid: %d, reason:
%s",func,pid,strerror(errno));
-+ exit(1);
-+ }
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * is_exist_pid_file()
-+ * NOTES
-+ * Check existence of pid file.
-+ * ARGS
-+ * void
-+ * RETURN
-+ * 1: the pid file is exist
-+ * 0: the pid file is not exist
-+ *--------------------------------------------------------------------
-+ */
-+static bool
-+is_exist_pid_file(void)
-+{
-+ char fname[256];
-+ struct stat buf;
-+
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Write_Path,
PGREPLICATE_PID_FILE);
-+ if (stat(fname,&buf) == 0)
-+ {
-+ /* pid file is exist */
-+ return true;
-+ }
-+ else
-+ {
-+ /* pid file is not exist */
-+ return false;
-+ }
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * child_wait()
-+ * NOTES
-+ * Waiting for hung up a child
-+ * ARGS
-+ * int signal_args: signal number (expecting the SIGCHLD)
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+void
-+child_wait(SIGNAL_ARGS)
-+{
-+ pid_t pid = 0;
-+
-+ do {
-+ int ret;
-+ pid = waitpid(-1,&ret,WNOHANG);
-+ } while(pid > 0);
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * usage()
-+ * NOTES
-+ * show usage of pglb
-+ * ARGS
-+ * void
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+static void
-+usage(void)
-+{
-+ char * path;
-+
-+ path = getenv("PGDATA");
-+ if (path == NULL)
-+ path = ".";
-+ fprintf(stderr,"PGReplicate version [%s]\n",PGREPLICATE_VERSION);
-+ fprintf(stderr,"A replication server for cluster DB servers (based on
PostgreSQL)\n\n");
-+ fprintf(stderr,"usage: pgreplicate [-D path_of_config_file] [-W
path_of_work_files] [-U login user][-l][-n][-v][-h][stop]\n");
-+ fprintf(stderr," config file default path: %s/%s\n",path,
PGREPLICATE_CONF_FILE);
-+ fprintf(stderr," -l: print error logs in the log file.\n");
-+ fprintf(stderr," -n: don't run in daemon mode.\n");
-+ fprintf(stderr," -v: debug mode. need '-n' flag\n");
-+ fprintf(stderr," -h: print this help\n");
-+ fprintf(stderr," stop: stop pgreplicate\n");
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * main()
-+ * NOTES
-+ * main module of pgreplicate
-+ * ARGS
-+ * int argc: number of parameter
-+ * char ** argv: value of parameter
-+ * RETURN
-+ * none
-+ *--------------------------------------------------------------------
-+ */
-+int
-+main(int argc, char * argv[])
-+{
-+ char * func = "main()";
-+ int opt = 0;
-+ pid_t pgid = 0;
-+ pid_t pid = 0;
-+ char * r_path = NULL;
-+ char * w_path = NULL;
-+ bool detach = true;
-+ pid_t rlog_pid;
-+
-+ r_path = getenv("PGDATA");
-+ if (r_path == NULL)
-+ r_path = ".";
-+ while ((opt = getopt(argc, argv, "U:D:W:w:lvnh")) != -1)
-+ {
-+ switch (opt)
-+ {
-+ case 'U':
-+ if (!optarg)
-+ {
-+ usage();
-+ exit(1);
-+ }
-+ PGRuserName = strdup(optarg);
-+ break;
-+ case 'D':
-+ if (!optarg)
-+ {
-+ usage();
-+ exit(1);
-+ }
-+ r_path = optarg;
-+ break;
-+ case 'W':
-+ if (!optarg)
-+ {
-+ usage();
-+ exit(1);
-+ }
-+ w_path = optarg;
-+ break;
-+ case 'w':
-+ fork_wait_time = atoi(optarg);
-+ break;
-+ case 'l':
-+ Log_Print = 1;
-+ break;
-+ case 'v':
-+ Debug_Print = 1;
-+ break;
-+ case 'n':
-+ detach = false;
-+ break;
-+ case 'h':
-+ usage();
-+ exit(0);
-+ break;
-+ default:
-+ usage();
-+ exit(1);
-+ }
-+ }
-+ PGR_Data_Path = r_path;
-+ if (w_path == NULL)
-+ {
-+ PGR_Write_Path = PGR_Data_Path;
-+ }
-+ else
-+ {
-+ PGR_Write_Path = w_path;
-+ }
-+
-+ if (optind == (argc-1) && !strncasecmp(argv[optind],"stop",4))
-+ {
-+ stop_pgreplicate();
-+ exit(0);
-+ }
-+ else if (optind == argc)
-+ {
-+ if (is_exist_pid_file())
-+ {
-+ fprintf(stderr,"pid file %s/%s found. is another
pgreplicate running?", PGR_Write_Path, PGREPLICATE_PID_FILE);
-+ exit(1);
-+ }
-+ }
-+ else if (optind < argc)
-+ {
-+ usage();
-+ exit(1);
-+ }
-+
-+ if (detach)
-+ {
-+ daemonize();
-+ }
-+ write_pid_file();
-+ pgreplicate_pid = getpid();
-+
-+ signal(SIGINT, set_exit_processing);
-+ signal(SIGQUIT, set_exit_processing);
-+ signal(SIGTERM, set_exit_processing);
-+ signal(SIGCHLD, child_wait);
-+ signal(SIGPIPE, SIG_IGN);
-+
-+ if (PGRget_Conf_Data(PGR_Data_Path) != STATUS_OK)
-+ {
-+ show_error("%s:PGRget_Conf_Data error",func);
-+ PGRreplicate_exit(0);
-+ }
-+ if (PGRinit_recovery() != STATUS_OK)
-+ {
-+ show_error("%s:PGRinit_recovery error",func);
-+ PGRreplicate_exit(0);
-+ }
-+ if (PGRload_replication_id() != STATUS_OK)
-+ {
-+ show_error("%s:PGRload_replication_id error",func);
-+ PGRreplicate_exit(0);
-+ }
-+
-+ pgid = getpgid(0);
-+ if ( PGR_Use_Replication_Log == true )
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("Use Replication Log. Start PGR_RLog_Main()");
-+#endif
-+ rlog_pid = PGR_RLog_Main();
-+ if (rlog_pid < 0)
-+ {
-+ show_error("%s:PGR_RLog_Main failed",func);
-+ PGRreplicate_exit(0);
-+ }
-+ }
-+
-+ pid = fork();
-+ if (pid == (pid_t) -1)
-+ {
-+ show_error("%s:fork() failed. reason: %s",
func,strerror(errno));
-+ exit(1);
-+ }
-+ if (pid == 0)
-+ {
-+ signal(SIGCHLD, SIG_DFL);
-+ signal(SIGHUP, quick_exit);
-+ signal(SIGINT, quick_exit);
-+ signal(SIGQUIT, quick_exit);
-+ signal(SIGTERM, quick_exit);
-+ signal(SIGPIPE, SIG_IGN);
-+ /*
-+ * in child process,
-+ * call recovery module
-+ */
-+ setpgid(0,pgid);
-+
-+ if (fork_wait_time > 0) {
-+#ifdef PRINT_DEBUG
-+ show_debug("recovery process: wait fork(): pid = %d",
getpid());
-+#endif
-+ sleep(fork_wait_time);
-+ }
-+
-+ PGRrecovery_main();
-+ }
-+ else
-+ {
-+ /*
-+ * call replicate module
-+ */
-+ Replicateion_Log->r_log_sock =-1;
-+
-+ if (fork_wait_time > 0) {
-+#ifdef PRINT_DEBUG
-+ show_debug("replicate process: wait fork(): pid =
%d", getpid());
-+#endif
-+ sleep(fork_wait_time);
-+ }
-+
-+ replicate_main();
-+ }
-+
-+ PGRreplicate_exit(0);
-+ return STATUS_OK;
-+}
-+
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/pgreplicate.conf.sample
pgcluster-1.5.0rc7/src/pgcluster/pgrp/pgreplicate.conf.sample
---- postgresql-8.1.2/src/pgcluster/pgrp/pgreplicate.conf.sample
1970-01-01 01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/pgreplicate.conf.sample
2006-02-09 17:55:02.000000000 +0100
-@@ -0,0 +1,84 @@
-+#=============================================================
-+# PGReplicate configuration file
-+#-------------------------------------------------------------
-+# file: pgreplicate.conf
-+#-------------------------------------------------------------
-+# This file controls:
-+# o which hosts & port are cluster server
-+# o which port use for replication request from cluster server
-+#=============================================================
-+#
-+#-------------------------------------------------------------
-+# A setup of Cluster DB(s)
-+#
-+# o Host_Name : The host name of Cluster DB.
-+# -- please write a host name by FQDN.
-+# -- do not write IP address.
-+# o Port : The connection port with postmaster.
-+# o Recovery_Port : The connection port at the time of
-+# a recovery sequence .
-+#-------------------------------------------------------------
-+#<Cluster_Server_Info>
-+# <Host_Name> master.postgres.jp </Host_Name>
-+# <Port> 5432 </Port>
-+# <Recovery_Port> 7001 </Recovery_Port>
-+#</Cluster_Server_Info>
-+#<Cluster_Server_Info>
-+# <Host_Name> cluster2.postgres.jp </Host_Name>
-+# <Port> 5432 </Port>
-+# <Recovery_Port> 7001 </Recovery_Port>
-+#</Cluster_Server_Info>
-+#<Cluster_Server_Info>
-+# <Host_Name> cluster3.postgres.jp </Host_Name>
-+# <Port> 5432 </Port>
-+# <Recovery_Port> 7001 </Recovery_Port>
-+#</Cluster_Server_Info>
-+#
-+#-------------------------------------------------------------
-+# A setup of Load Balance Server
-+#
-+# o Host_Name : The host name of a load balance server.
-+# -- please write a host name by FQDN.
-+# -- do not write IP address.
-+# o Recovery_Port : The connection port at the time of
-+# a recovery sequence .
-+#-------------------------------------------------------------
-+#<LoadBalance_Server_Info>
-+# <Host_Name> loadbalancer.postgres.jp </Host_Name>
-+# <Recovery_Port> 6001 </Recovery_Port>
-+#</LoadBalance_Server_Info>
-+#
-+#------------------------------------------------------------
-+# A setup of the upper replication server for cascade connection.
-+#
-+# o Host_Name : The host name of Cluster DB.
-+# -- please write a host name by FQDN.
-+# -- do not write IP address.
-+# o Port : The connection port with postmaster.
-+# o Recovery_Port : The connection port at the time of
-+# a recovery sequence .
-+#------------------------------------------------------------
-+#<Replicate_Server_Info>
-+# <Host_Name> upper_replicate.postgres.jp </Host_Name>
-+# <Port> 8002 </Port>
-+# <Recovery_Port> 8102 </Recovery_Port>
-+#</Replicate_Server_Info>
-+#
-+#-------------------------------------------------------------
-+# A setup of a replication server
-+#
-+# o Replicate_Port : connection for replication
-+# o Recovery_Port : connection for recovery
-+# o Response_mode : timing which returns a response
-+# normal -- return result of DB which received the query
-+# reliable -- return result after waiting for response of
-+# all Cluster DBs.
-+# o Use_Replication_Log : use replication log
-+# [yes/no]. default : no
-+# o RLOG_Port : connection for replication log
-+#-------------------------------------------------------------
-+<Replication_Port> 8001 </Replication_Port>
-+<Recovery_Port> 8101 </Recovery_Port>
-+<Response_Mode> normal </Response_Mode>
-+<Use_Replication_Log> no </Use_Replication_Log>
-+<RLOG_Port> 8301 </RLOG_Port>
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/pgreplicate.h
pgcluster-1.5.0rc7/src/pgcluster/pgrp/pgreplicate.h
---- postgresql-8.1.2/src/pgcluster/pgrp/pgreplicate.h 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/pgreplicate.h 2006-02-09
17:46:34.000000000 +0100
-@@ -0,0 +1,414 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * pgreplicate.h
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#ifndef PGREPLICATE_H
-+#define PGREPLICATE_H
-+
-+#define PGREPLICATE_VERSION "1.5.0rc7"
-+
-+#include "lib/dllist.h"
-+#include "lib/stringinfo.h"
-+#include "../libpgc/libpgc.h"
-+
-+/* cascade packet id */
-+#define CMD_SYS_CASCADE 'C'
-+#define CMD_STS_TO_UPPER 'U'
-+#define CMD_STS_TO_LOWER 'L'
-+#define CMD_TYPE_ADD 'A'
-+#define CMD_TYPE_DELTE 'D'
-+#define CMD_TYPE_UPDATE_ALL 'A'
-+
-+/* log packet id */
-+#define CMD_SYS_LOG 'L'
-+#define CMD_STS_DELETE_QUERY 'q'
-+#define CMD_STS_DELETE_TRANSACTION 't'
-+#define CMD_STS_UPDATE_QUERY 'r'
-+#define CMD_STS_UPDATE_TRANSACTION 'u'
-+
-+#define INIT_TRANSACTION_TBL_NUM (12)
-+#define MAX_HOST_NAME_LEN (128)
-+#define MAX_DB_SERVER (32)
-+#define MAX_CONNECTIONS (128)
-+#define PGR_MAX_TICKETS (0x7FFFFFFF)
-+#define PGR_MAX_QUERY_ID (0x7FFFFFFF)
-+#define PGR_CONNECT_RETRY_TIME (3)
-+#define PGR_EXEC_RETRY_TIME (5)
-+#define DB_TBL_FREE (0)
-+#define DB_TBL_INIT (1)
-+#define DB_TBL_USE (2)
-+#define DB_TBL_ERROR (-1)
-+#define DB_TBL_TOP (10)
-+#define DB_TBL_END (11)
-+#define RECOVERY_HEADER_MTYPE (1)
-+#define QUERY_LOG_MTYPE (2)
-+#define PGREPLICATE_CONF_FILE "pgreplicate.conf"
-+#define PGREPLICATE_LOG_FILE "pgreplicate.log"
-+#define PGREPLICATE_STATUS_FILE "pgreplicate.sts"
-+#define PGREPLICATE_PID_FILE "pgreplicate.pid"
-+#define PGREPLICATE_RID_FILE "pgreplicate.rid"
-+#define RECOVERY_QUEUE_FILE ".pgr_recovery."
-+#define CLUSTER_SERVER_TAG "Cluster_Server_Info"
-+#define LOAD_BALANCE_SERVER_TAG "LoadBalance_Server_Info"
-+#define REPLICATE_PORT_TAG "Replication_Port"
-+#define RECOVERY_PORT_TAG "Recovery_Port"
-+#define LIFECHECK_PORT_TAG "LifeCheck_Port"
-+#define RLOG_PORT_TAG "RLOG_Port"
-+#define RESPONSE_MODE_TAG "Response_Mode"
-+#define RESPONSE_MODE_FAST "fast"
-+#define RESPONSE_MODE_NORMAL "normal"
-+#define RESPONSE_MODE_RELIABLE "reliable"
-+#define USE_REPLICATION_LOG_TAG "Use_Replication_Log"
-+#define RESERVED_CONNECTIONS_TAG "Reserved_Connections"
-+/* semapho numner of recovery queue */
-+#define SEM_NUM_OF_RECOVERY (1)
-+#define SEM_NUM_OF_RECOVERY_QUEUE (2)
-+/* semapho numner of lock tickets */
-+#define SEM_NUM_OF_LOCK (1)
-+#define STATUS_LOCK_CONFLICT (2)
-+#define STATUS_DEADLOCK_DETECT (3)
-+#define STATUS_ABORTED (4)
-+#define STATUS_NOT_YET_REPLICATE (5)
-+#define STATUS_ALREADY_REPLICATED (6)
-+#define STATUS_SKIP_REPLICATE (7)
-+#define PGR_NOWAIT_ANSWER (0)
-+#define PGR_WAIT_ANSWER (1)
-+#define LOOP_CONTINUE (0)
-+#define LOOP_END (1)
-+#define LOWER_CASCADE (1)
-+#define UPPER_CASCADE (2)
-+#define ALL_CASCADE (3)
-+#define NOTICE_SYSTEM_CALL_TYPE (10)
-+#define RECOVERY_QUERY_TYPE (20)
-+
-+#define PGR_TIME_OUT (60)
-+#define PGR_SEND_RETRY_CNT (1000)
-+#define PGR_SEND_WAIT_MSEC (50)
-+#define PGR_RECV_RETRY_CNT (1000)
-+#define PGR_RECV_WAIT_MSEC (50)
-+#define PGR_SEM_UNLOCK_WAIT_MSEC (100)
-+#define PGR_SEM_LOCK_WAIT_MSEC (500)
-+#define PGR_RECV_TIMEOUT (10)
-+#define PGR_SEND_TIMEOUT (600)
-+#define PGR_LOCK_WAIT_MSEC (50)
-+#define PGR_LOCK_TIMEOUT (60)
-+#define PGR_RECOVERY_RETRY_CNT (6000)
-+#define PGR_RECOVERY_WAIT_MSEC (500)
-+#define PGR_CHECK_POINT (300)
-+
-+#define PGR_RECOVERY_1ST_STAGE (1)
-+#define PGR_RECOVERY_2ND_STAGE (2)
-+
-+#define IDLE_MODE (0)
-+#define BUSY_MODE (1)
-+
-+/*
-+ * connection table for transaction query
-+ */
-+typedef struct {
-+ int useFlag;
-+ int lock;
-+ int transaction_count;
-+ unsigned short port;
-+ unsigned short pid;
-+ unsigned int hostIP;
-+ unsigned int srcHostIP;
-+ char host[HOSTNAME_MAX_LENGTH];
-+ char srcHost[HOSTNAME_MAX_LENGTH];
-+ char dbName[DBNAME_MAX_LENGTH];
-+ bool in_transaction;
-+ PGconn * conn;
-+}TransactionTbl;
-+
-+/*
-+ * cluster server table
-+ */
-+typedef struct {
-+ int useFlag;
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+ char resolvedName[21];
-+ int port;
-+ int recoveryPort;
-+ int hostNum;
-+ int transaction_count;
-+}HostTbl;
-+
-+
-+typedef struct {
-+ FILE * queue_fp;
-+ int current_queue_no;
-+} RecoveryQueueInf;
-+
-+
-+/*
-+ * host table for recovery request
-+ */
-+typedef struct {
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+ int port;
-+ int recoveryPort;
-+ int sock;
-+ int recovery_sock;
-+} RecoveryTbl;
-+
-+/*
-+ * status table for recovery
-+ */
-+typedef struct {
-+ int useFlag;
-+ int transaction_count;
-+ int recovery_status;
-+ unsigned int replication_id;
-+ HostTbl target_host;
-+ int read_queue_no;
-+ int write_queue_no;
-+ int check_point;
-+} RecoveryStatusInf;
-+
-+typedef struct {
-+ long mtype;
-+ long query_mtype;
-+ char mdata[1];
-+} RecoveryQueueHeader;
-+
-+typedef struct {
-+ long mtype;
-+ unsigned int replicationId;
-+ char mdata[1];
-+} RecoveryQueueQuery;
-+
-+typedef struct {
-+ unsigned int entry_ticket;
-+ unsigned int lock_wait_queue_length;
-+ int overflow;
-+} LockWaitInf;
-+
-+typedef struct {
-+ int response_mode;
-+ int current_cluster;
-+} ResponseInf;
-+
-+typedef struct {
-+ ReplicateHeader * header;
-+ char * query;
-+ char * next;
-+ char * last;
-+} QueryLogType;
-+
-+typedef struct {
-+ ReplicateServerInfo * top;
-+ ReplicateServerInfo * end;
-+ ReplicateServerInfo * lower;
-+ ReplicateServerInfo * upper;
-+ ReplicateServerInfo * myself;
-+ int useFlag;
-+} CascadeInf;
-+
-+typedef struct {
-+ union
-+ {
-+ int useFlag;
-+ int commit_log_num;
-+ } inf;
-+ ReplicateHeader header;
-+} CommitLogInf;
-+
-+typedef struct {
-+ int useFlag;
-+ char * RLog_Sock_Path;
-+ uint16_t RLog_Port_Number;
-+ int r_log_sock;
-+ ReplicateHeader * header;
-+ char * query;
-+} ReplicationLogInf;
-+
-+typedef struct {
-+ char hostName[HOSTNAME_MAX_LENGTH];
-+ uint16_t port;
-+ uint16_t pid;
-+ uint32_t request_id;
-+} QueryLogID;
-+
-+typedef struct {
-+ QueryLogID query_log_id;
-+ char * last;
-+ char * next;
-+} ConfirmQueryList;
-+
-+typedef struct {
-+ ReplicateHeader * header;
-+ char * query;
-+ int dest;
-+ HostTbl * host_ptr;
-+ int current_cluster;
-+ int transaction_count;
-+ TransactionTbl *transaction_tbl;
-+} ThreadArgInf;
-+
-+
-+/* replication server data */
-+extern uint16_t Port_Number;
-+extern uint16_t LifeCheck_Port_Number;
-+extern uint16_t Recovery_Port_Number;
-+extern int Reserved_Connections;
-+extern bool PGR_Parse_Session_Started;
-+
-+/* global tables */
-+extern HostTbl * Host_Tbl_Begin;
-+extern Dllist * Transaction_Tbl_Begin;
-+extern TransactionTbl * Transaction_Tbl_End;
-+extern RecoveryTbl * LoadBalanceTbl;
-+extern RecoveryStatusInf * Recovery_Status_Inf;
-+extern LockWaitInf * Lock_Wait_Tbl;
-+extern ReplicateHeader * PGR_Log_Header;
-+extern ReplicateServerInfo * Cascade_Tbl;
-+extern CascadeInf * Cascade_Inf;
-+extern CommitLogInf * Commit_Log_Tbl;
-+extern QueryLogType * Query_Log_Top;
-+extern QueryLogType * Query_Log_End;
-+extern ReplicationLogInf * Replicateion_Log;
-+extern int RecoveryShmid;
-+extern int ReplicateSerializationShmid;
-+extern int RecoveryMsgShmid;
-+extern int *RecoveryMsgid;
-+extern int HostTblShmid;
-+extern int LockWaitTblShmid;
-+extern int CascadeTblShmid;
-+extern int CascadeInfShmid;
-+extern int CommitLogShmid;
-+extern int MaxBackends;
-+extern char * PGR_Result;
-+extern int SemID;
-+extern int RecoverySemID;
-+extern int CascadeSemID;
-+extern int LockSemID;
-+extern int VacuumSemID;
-+extern char * PGR_Data_Path;
-+extern char * PGR_Write_Path;
-+extern FILE * LogFp;
-+extern FILE * StatusFp;
-+extern FILE * RidFp;
-+extern int Log_Print;
-+extern int Debug_Print;
-+extern char * Function;
-+extern int IS_SESSION_AUTHORIZATION;
-+extern ResponseInf * PGR_Response_Inf;
-+extern bool StartReplication[MAX_DB_SERVER];
-+extern bool PGR_Cascade;
-+extern bool PGR_Use_Replication_Log;
-+extern bool PGR_AutoCommit;
-+extern unsigned int * PGR_ReplicateSerializationID;
-+extern unsigned int * PGR_Send_Query_ID;
-+extern unsigned int PGR_Query_ID;
-+extern bool exit_processing;
-+extern RecoveryQueueInf RecoveryQueue;
-+extern int pgreplicate_pid;
-+
-+extern int ReplicateSock;
-+
-+/* smart shutdown */
-+extern int Idle_Flag;
-+extern bool Exit_Request;
-+
-+/*
-+ * external prototype in main.c
-+ */
-+extern void child_wait(SIGNAL_ARGS);
-+
-+/*
-+ * external prototype in conf.c
-+ */
-+extern int PGRget_Conf_Data(char * path);
-+
-+/*
-+ * external prototype in replicate.c
-+ */
-+extern int PGRset_replication_id(uint32_t rid);
-+extern bool PGRis_same_host(char * host1, unsigned short port1 , char *
host2, unsigned short port2);
-+extern HostTbl * PGRadd_HostTbl(HostTbl * conf_data, int useFlag);
-+extern HostTbl * PGRget_master(void);
-+extern void PGRset_recovery_status(int status);
-+extern int PGRget_recovery_status(void);
-+extern int PGRcheck_recovered_host(void);
-+extern int PGRset_recovered_host(HostTbl * target,int useFlag);
-+extern int PGRinit_recovery(void);
-+extern void set_exit_processing(int signo);
-+extern void PGRreplicate_exit(int exit_status);
-+extern int PGRsend_replicate_packet_to_server( HostTbl * host_ptr,
ReplicateHeader * header, char *query , char * result,unsigned int
replicationId, bool recovery);
-+extern int PGRreplicate_packet_send_each_server( HostTbl * ptr, bool
return_response, ReplicateHeader * header, char * query,int dest);
-+extern HostTbl * PGRget_HostTbl(char * hostName,int port);
-+extern int PGRset_queue(ReplicateHeader * header,char * query);
-+extern int PGRset_host_status(HostTbl * host_ptr,int status);
-+extern void PGRclear_connections(void);
-+extern void PGRsem_unlock( int semid, short sem_num );
-+extern void PGRsem_lock( int semid, short sem_num );
-+extern int PGRdo_replicate(int sock,ReplicateHeader *header, char * query);
-+extern int PGRreturn_result(int dest, char * result, int wait);
-+extern int PGRreplicate_packet_send( ReplicateHeader * header, char *
query,int dest,int recovery_status);
-+extern char * PGRread_packet(int sock, ReplicateHeader *header);
-+extern void PGRnotice_replication_server(char * hostName, unsigned short
portNumber,unsigned short recoveryPortNumber, unsigned short
lifecheckPortNumber, char * userName);
-+extern char * PGRread_query(int sock, ReplicateHeader *header);
-+extern int PGRwait_transaction_count_clear(HostTbl *host);
-+extern int PGRsync_oid(ReplicateHeader *header);
-+extern unsigned int PGRget_next_query_id(void);
-+extern int PGRinit_transaction_table(void);
-+extern int replicate_packet_send_internal(ReplicateHeader * header, char *
query,int dest,int recovery_status,bool isHeldLock);
-+extern int PGRsync_oid(ReplicateHeader *header);
-+extern int PGRload_replication_id(void);
-+
-+/*
-+ * external prototype in recovery.c
-+ */
-+extern int PGRsend_load_balance_packet(RecoveryPacket * packet);
-+extern void PGRrecovery_main(void);
-+extern FILE * PGRget_recovery_queue_file_for_write(void);
-+extern FILE * PGRget_recovery_queue_file_for_read(int next);
-+
-+/*
-+ * external prototype in rlog.c
-+ */
-+extern int PGRwrite_rlog(ReplicateHeader * header, char * query);
-+extern ReplicateHeader * PGRget_requested_query(ReplicateHeader * header);
-+extern void PGRreconfirm_commit(int sock, ReplicateHeader * header);
-+extern void PGRset_rlog(ReplicateHeader * header, char * query);
-+extern void PGRunset_rlog(ReplicateHeader * header, char * query);
-+extern int PGRresend_rlog_to_db(void);
-+extern void PGRreconfirm_query(int sock, ReplicateHeader * header);
-+extern pid_t PGR_RLog_Main(void);
-+extern int PGRcreate_send_rlog_socket(void);
-+extern int PGRsend_rlog_packet(int sock,ReplicateHeader * header, const
char * query_string);
-+extern int PGRrecv_rlog_result(int sock,void * result, int size);
-+extern int PGRsend_rlog_to_local(ReplicateHeader * header,char * query);
-+extern int PGRget_rlog_header(ReplicateHeader * header);
-+
-+/*
-+ * external prototype in cascade.c
-+ */
-+extern void PGRinit_cascade_child() ;
-+extern int PGRstartup_cascade(void);
-+extern int PGRsend_lower_cascade(ReplicateHeader * header, char * query);
-+extern int PGRsend_upper_cascade(ReplicateHeader * header, char * query);
-+extern int PGRwait_answer_cascade(int sock);
-+extern ReplicateServerInfo * PGRget_lower_cascade(void);
-+extern ReplicateServerInfo * PGRget_upper_cascade(void);
-+extern void PGRset_cascade_server_status(ReplicateServerInfo * cascade, int
status);
-+extern ReplicateServerInfo * PGRrecv_cascade_answer(ReplicateServerInfo *
cascade,ReplicateHeader * header);
-+extern int PGRsend_cascade(int sock , ReplicateHeader * header, char *
query);
-+extern int PGRcascade_main(int sock, ReplicateHeader * header, char *
query);
-+extern int PGRwait_notice_rlog_done(void);
-+extern int PGRsend_notice_rlog_done(int sock);
-+extern int PGRsend_notice_quit();
-+
-+/*
-+ * external prototype in pqformat.c
-+ */
-+extern const char * pq_getmsgstring(StringInfo msg);
-+extern unsigned int pq_getmsgint(StringInfo msg, int b);
-+extern void pq_copymsgbytes(StringInfo msg, char *buf, int datalen);
-+extern const char * pq_getmsgbytes(StringInfo msg, int datalen);
-+extern int pq_getmsgbyte(StringInfo msg);
-+
-+#endif /* PGREPLICATE_H */
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/pqformat.c
pgcluster-1.5.0rc7/src/pgcluster/pgrp/pqformat.c
---- postgresql-8.1.2/src/pgcluster/pgrp/pqformat.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/pqformat.c 2006-01-31
17:34:54.000000000 +0100
-@@ -0,0 +1,176 @@
-+/*-------------------------------------------------------------------------
-+ * pqformat.c
-+ * Routines for formatting and parsing frontend/backend messages
-+ *
-+ * These modules copyed from src/backend/libpq/pgformat.c.
-+ * Original modules have some shared modules and macro,
-+ * then it is difficult link to replication server directory.
-+ * Therefore, these modules were custamized.
-+ * (removed shared module and macro)
-+ *
-+ * Original source code is under the following copyright
-+ *
-+ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
-+ * Portions Copyright (c) 1994, Regents of the University of California
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+/*
-+ * INTERFACE ROUTINES
-+ * Message parsing after input:
-+ * pq_getmsgbyte - get a raw byte from a message buffer
-+ * pq_getmsgint - get a binary integer from a message buffer
-+ * pq_getmsgbytes - get raw data from a message buffer
-+ * pq_copymsgbytes - copy raw data from a message buffer
-+ * pq_getmsgstring - get a null-terminated text string (with
conversion)
-+ */
-+
-+/* --------------------------------
-+ * pq_getmsgstring - get a null-terminated text string (with
conversion)
-+ *
-+ * May return a pointer directly into the message buffer, or a
pointer
-+ * to a palloc'd conversion result.
-+ * --------------------------------
-+ */
-+
-+#include "postgres.h"
-+
-+#include <errno.h>
-+#include <sys/param.h>
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+#ifdef HAVE_ENDIAN_H
-+#include <endian.h>
-+#endif
-+
-+#if 0
-+#include "libpq/libpq.h"
-+#include "libpq/pqformat.h"
-+#endif
-+#include "mb/pg_wchar.h"
-+
-+#include "libpq-fe.h"
-+#include "libpq-int.h"
-+#include "fe-auth.h"
-+#include "replicate_com.h"
-+#include "pgreplicate.h"
-+
-+const char *
-+pq_getmsgstring(StringInfo msg)
-+{
-+ char *str;
-+ int slen;
-+
-+ if (msg == NULL)
-+ {
-+ return NULL;
-+ }
-+ str = &msg->data[msg->cursor];
-+ /*
-+ * It's safe to use strlen() here because a StringInfo is guaranteed
to
-+ * have a trailing null byte. But check we found a null inside the
-+ * message.
-+ */
-+ slen = strlen(str);
-+ if (msg->cursor + slen >= msg->len)
-+ {
-+ show_error("invalid string in message");
-+ return NULL;
-+ }
-+ msg->cursor += slen + 1;
-+
-+ return str;
-+}
-+
-+
-+/* --------------------------------
-+ * pq_getmsgint - get a binary integer from a message buffer
-+ *
-+ * Values are treated as unsigned.
-+ * --------------------------------
-+ */
-+unsigned int
-+pq_getmsgint(StringInfo msg, int b)
-+{
-+ unsigned int result;
-+ unsigned char n8;
-+ uint16 n16;
-+ uint32 n32;
-+
-+ switch (b)
-+ {
-+ case 1:
-+ pq_copymsgbytes(msg, (char *) &n8, 1);
-+ result = n8;
-+ break;
-+ case 2:
-+ pq_copymsgbytes(msg, (char *) &n16, 2);
-+ result = ntohs(n16);
-+ break;
-+ case 4:
-+ pq_copymsgbytes(msg, (char *) &n32, 4);
-+ result = ntohl(n32);
-+ break;
-+ default:
-+ show_error("unsupported integer size %d", b);
-+ result = 0; /* keep compiler
quiet */
-+ break;
-+ }
-+ return result;
-+}
-+
-+/* --------------------------------
-+ * pq_copymsgbytes - copy raw data from a message buffer
-+ *
-+ * Same as above, except data is copied to caller's buffer.
-+ * --------------------------------
-+ */
-+void
-+pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
-+{
-+ if (datalen < 0 || datalen > (msg->len - msg->cursor))
-+ {
-+ show_error("insufficient data left in message");
-+ return;
-+ }
-+ memcpy(buf, &msg->data[msg->cursor], datalen);
-+ msg->cursor += datalen;
-+}
-+
-+
-+/* --------------------------------
-+ * pq_getmsgbytes - get raw data from a message buffer
-+ *
-+ * Returns a pointer directly into the message buffer; note this
-+ * may not have any particular alignment.
-+ * --------------------------------
-+ */
-+const char *
-+pq_getmsgbytes(StringInfo msg, int datalen)
-+{
-+ const char *result;
-+
-+ if (datalen < 0 || datalen > (msg->len - msg->cursor))
-+ {
-+ show_error("insufficient data left in message");
-+ return NULL;
-+ }
-+ result = &msg->data[msg->cursor];
-+ msg->cursor += datalen;
-+ return result;
-+}
-+
-+/* --------------------------------
-+ * pq_getmsgbyte - get a raw byte from a message buffer
-+ * --------------------------------
-+ */
-+int
-+pq_getmsgbyte(StringInfo msg)
-+{
-+ if (msg->cursor >= msg->len)
-+ {
-+ show_error("no data left in message");
-+ return 0;
-+ }
-+ return (unsigned char) msg->data[msg->cursor++];
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/recovery.c
pgcluster-1.5.0rc7/src/pgcluster/pgrp/recovery.c
---- postgresql-8.1.2/src/pgcluster/pgrp/recovery.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/recovery.c 2006-01-31
23:44:12.000000000 +0100
-@@ -0,0 +1,1050 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * recovery.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at pgreplicate for the recovery.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#include "postgres.h"
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <sys/msg.h>
-+#include <netdb.h>
-+#include <netinet/in.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <arpa/inet.h>
-+#include <sys/param.h>
-+#include <sys/file.h>
-+
-+#ifdef HAVE_SYS_SELECT_H
-+#include <sys/select.h>
-+#endif
-+
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+#include "miscadmin.h"
-+#include "nodes/nodes.h"
-+
-+#include "libpq-fe.h"
-+#include "libpq/libpq-fs.h"
-+#include "libpq-int.h"
-+#include "fe-auth.h"
-+
-+#include "access/xact.h"
-+#include "replicate_com.h"
-+#include "pgreplicate.h"
-+
-+
-+#ifdef WIN32
-+#include "win32.h"
-+#else
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+#include <arpa/inet.h>
-+#endif
-+
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+#ifdef MULTIBYTE
-+#include "mb/pg_wchar.h"
-+#endif
-+#include "pgreplicate.h"
-+
-+
-+/*--------------------------------------
-+ * GLOBAL VARIABLE DECLARATION
-+ *--------------------------------------
-+ */
-+RecoveryPacket MasterPacketData;
-+RecoveryTbl Master;
-+RecoveryTbl Target;
-+
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+static int read_packet(int sock,RecoveryPacket * packet);
-+static int read_packet_from_master( RecoveryTbl * host, RecoveryPacket *
packet );
-+static int send_recovery_packet(int sock, RecoveryPacket * packet);
-+static int send_packet(RecoveryTbl * host, RecoveryPacket * packet );
-+static void start_recovery_prepare(void);
-+static void reset_recovery_prepare(void);
-+static void start_recovery(void);
-+static void finish_recovery(void);
-+static bool first_setup_recovery(int * sock, RecoveryPacket * packet);
-+static bool second_setup_recovery (RecoveryPacket * packet);
-+static void pgrecovery_loop(int fd);
-+static int PGRsend_queue(RecoveryTbl * master, RecoveryTbl * target);
-+static int send_vacuum(HostTbl *host, char * userName, int stage);
-+
-+#ifdef PRINT_DEBUG
-+static void show_recovery_packet(RecoveryPacket * packet);
-+#endif
-+
-+int PGRsend_load_balance_packet(RecoveryPacket * packet);
-+void PGRrecovery_main(void);
-+
-+/*-----------------------------------------------------------
-+ * SYMBOL
-+ * read_packet()
-+ * NOTES
-+ * Read recovery packet data
-+ * ARGS
-+ * int sock : socket
-+ * RecoveryPacket * packet : read packet buffer
-+ * RETURN
-+ * -1 : error
-+ * >0 : read size
-+ *-----------------------------------------------------------
-+ */
-+static int
-+read_packet(int sock,RecoveryPacket * packet)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "read_packet()";
-+#endif
-+ int r = 0;
-+ char * read_ptr = NULL;
-+ int read_size = 0;
-+ int packet_size = 0;
-+
-+ if (packet == NULL)
-+ {
-+ return -1;
-+ }
-+ read_ptr = (char*)packet;
-+ packet_size = sizeof(RecoveryPacket);
-+ for (;;)
-+ {
-+ r = recv(sock,read_ptr + read_size ,packet_size - read_size,
MSG_WAITALL);
-+ if (r < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+ else
-+ {
-+ show_error("%s:recv failed: %d(%s)",func,
errno, strerror(errno));
-+ return -1;
-+ }
-+ }
-+ else if (r > 0)
-+ {
-+ read_size += r;
-+ if (read_size == packet_size)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:receive packet",func);
-+ show_recovery_packet(packet);
-+#endif
-+ return read_size;
-+ }
-+ }
-+ else /* r == 0 */
-+ {
-+ show_error("%s:unexpected EOF", func);
-+ return -1;
-+ }
-+ }
-+ return -1;
-+}
-+
-+static int
-+read_packet_from_master( RecoveryTbl * host, RecoveryPacket * packet )
-+{
-+ int read_size = 0;
-+ int rtn;
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ for(;;)
-+ {
-+ timeout.tv_sec = PGR_RECV_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(host->recovery_sock,&rmask);
-+ rtn = select(host->recovery_sock+1, &rmask, (fd_set *)NULL,
(fd_set *)NULL, &timeout);
-+
-+ if (rtn == 0) /* timeout */
-+ {
-+ return -1;
-+ }
-+
-+ if (rtn && FD_ISSET(host->recovery_sock, &rmask))
-+ {
-+ read_size = read_packet(host->recovery_sock, packet);
-+ return read_size;
-+ }
-+ }
-+}
-+
-+static int
-+send_recovery_packet(int sock, RecoveryPacket * packet)
-+{
-+ char *func = "send_recovery_packet";
-+ char * send_ptr;
-+ int send_size= 0;
-+ int buf_size = 0;
-+ int s;
-+
-+ send_ptr = (char *)packet;
-+ buf_size = sizeof(RecoveryPacket);
-+
-+ for (;;)
-+ {
-+ s = send(sock, send_ptr + send_size,buf_size - send_size ,0);
-+ if (s < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+
-+ show_error("%s:send error: %d(%s)", func, errno,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ else if (s == 0)
-+ {
-+ show_error("%s:unexpected EOF", func);
-+ return STATUS_ERROR;
-+ }
-+
-+ send_size += s;
-+ if (send_size == buf_size)
-+ return STATUS_OK;
-+ }
-+}
-+
-+static int
-+send_packet(RecoveryTbl * host, RecoveryPacket * packet )
-+{
-+ char * func = "send_packet()";
-+ int count = 0;
-+
-+ if (host->recovery_sock == -1)
-+ {
-+ while(PGR_Create_Socket_Connect(&(host->recovery_sock),
host->hostName , host->recoveryPort) != STATUS_OK )
-+ {
-+ if (count > MAX_RETRY_TIMES )
-+ {
-+ show_error("%s:host[%s]
port[%d]PGR_Create_Socket_Connect failed",func,host->hostName,
host->recoveryPort);
-+ return STATUS_ERROR;
-+ }
-+ count ++;
-+ }
-+ }
-+ count = 0;
-+ while (send_recovery_packet(host->recovery_sock,packet) != STATUS_OK)
-+ {
-+ close(host->recovery_sock);
-+ host->recovery_sock = -1;
-+ PGR_Create_Socket_Connect(&(host->recovery_sock),
host->hostName , host->recoveryPort);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PGR_Create_Socket_Connectsock[%d] host[%s]
port[%d]",
-+
func,host->recovery_sock,host->hostName,host->recoveryPort);
-+#endif
-+ if (count > PGR_CONNECT_RETRY_TIME )
-+ {
-+
-+ show_error("%s:send failed and
PGR_Create_Socket_Connect failed",func);
-+ return STATUS_ERROR;
-+ }
-+ count ++;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static void
-+start_recovery_prepare(void)
-+{
-+ PGRset_recovery_status (RECOVERY_PREPARE_START);
-+}
-+
-+static void
-+reset_recovery_prepare(void)
-+{
-+ PGRset_recovery_status (RECOVERY_INIT);
-+}
-+
-+static void
-+start_recovery(void)
-+{
-+ PGRset_recovery_status (RECOVERY_START);
-+}
-+
-+static void
-+finish_recovery(void)
-+{
-+ PGRset_recovery_status (RECOVERY_INIT);
-+}
-+
-+int
-+PGRsend_load_balance_packet(RecoveryPacket * packet)
-+{
-+ char * func = "PGRsend_load_balance_packet()";
-+ RecoveryTbl * lbp;
-+ int status;
-+
-+ lbp = LoadBalanceTbl;
-+ if (lbp == (RecoveryTbl *)NULL)
-+ {
-+ show_error("%s:recovery table is NULL",func);
-+ return STATUS_ERROR;
-+ }
-+ while (lbp->hostName[0] != 0)
-+ {
-+ if (lbp->recovery_sock != -1)
-+ {
-+ close(lbp->recovery_sock);
-+ lbp->recovery_sock = -1;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:host[%s]
port[%d]",func,lbp->hostName,lbp->recoveryPort);
-+#endif
-+ status = send_packet(lbp,packet);
-+ if (lbp->recovery_sock != -1)
-+ {
-+ close(lbp->recovery_sock);
-+ lbp->recovery_sock = -1;
-+ }
-+ lbp ++;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+send_vacuum(HostTbl *host, char * userName, int stage)
-+{
-+ int rtn = STATUS_OK;
-+ ReplicateHeader header;
-+ char * query = NULL;
-+
-+ if (stage == PGR_RECOVERY_1ST_STAGE)
-+ {
-+ query = strdup("VACUUM");
-+ }
-+ else
-+ {
-+ query = strdup("VACUUM FULL");
-+ }
-+ memset(&header,0,sizeof(header));
-+ header.query_size = strlen(query) + 1;
-+ strncpy(header.dbName,"template1",sizeof(header.dbName));
-+ strncpy(header.userName,userName,sizeof(header.userName));
-+ header.cmdSys = CMD_SYS_REPLICATE;
-+ header.cmdSts = CMD_STS_QUERY;
-+ header.cmdType = CMD_TYPE_VACUUM;
-+ header.pid = getpid();
-+ header.query_id = getpid();
-+ header.isAutoCommit=1;
-+ rtn =
PGRsend_replicate_packet_to_server(host,&header,query,PGR_Result,0, true);
-+ if (query !=NULL)
-+ free(query);
-+ return rtn;
-+}
-+
-+static bool
-+first_setup_recovery(int * sock, RecoveryPacket * packet)
-+{
-+ char * func = "first_setup_recovery()";
-+ int status;
-+ HostTbl * master = (HostTbl *)NULL;
-+ bool loop_end = false;
-+ HostTbl host_tbl;
-+ char * userName = NULL;
-+
-+ memcpy(Target.hostName,packet->hostName,sizeof(Target.hostName));
-+ Target.port = ntohs(packet->port);
-+ Target.recoveryPort = ntohs(packet->recoveryPort);
-+ Target.sock = *sock;
-+ Target.recovery_sock = *sock;
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:1st setup target %s",func,Target.hostName);
-+ show_debug("%s:1st setup port %d",func,Target.port);
-+#endif
-+ /*
-+ * check another recovery process
-+ */
-+ if (PGRget_recovery_status() != RECOVERY_INIT)
-+ {
-+ /*
-+ * recovery process is already running
-+ */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:already recovery job runing",func);
-+#endif
-+ memset(packet,0,sizeof(packet));
-+ PGRset_recovery_packet_no(packet, RECOVERY_ERROR_OCCUPIED) ;
-+ status = send_packet(&Target,packet);
-+ loop_end = true;
-+ return loop_end;
-+ }
-+ /*
-+ * add recovery target to host table
-+ */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:add recovery target to host table",func);
-+#endif
-+ memcpy(host_tbl.hostName,packet->hostName,sizeof(host_tbl.hostName));
-+ host_tbl.port = ntohs(packet->port);
-+ PGRset_recovered_host(&host_tbl,DB_TBL_INIT);
-+ PGRadd_HostTbl(&host_tbl,DB_TBL_INIT);
-+ /*
-+ * send prepare recovery to load balancer
-+ */
-+ PGRsend_load_balance_packet(packet);
-+ userName = strdup(packet->userName);
-+
-+ /*
-+ * set RECOVERY_PGDATA_REQ packet data
-+ */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:set RECOVERY_PGDATA_REQ packet data",func);
-+#endif
-+ memset(packet,0,sizeof(RecoveryPacket));
-+ PGRset_recovery_packet_no(packet, RECOVERY_PGDATA_REQ );
-+
-+retry_connect_master:
-+ master = PGRget_master();
-+ if (master == (HostTbl *)NULL)
-+ {
-+ /*
-+ * connection error , master may be down
-+ */
-+ show_error("%s:get master info error , master may be
down",func);
-+ PGRset_recovery_packet_no(packet, RECOVERY_ERROR_TARGET_ONLY);
-+ status = send_packet(&Target, packet);
-+ reset_recovery_prepare();
-+ loop_end = true;
-+ if (userName != NULL)
-+ free(userName);
-+ return loop_end;
-+ }
-+ /* send vauum command to master server */
-+ status = send_vacuum(master, userName, PGR_RECOVERY_1ST_STAGE );
-+ if (status != STATUS_OK)
-+ {
-+ PGRset_host_status(master, DB_TBL_ERROR);
-+ goto retry_connect_master;
-+ }
-+
-+ memcpy(Master.hostName,master->hostName,sizeof(Master.hostName));
-+ Master.sock = -1;
-+ Master.recovery_sock = -1;
-+ Master.port = master->port;
-+ Master.recoveryPort = master->recoveryPort;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:send packet to master %s recoveryPort %d",func,
Master.hostName, Master.recoveryPort);
-+#endif
-+ status = send_packet(&Master, packet);
-+ if (status != STATUS_OK)
-+ {
-+ /*
-+ * connection error , master may be down
-+ */
-+ show_error("%s:connection error , master may be down",func);
-+ PGRset_host_status(master,DB_TBL_ERROR);
-+ goto retry_connect_master ;
-+ }
-+
-+ /*
-+ * start prepare of recovery
-+ * set recovery status to "prepare start"
-+ * start transaction count up
-+ */
-+ start_recovery_prepare();
-+ /*
-+ * wait answer from master server
-+ */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:wait answer from master server",func);
-+#endif
-+ memset(packet,0,sizeof(RecoveryPacket));
-+ read_packet_from_master(&Master, packet);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:get answer from
master:no[%d]",func,ntohs(packet->packet_no));
-+#endif
-+ if (ntohs(packet->packet_no) == RECOVERY_PGDATA_ANS)
-+ {
-+ /*
-+ * send a packet to load balancer that is stopped master's
-+ * load balancing until all recovery process is finished
-+ */
-+ PGRsend_load_balance_packet(packet);
-+ memcpy((char
*)&MasterPacketData,packet,sizeof(RecoveryPacket));
-+
-+ /*
-+ * prepare answer from master DB
-+ */
-+ PGRset_recovery_packet_no(packet, RECOVERY_PREPARE_ANS );
-+
memcpy(packet->hostName,Master.hostName,sizeof(packet->hostName));
-+ status = send_packet(&Target, packet);
-+ if (status != STATUS_OK)
-+ {
-+ show_error("%s:no[%d] send_packet to target
error",func,ntohs(packet->packet_no));
-+ PGRset_recovery_packet_no(packet,
RECOVERY_ERROR_TARGET_ONLY);
-+ status = send_packet(&Master,packet);
-+ reset_recovery_prepare();
-+ loop_end = true;
-+ }
-+ }
-+ if (userName != NULL)
-+ free(userName);
-+
-+
-+ return loop_end;
-+}
-+
-+static bool
-+second_setup_recovery (RecoveryPacket * packet)
-+{
-+ char * func = "second_setup_recovery()";
-+ HostTbl * master = (HostTbl *)NULL;
-+ int status;
-+ bool loop_end = false;
-+ char * userName = NULL;
-+
-+ start_recovery();
-+
-+ /* send vauum command to master server */
-+ while ((master = PGRget_master()) != NULL)
-+ {
-+ userName = strdup(packet->userName);
-+ status = send_vacuum(master, userName, PGR_RECOVERY_2ND_STAGE
);
-+ if (status != STATUS_OK)
-+ {
-+ PGRset_host_status(master, DB_TBL_ERROR);
-+ if (userName != NULL)
-+ {
-+ free(userName);
-+ userName = NULL;
-+ }
-+ continue;
-+ }
-+ break;
-+ }
-+
-+ if (master == NULL)
-+ {
-+ show_error("%s:vacuum error , master may be down",func);
-+ PGRset_recovery_packet_no(packet, RECOVERY_ERROR_TARGET_ONLY);
-+ status = send_packet(&Target,packet);
-+ status = send_packet(&Master,packet);
-+ reset_recovery_prepare();
-+
-+ return true;
-+ }
-+
-+ /*
-+ * wait until all started transactions are going to finish
-+ */
-+ status = PGRwait_transaction_count_clear(master);
-+ if (status != STATUS_OK && PGRget_recovery_status() == RECOVERY_START)
-+ {
-+ show_error("%s:transaction is too busy, please try again
after",func);
-+ PGRset_recovery_packet_no(packet, RECOVERY_ERROR_TARGET_ONLY);
-+ status = send_packet(&Target,packet);
-+ status = send_packet(&Master,packet);
-+ reset_recovery_prepare();
-+ return true;
-+ }
-+
-+ if (PGRget_recovery_status() != RECOVERY_START) {
-+ show_error("%s:queue set failed. stop to recovery",func);
-+ PGRset_recovery_packet_no(packet, RECOVERY_ERROR_CONNECTION);
-+ status = send_packet(&Target,packet);
-+ status = send_packet(&Master,packet);
-+ reset_recovery_prepare();
-+ if (userName != NULL)
-+ free(userName);
-+ return true;
-+ }
-+
-+ /*
-+ * then, send fsync request to master DB
-+ */
-+ PGRset_recovery_packet_no(packet, RECOVERY_FSYNC_REQ );
-+ status = send_packet(&Master,packet);
-+ if (status != STATUS_OK)
-+ {
-+ /*
-+ * connection error , master may be down
-+ */
-+ show_error("%s:connection error , master may be down",func);
-+ PGRset_recovery_packet_no(packet, RECOVERY_ERROR_CONNECTION);
-+ status = send_packet(&Target,packet);
-+ status = send_packet(&Master,packet);
-+ reset_recovery_prepare();
-+ if (userName != NULL)
-+ free(userName);
-+ return true;
-+ }
-+
-+ if (PGRget_recovery_status() != RECOVERY_START) {
-+ show_error("%s:queue set failed. stop to recovery",func);
-+ PGRset_recovery_packet_no(packet, RECOVERY_ERROR_CONNECTION);
-+ status = send_packet(&Target,packet);
-+ status = send_packet(&Master,packet);
-+ reset_recovery_prepare();
-+ if (userName != NULL)
-+ free(userName);
-+ return true;
-+ }
-+
-+ /*
-+ * wait answer from master server
-+ */
-+ memset(packet,0,sizeof(RecoveryPacket));
-+ read_packet_from_master(&Master,packet);
-+ if (ntohs(packet->packet_no) == RECOVERY_FSYNC_ANS )
-+ {
-+ /*
-+ * master DB finished fsync
-+ */
-+ PGRset_recovery_packet_no(packet, RECOVERY_START_ANS );
-+
memcpy(packet->hostName,Master.hostName,sizeof(packet->hostName));
-+ status = send_packet(&Target,packet);
-+ if (status != STATUS_OK)
-+ {
-+ finish_recovery();
-+ }
-+ loop_end = true;
-+ }
-+ else
-+ {
-+ show_error("%s:failure answer returned",func);
-+ PGRset_recovery_packet_no(packet, RECOVERY_ERROR_CONNECTION);
-+ status = send_packet(&Target,packet);
-+ status = send_packet(&Master,packet);
-+ reset_recovery_prepare();
-+ loop_end = true;
-+ }
-+ if (userName != NULL)
-+ free(userName);
-+ return loop_end;
-+}
-+/**
-+ * send queries from queue.
-+ *
-+ * return
-+ * STATUS_OK - success both
-+ * STATUS_ERROR - fail both
-+ */
-+static int
-+PGRsend_queue(RecoveryTbl * master, RecoveryTbl * target)
-+{
-+ char * func = "PGRsend_queue()";
-+ HostTbl * master_ptr = NULL;
-+ HostTbl * target_ptr = NULL;
-+ RecoveryQueueHeader * msg_header = NULL;
-+ RecoveryQueueQuery * msg_query = NULL;
-+ ReplicateHeader * header = NULL;
-+ char * query = NULL;
-+ int size = 0;
-+ int rcv_header_size = 0;
-+ long mtype = 0;
-+ int status = 0;
-+ int query_size = 0;
-+ int rtn=0;
-+ if (master == (RecoveryTbl *)NULL)
-+ {
-+ show_error("%s:there is no master ",func);
-+ return STATUS_ERROR;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:master %s - %d",func,master->hostName,master->port);
-+#endif
-+ master_ptr = PGRget_HostTbl(master->hostName,master->port);
-+ if (master_ptr == (HostTbl *)NULL)
-+ {
-+ show_error("%s:master table is null",func);
-+ return STATUS_ERROR;
-+ }
-+ if (target != (RecoveryTbl *)NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:target %s -
%d",func,target->hostName,target->port);
-+#endif
-+ target_ptr = PGRget_HostTbl(target->hostName,target->port);
-+ if (target_ptr == (HostTbl *)NULL)
-+ {
-+ show_error("%s:target table is null",func);
-+ return STATUS_ERROR;
-+ }
-+ }
-+
-+ size = sizeof(RecoveryQueueHeader) + sizeof(ReplicateHeader);
-+ msg_header = (RecoveryQueueHeader *)malloc(size+4);
-+ if (msg_header == NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:malloc() failed. reason: %s",func,
strerror(errno));
-+#endif
-+ return STATUS_ERROR;
-+ }
-+ memset(msg_header,0,size+4);
-+ rcv_header_size = sizeof(long)+sizeof(ReplicateHeader);
-+ status = STATUS_OK;
-+ while (msgrcv(*RecoveryMsgid , msg_header, rcv_header_size,
RECOVERY_HEADER_MTYPE, IPC_NOWAIT) > 0 )
-+ {
-+ header = (ReplicateHeader *)(msg_header->mdata);
-+ query_size = ntohl(header->query_size);
-+ if (query_size < 0)
-+ {
-+ if (msg_query != NULL)
-+ {
-+ free(msg_query);
-+ msg_query = NULL;
-+ }
-+ break;
-+ }
-+ size = sizeof(RecoveryQueueQuery) + query_size;
-+ mtype = msg_header->query_mtype;
-+ msg_query = (RecoveryQueueQuery *) malloc(size+4);
-+ if (msg_query == NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:malloc() failed. reason: %s",func,
strerror(errno));
-+#endif
-+ free(msg_header);
-+ msg_header = NULL;
-+ return STATUS_ERROR;
-+ }
-+ memset(msg_query,0,size+4);
-+ if (msgrcv(*RecoveryMsgid , msg_query, sizeof(unsigned
int)+query_size, mtype, IPC_NOWAIT) < 0)
-+ {
-+ show_error("%s:msgrcv() failed.
(%s)",func,strerror(errno) );
-+ status = STATUS_ERROR;
-+ if (msg_query != NULL)
-+ {
-+ free(msg_query);
-+ msg_query = NULL;
-+ }
-+ break;
-+ }
-+ query = (char *)(msg_query->mdata);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:put query from queue :%s",func,query);
-+#endif
-+
rtn=PGRsend_replicate_packet_to_server(master_ptr,header,query,PGR_Result,msg_query->replicationId,
true);
-+ if (rtn == STATUS_ERROR || rtn == STATUS_DEADLOCK_DETECT )
-+ {
-+ show_error("%s:PGRsend_replicate_packet_to_server to
master error",func);
-+ status = STATUS_ERROR ;
-+ if (msg_query != NULL)
-+ {
-+ free(msg_query);
-+ msg_query = NULL;
-+ }
-+ break;
-+ }
-+ if (target_ptr != NULL)
-+ {
-+
rtn=PGRsend_replicate_packet_to_server(target_ptr,header,query,PGR_Result,msg_query->replicationId,
true);
-+ if (rtn == STATUS_ERROR || rtn ==
STATUS_DEADLOCK_DETECT )
-+ {
-+
show_error("%s:PGRsend_replicate_packet_to_server to target error",func);
-+ status = STATUS_ERROR;
-+ if (msg_query != NULL)
-+ {
-+ free(msg_query);
-+ msg_query = NULL;
-+ }
-+ break;
-+ }
-+ }
-+ if (msg_query != NULL)
-+ {
-+ free(msg_query);
-+ msg_query = NULL;
-+ }
-+ }
-+ if (msg_header != NULL)
-+ {
-+ free(msg_header);
-+ msg_header = NULL;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:send_queue return status %d",func,status);
-+#endif
-+ return status;
-+}
-+
-+static void
-+pgrecovery_loop(int fd)
-+{
-+ char * func = "pgrecovery_loop()";
-+ int count;
-+ int sock;
-+ int status;
-+ bool loop_end = false;
-+ RecoveryPacket packet;
-+ HostTbl new_host;
-+ RecoveryTbl * lbp;
-+
-+ lbp = LoadBalanceTbl;
-+ if (lbp == (RecoveryTbl *)NULL)
-+ {
-+ show_error("%s:recovery table is NULL",func);
-+ return ;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:recovery accept port %d",func, Recovery_Port_Number);
-+#endif
-+ count = 0;
-+ while ((status =
PGR_Create_Acception(fd,&sock,"",Recovery_Port_Number)) != STATUS_OK)
-+ {
-+ show_error("%s:PGR_Create_Acception failed",func);
-+ PGR_Close_Sock(&sock);
-+ sock = -1;
-+ if ( count > PGR_CONNECT_RETRY_TIME)
-+ {
-+ return;
-+ }
-+ count ++;
-+ }
-+ if(sock==-1) {
-+ show_error("can't create recovery socket.exit.");
-+ PGRreplicate_exit(1);
-+ }
-+ for(;;)
-+ {
-+ int read_size = 0;
-+ int rtn;
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = RECOVERY_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(sock,&rmask);
-+ /*
-+ * read packet from target cluster server
-+ */
-+ rtn = select(sock+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+
-+ if (rtn == 0) /* timeout */
-+ {
-+ return;
-+ }
-+
-+ if (rtn && FD_ISSET(sock, &rmask))
-+ {
-+ read_size = read_packet(sock, &packet);
-+ }
-+ else
-+ {
-+ continue;
-+ }
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:receive packet
no:%d",func,ntohs(packet.packet_no));
-+#endif
-+
-+ switch (ntohs(packet.packet_no))
-+ {
-+ case RECOVERY_PREPARE_REQ :
-+ /*
-+ * start prepare of recovery
-+ */
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:1st master %s - %d",
-+ func,Master.hostName,Master.port);
-+ show_debug("%s:1st target %s - %d",
-+ func,Target.hostName,Target.port);
-+#endif
-+
-+ loop_end = first_setup_recovery(&sock,
&packet);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:first_setup_recovery end:%d
",func,loop_end);
-+#endif
-+ break;
-+ case RECOVERY_START_REQ :
-+ /*
-+ * now, recovery process will start
-+ * stop the transaction count up
-+ * start queueing and stop send all
queries for master DB
-+ */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:2nd master %s - %d",
-+ func, Master.hostName,Master.port);
-+ show_debug("%s:2nd target %s - %d",
-+ func, Target.hostName,Target.port);
-+#endif
-+ loop_end = second_setup_recovery (&packet);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:second_setup_recovery end :%d
",
-+ func,loop_end);
-+#endif
-+ break;
-+ case RECOVERY_FINISH :
-+ /*
-+ * finished rsync DB datas from master to
target
-+ */
-+ /*
-+ * send all queries in queue
-+ */
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:last master %s - %d",
-+ func, Master.hostName,Master.port);
-+ show_debug("%s:last target %s - %d",
-+ func, Target.hostName,Target.port);
-+#endif
-+ status = PGRsend_queue(&Master,&Target);
-+ if (status == STATUS_OK)
-+ {
-+
memcpy(new_host.hostName,Target.hostName,sizeof(new_host.hostName));
-+ new_host.port = Target.port;
-+ new_host.recoveryPort =
Target.recoveryPort;
-+
PGRset_recovered_host(&new_host,DB_TBL_USE);
-+ PGRadd_HostTbl(&new_host,DB_TBL_USE);
-+ }
-+ else
-+ {
-+ /* connection error , master or
target may be down */
-+ show_error("%s:PGRsend_queue
failed",func);
-+ PGRset_recovery_packet_no(&packet,
RECOVERY_ERROR_CONNECTION);
-+ status = send_packet(&Target,&packet);
-+ }
-+ /*
-+ * stop queueing, and re-initialize recovery
status
-+ */
-+ finish_recovery();
-+ loop_end = true;
-+ /*
-+ * send finish recovery to load balancer
-+ */
-+ if (Master.recovery_sock != -1)
-+ {
-+ close(Master.recovery_sock);
-+ Master.recovery_sock = -1;
-+ }
-+ if (Target.recovery_sock != -1)
-+ {
-+ close(Target.recovery_sock);
-+ Target.recovery_sock = -1;
-+ }
-+ send_packet(&Master, &packet);
-+ MasterPacketData.packet_no = packet.packet_no;
-+
PGRsend_load_balance_packet(&MasterPacketData);
-+ PGRsend_load_balance_packet(&packet);
-+ memset((char
*)&MasterPacketData,0,sizeof(RecoveryPacket));
-+ break;
-+ case RECOVERY_ERROR_ANS :
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:recovery error accept. top
queueing and initiarse recovery status",func);
-+#endif
-+ status = PGRsend_queue(&Master,NULL);
-+ memset(&packet,0,sizeof(RecoveryPacket));
-+ PGRset_recovery_packet_no(&packet,
RECOVERY_ERROR_ANS);
-+ send_packet(&Master, &packet);
-+ finish_recovery();
-+ loop_end = true;
-+ PGRset_recovery_packet_no(&MasterPacketData,
RECOVERY_FINISH );
-+
PGRsend_load_balance_packet(&MasterPacketData);
-+ memset((char
*)&MasterPacketData,0,sizeof(RecoveryPacket));
-+ break;
-+ default:
-+ show_error("%s:unknown packet. abort to parse");
-+ loop_end=true;
-+ break;
-+ }
-+ if (loop_end)
-+ {
-+ if (Master.sock != -1)
-+ {
-+ close (Master.sock);
-+ }
-+ if (Master.recovery_sock != -1)
-+ {
-+ close (Master.recovery_sock);
-+ }
-+ PGR_Close_Sock(&sock);
-+ return;
-+ }
-+ }
-+}
-+
-+void
-+PGRrecovery_main(void)
-+{
-+ char * func = "PGRrecovery_main()";
-+ int status;
-+ int fd = -1;
-+ int rtn;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PGRrecovery_main bind port
%d",func,Recovery_Port_Number);
-+#endif
-+ status = PGR_Create_Socket_Bind(&fd, "", Recovery_Port_Number);
-+ if (status != STATUS_OK)
-+ {
-+ show_error("%s:PGR_Create_Socket_Bind failed",func);
-+ exit(1);
-+ }
-+ memset(&MasterPacketData,0,sizeof(RecoveryPacket));
-+ memset(&Master,0,sizeof(RecoveryTbl));
-+ memset(&Target,0,sizeof(RecoveryTbl));
-+ for (;;)
-+ {
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = RECOVERY_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(fd,&rmask);
-+ rtn = select(fd+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+ if (rtn && FD_ISSET(fd, &rmask))
-+ {
-+ pgrecovery_loop(fd);
-+ }
-+ }
-+}
-+
-+#ifdef PRINT_DEBUG
-+static void
-+show_recovery_packet(RecoveryPacket * packet)
-+{
-+ show_debug("no = %d",ntohs(packet->packet_no));
-+ show_debug("max_connect = %d",ntohs(packet->max_connect));
-+ show_debug("port = %d",ntohs(packet->port));
-+ show_debug("recoveryPort = %d",ntohs(packet->recoveryPort));
-+ if (packet->hostName != NULL)
-+ show_debug("hostName = %s",packet->hostName);
-+ if (packet->pg_data != NULL)
-+ show_debug("pg_data = %s",packet->pg_data);
-+}
-+#endif
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/replicate.c
pgcluster-1.5.0rc7/src/pgcluster/pgrp/replicate.c
---- postgresql-8.1.2/src/pgcluster/pgrp/replicate.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/replicate.c 2006-01-31
23:38:17.000000000 +0100
-@@ -0,0 +1,3938 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * replicate.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at pgreplicate for the replication.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#include "postgres.h"
-+#include "postgres_fe.h"
-+
-+#include <pthread.h>
-+#include <stdio.h>
-+#include <stdarg.h>
-+#include <sys/types.h>
-+#include <fcntl.h>
-+#include <errno.h>
-+#include <ctype.h>
-+#include <time.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <sys/sem.h>
-+#include <sys/msg.h>
-+#include <signal.h>
-+
-+
-+#include "libpq-fe.h"
-+#include "libpq-int.h"
-+#include "fe-auth.h"
-+
-+#include <sys/socket.h>
-+#include <unistd.h>
-+#include <netdb.h>
-+#include <arpa/inet.h>
-+
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+
-+#ifdef HAVE_SYS_SELECT_H
-+#include <sys/select.h>
-+#endif
-+
-+
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+
-+#ifdef MULTIBYTE
-+#include "mb/pg_wchar.h"
-+#endif
-+
-+#include "access/xact.h"
-+#include "lib/dllist.h"
-+#include "libpq/pqformat.h"
-+#include "replicate_com.h"
-+#include "pgreplicate.h"
-+
-+
-+#define IPC_NMAXSEM (32)
-+
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+static PGconn * pgr_createConn( char * host, char * port,char * database,
char * userName );
-+static TransactionTbl * setTransactionTbl(HostTbl * host_ptr,
ReplicateHeader * header);
-+static TransactionTbl * insertTransactionTbl( HostTbl * host_ptr,
TransactionTbl * datap);
-+static TransactionTbl * getTransactionTbl( HostTbl * host_ptr,
ReplicateHeader * header);
-+static void deleteTransactionTbl(HostTbl * host_ptr,ReplicateHeader *
header);
-+
-+static HostTbl * deleteHostTbl(HostTbl * ptr);
-+static bool is_master_in_recovery(char * host, int port,int
recovery_status);
-+static void sem_quit(int semid);
-+static int send_cluster_status_to_load_balance(HostTbl * host_ptr,int
status);
-+static void set_transaction_status(int status);
-+static void check_transaction_status(ReplicateHeader * header,HostTbl
*host, TransactionTbl *transaction);
-+static void clearHostTbl(void);
-+static bool is_need_sync_time(ReplicateHeader * header);
-+static bool is_need_wait_answer(ReplicateHeader * header);
-+static void write_host_status_file(HostTbl * host_ptr);
-+
-+static void delete_template(HostTbl * ptr, ReplicateHeader * header);
-+static char * check_copy_command(char * query);
-+static int read_answer(int dest);
-+static bool is_autocommit_off(char * query);
-+static bool is_autocommit_on(char * query);
-+static unsigned int get_host_ip_from_tbl(char * host);
-+static unsigned int get_srcHost_ip_from_tbl(char * srcHost);
-+
-+static int next_replication_id(void);
-+static void check_replication_id(void);
-+static bool is_need_use_rlog(ReplicateHeader * header);
-+static bool is_need_queue_jump( ReplicateHeader * header,char * query);
-+static int check_delete_transaction (HostTbl * host_ptr, ReplicateHeader *
header);
-+
-+static bool is_executed_query_in_origin( ReplicateHeader *header );
-+static bool is_executed_query( PGconn *conn,ReplicateHeader *header );
-+
-+static void * thread_send_source(void * arg);
-+static void * thread_send_cluster(void * arg);
-+
-+static int send_replicate_packet_to_server( TransactionTbl *
transaction_tbl, int current_cluster, HostTbl * host_ptr, ReplicateHeader *
header, char *query , char * result,unsigned int replicationId, bool
recovery);
-+
-+static int send_func(HostTbl * host_ptr,ReplicateHeader * header, char *
func,char * result);
-+static uint32_t get_oid(HostTbl * host_ptr,ReplicateHeader * header);
-+static int set_oid(HostTbl * host_ptr,ReplicateHeader * header, uint32_t
oid);
-+static int replicate_lo( PGconn * conn, ReplicateHeader * header, LOArgs *
query);
-+static int notice_abort(HostTbl * host_ptr,ReplicateHeader * header);
-+static int send_p_parse (PGconn * conn, StringInfo input_message);
-+static int send_p_bind (PGconn * conn, StringInfo input_message);
-+static int send_p_describe (PGconn * conn, StringInfo input_message);
-+static int send_p_execute (PGconn * conn, StringInfo input_message);
-+static int send_p_sync (PGconn * conn, StringInfo input_message);
-+static int send_p_close (PGconn * conn, StringInfo input_message);
-+static void set_string_info(StringInfo input_message, ReplicateHeader *
header, char * query);
-+
-+int replicate_packet_send_internal(ReplicateHeader * header, char *
query,int dest,int recovery_status,bool isHeldLock);
-+bool PGRis_same_host(char * host1, unsigned short port1 , char * host2,
unsigned short port2);
-+HostTbl * PGRadd_HostTbl(HostTbl * conf_data, int useFlag);
-+HostTbl * PGRget_master(void);
-+void PGRset_recovery_status(int status);
-+int PGRget_recovery_status(void);
-+int PGRcheck_recovered_host(void);
-+int PGRset_recovered_host(HostTbl * target,int useFlag);
-+int PGRinit_recovery(void);
-+void PGRreplicate_exit(int exit_status);
-+int PGRsend_replicate_packet_to_server( HostTbl * host_ptr, ReplicateHeader
* header, char *query , char * result,unsigned int replicationId, bool
recovery);
-+HostTbl * PGRget_HostTbl(char * hostName,int port);
-+int PGRset_queue(ReplicateHeader * header,char * query);
-+int PGRset_host_status(HostTbl * host_ptr,int status);
-+void PGRclear_transactions(void);
-+void PGRclear_connections();
-+int PGRset_replication_id(uint32_t id);
-+int PGRdo_replicate(int sock,ReplicateHeader *header, char * query);
-+int PGRreturn_result(int dest, char * result,int wait);
-+int PGRreplicate_packet_send( ReplicateHeader * header, char * query,int
dest,int recovery_status);
-+char * PGRread_packet(int sock, ReplicateHeader *header);
-+//void PGRnotice_replication_server(char * hostName, unsigned short
portNumber,unsigned short recoveryPortNumber, unsigned short
lifecheckPortNumber, char * userName);
-+char * PGRread_query(int sock, ReplicateHeader *header);
-+int PGRwait_transaction_count_clear(HostTbl *host);
-+
-+unsigned int PGRget_next_query_id(void);
-+int PGRinit_transaction_table(void);
-+int PGRsync_oid(ReplicateHeader *header);
-+int PGRload_replication_id(void);
-+
-+extern pthread_mutex_t transaction_table_mutex;
-+
-+static int exit_signo = SIGTERM;
-+
-+bool
-+PGRis_same_host(char * host1, unsigned short port1 , char * host2, unsigned
short port2)
-+{
-+#ifdef PRINT_DEBUG
-+ char * func = "PGRis_same_host()";
-+#endif
-+ unsigned int ip1, ip2;
-+
-+ if ((host1[0] == '\0' ) || (host2[0] == '\0') ||
-+ ( port1 != port2 ))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:not same host",func);
-+#endif
-+ return false;
-+ }
-+ ip1 = PGRget_ip_by_name( host1);
-+ ip2 = PGRget_ip_by_name( host2);
-+
-+ if ((ip1 == ip2) && (port1 == port2))
-+ {
-+ return true;
-+ }
-+ return false;
-+}
-+
-+static PGconn *
-+pgr_createConn( char * host, char * port,char * database, char * userName )
-+{
-+ char * func = "pgr_createConn()";
-+ int cnt = 0;
-+ PGconn * conn = NULL;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PQsetdbLogin host[%s] port[%s] db[%s] user[%s]",
-+ func, host,port,database,userName);
-+#endif
-+ conn = PQsetdbLogin(host, port, NULL, NULL, database, userName, NULL);
-+ /* check to see that the backend Connection was successfully made */
-+ cnt = 0;
-+ while (PQstatus(conn) == CONNECTION_BAD)
-+ {
-+ if (conn != NULL)
-+ {
-+ PQfinish(conn);
-+ conn = NULL;
-+ }
-+ conn = PQsetdbLogin(host, port, NULL, NULL, database,
userName, NULL);
-+ if (cnt > PGR_CONNECT_RETRY_TIME )
-+ {
-+ if (conn != NULL)
-+ {
-+ PQfinish(conn);
-+ conn = NULL;
-+ }
-+ return (PGconn *)NULL;
-+ }
-+
-+ if(PQstatus(conn) == CONNECTION_BAD && h_errno==2)
-+ {
-+ sleep(3);
-+ show_debug("gethostbyname() failed. sleep and
retrying...");
-+ }
-+ else if(!strncasecmp(PQerrorMessage(conn),"FATAL: Sorry, too
many clients already",30) ||
-+ !strncasecmp(PQerrorMessage(conn),"FATAL:
Non-superuser connection limit",30) )
-+ {
-+ sleep(3) ;
-+ show_debug("Connection overflow. sleep and retrying...");
-+ }
-+ else if(!strncasecmp(PQerrorMessage(conn),"FATAL: The
database system is starting up",40) )
-+ {
-+ show_debug("waiting for starting up...");
-+ sleep(3) ;
-+ }
-+ else
-+ {
-+ show_debug("%s:Retry. h_errno is %d,reason is
'%s'",func,h_errno,PQerrorMessage(conn));
-+ sleep(3) ;
-+ cnt ++;
-+ }
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PQsetdbLogin ok!!",func);
-+#endif
-+ return conn;
-+}
-+
-+static TransactionTbl *
-+setTransactionTbl(HostTbl * host_ptr, ReplicateHeader * header)
-+{
-+ char * func = "setTransactionTbl()";
-+ TransactionTbl * ptr = NULL;
-+ TransactionTbl work ;
-+ char port[8];
-+ char * hostName, *dbName, *userName;
-+
-+ if ((host_ptr == NULL) || (header == NULL))
-+ {
-+ return (TransactionTbl *)NULL;
-+ }
-+ dbName = (char *)header->dbName;
-+ snprintf(port,sizeof(port),"%d", host_ptr->port);
-+ userName = (char *)header->userName;
-+ hostName = (char *)host_ptr->resolvedName;
-+
-+ ptr = getTransactionTbl(host_ptr,header);
-+ if (ptr != NULL)
-+ {
-+ ptr->transaction_count = 0;
-+ ptr->conn = pgr_createConn(hostName,port,dbName,userName);
-+ if (ptr->conn == NULL)
-+ {
-+ show_error("%s:Transaction is pooling but
pgr_createConn failed",func);
-+ deleteTransactionTbl(host_ptr, header);
-+ PGRset_host_status(host_ptr,DB_TBL_ERROR);
-+ ptr = NULL;
-+ }
-+ return ptr;
-+ }
-+
-+ memset(&work,0,sizeof(work));
-+ strncpy(work.host, hostName, sizeof(work.host));
-+ strncpy(work.srcHost, header->from_host, sizeof(work.srcHost));
-+ work.hostIP = PGRget_ip_by_name(hostName);
-+ work.port = host_ptr->port;
-+ work.srcHostIP = PGRget_ip_by_name(header->from_host);
-+ work.pid = ntohs(header->pid);
-+ strncpy(work.dbName,header->dbName,sizeof(work.dbName));
-+ work.conn = pgr_createConn(hostName,port,dbName,userName);
-+ if (work.conn == NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: %s@%s is not ready",func,port,hostName);
-+#endif
-+ return (TransactionTbl *)NULL;
-+ }
-+ work.useFlag = DB_TBL_USE ;
-+ work.in_transaction = false;
-+ work.transaction_count = 0;
-+ ptr = insertTransactionTbl(host_ptr,&work);
-+ if (ptr == (TransactionTbl *)NULL)
-+ {
-+ show_error("%s:insertTransactionTbl failed",func);
-+ return (TransactionTbl *)NULL;
-+ }
-+ return ptr;
-+}
-+
-+static TransactionTbl *
-+insertTransactionTbl( HostTbl * host_ptr, TransactionTbl * datap)
-+{
-+ char * func = "insertTransactionTbl()";
-+ TransactionTbl * workp = NULL;
-+
-+ pthread_mutex_lock(&transaction_table_mutex);
-+ if ((host_ptr == (HostTbl *)NULL) || (datap == (TransactionTbl*)NULL))
-+ {
-+ show_error("%s:host table or transaction table is NULL",func);
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+
-+ return (TransactionTbl *)NULL;
-+ }
-+ if (Transaction_Tbl_Begin == NULL)
-+ {
-+ if (PGRinit_transaction_table() != STATUS_OK)
-+ {
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+
-+ return (TransactionTbl *)NULL;
-+ }
-+ }
-+
-+ workp = (TransactionTbl *)malloc(sizeof(TransactionTbl));
-+ memset(workp,0,sizeof(TransactionTbl));
-+ Transaction_Tbl_End = workp;
-+ workp->hostIP = datap->hostIP;
-+ workp->port = datap->port;
-+ workp->pid = datap->pid;
-+ workp->srcHostIP = datap->srcHostIP;
-+ strncpy(workp->host,datap->host,sizeof(workp->host));
-+ strncpy(workp->srcHost,datap->srcHost,sizeof(workp->srcHost));
-+ strncpy(workp->dbName,datap->dbName,sizeof(workp->dbName));
-+ workp->conn = datap->conn;
-+ workp->useFlag = DB_TBL_USE;
-+ workp->lock = STATUS_OK;
-+ workp->in_transaction =datap->in_transaction;
-+ workp->transaction_count =datap->transaction_count;
-+ DLAddTail(Transaction_Tbl_Begin, DLNewElem(workp));
-+
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+
-+ return workp;
-+}
-+
-+static TransactionTbl *
-+getTransactionTbl( HostTbl * host_ptr, ReplicateHeader * header)
-+{
-+ Dlelem * ptr = NULL;
-+ unsigned int host_ip,srcHost_ip;
-+ unsigned short pid = 0;
-+
-+ if (Transaction_Tbl_Begin == (Dllist *) NULL)
-+ {
-+ return (TransactionTbl * )NULL;
-+ }
-+ if ((host_ptr == (HostTbl *)NULL) ||
-+ (header == (ReplicateHeader *)NULL))
-+ {
-+ return (TransactionTbl * )NULL;
-+ }
-+ host_ip = get_host_ip_from_tbl(host_ptr->resolvedName);
-+ if (host_ip == 0)
-+ {
-+ host_ip = PGRget_ip_by_name(host_ptr->resolvedName);
-+ }
-+ srcHost_ip = get_srcHost_ip_from_tbl(header->from_host);
-+ if (srcHost_ip == 0)
-+ {
-+ srcHost_ip = PGRget_ip_by_name(header->from_host);
-+ }
-+ pid = ntohs(header->pid);
-+
-+ pthread_mutex_lock(&transaction_table_mutex);
-+
-+ ptr = DLGetHead(Transaction_Tbl_Begin);
-+ while (ptr)
-+ {
-+ TransactionTbl *transaction = DLE_VAL(ptr);
-+ if ((transaction->useFlag == DB_TBL_USE) &&
-+ (transaction->hostIP == host_ip) &&
-+ (transaction->port == host_ptr->port) &&
-+ (transaction->srcHostIP == srcHost_ip) &&
-+
(!strncmp(transaction->dbName,header->dbName,sizeof(transaction->dbName))) &&
-+ (transaction->pid == pid))
-+ {
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+ return transaction;
-+ }
-+ ptr = DLGetSucc(ptr);
-+ }
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+
-+ return (TransactionTbl * )NULL;
-+}
-+
-+static void
-+deleteTransactionTbl(HostTbl * host_ptr,ReplicateHeader * header)
-+{
-+ char * func = "deleteTransactionTbl()";
-+ TransactionTbl *ptr = NULL;
-+ Dlelem *elem;
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:",func);
-+#endif
-+
-+ ptr = getTransactionTbl(host_ptr,header);
-+
-+ pthread_mutex_lock(&transaction_table_mutex);
-+
-+ if (ptr != NULL)
-+ {
-+ /*
-+ if ( ptr->transaction_count > 0 )
-+ {
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+ return;
-+ }
-+ */
-+ if (ptr->in_transaction)
-+ {
-+ host_ptr->transaction_count--;
-+ }
-+
-+ if (ptr->conn != NULL)
-+ {
-+ PQfinish(ptr->conn);
-+ }
-+ elem = DLGetHead(Transaction_Tbl_Begin);
-+ while (elem)
-+ {
-+ TransactionTbl *transaction = DLE_VAL(elem);
-+ if (transaction == ptr) {
-+ DLRemove(elem);
-+ DLFreeElem(elem);
-+ free(ptr);
-+
pthread_mutex_unlock(&transaction_table_mutex);
-+ return;
-+ }
-+ elem = DLGetSucc(elem);
-+ }
-+ }
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+}
-+
-+static HostTbl *
-+deleteHostTbl(HostTbl * ptr)
-+{
-+ if (ptr != (HostTbl*)NULL)
-+ {
-+ memset(ptr,0,sizeof(HostTbl));
-+ }
-+ return ++ptr;
-+}
-+
-+HostTbl *
-+PGRadd_HostTbl(HostTbl *conf_data, int useFlag)
-+{
-+ HostTbl * ptr = NULL;
-+ int cnt = 0;
-+
-+ ptr = PGRget_HostTbl(conf_data->hostName, conf_data->port);
-+ if (ptr != (HostTbl*)NULL)
-+ {
-+ PGRset_host_status(ptr,useFlag);
-+ return ptr;
-+ }
-+
-+ ptr = Host_Tbl_Begin;
-+ cnt = 1;
-+ while (ptr->useFlag != DB_TBL_END)
-+ {
-+ if (ptr->useFlag == DB_TBL_FREE)
-+ {
-+ break;
-+ }
-+ ptr ++;
-+ cnt ++;
-+ }
-+ if (cnt >= MAX_DB_SERVER)
-+ {
-+ return (HostTbl*)NULL;
-+ }
-+ if (ptr->useFlag == DB_TBL_END)
-+ {
-+ (ptr + 1) -> useFlag = DB_TBL_END;
-+ }
-+ memset(ptr,0,sizeof(HostTbl));
-+ ptr->hostNum = cnt;
-+ memcpy(ptr->hostName,conf_data->hostName,sizeof(ptr->hostName));
-+
memcpy(ptr->resolvedName,conf_data->resolvedName,sizeof(ptr->resolvedName));
-+ ptr->port = conf_data->port;
-+ ptr->recoveryPort = conf_data->recoveryPort;
-+ ptr->transaction_count = 0;
-+ PGRset_host_status(ptr,useFlag);
-+
-+ return ptr;
-+}
-+
-+HostTbl *
-+PGRget_master(void)
-+{
-+ HostTbl * host_tbl = NULL;
-+
-+ host_tbl = Host_Tbl_Begin;
-+ while(host_tbl->useFlag != DB_TBL_END)
-+ {
-+ if (host_tbl->useFlag == DB_TBL_USE)
-+ {
-+ return host_tbl;
-+ }
-+ host_tbl ++;
-+ }
-+ return (HostTbl *)NULL;
-+}
-+
-+void
-+PGRset_recovery_status(int status)
-+{
-+ if (RecoverySemID <= 0)
-+ return;
-+ PGRsem_lock(RecoverySemID,SEM_NUM_OF_RECOVERY);
-+ if (Recovery_Status_Inf != (RecoveryStatusInf *)NULL)
-+ {
-+ Recovery_Status_Inf->recovery_status = status;
-+
-+ }
-+ PGRsem_unlock(RecoverySemID,SEM_NUM_OF_RECOVERY);
-+}
-+
-+int
-+PGRget_recovery_status(void)
-+{
-+ int status = -1;
-+
-+ if (RecoverySemID <= 0)
-+ return -1;
-+ PGRsem_lock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ if (Recovery_Status_Inf != (RecoveryStatusInf *)NULL)
-+ {
-+ status = Recovery_Status_Inf->recovery_status;
-+ }
-+ PGRsem_unlock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ return status;
-+
-+}
-+
-+static void
-+set_transaction_status(int status)
-+{
-+ if (RecoverySemID <= 0)
-+ return ;
-+ PGRsem_lock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ if (Recovery_Status_Inf != (RecoveryStatusInf *)NULL)
-+ {
-+ Recovery_Status_Inf->recovery_status = status;
-+ }
-+ PGRsem_unlock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+}
-+
-+#if 0
-+static int
-+get_transaction_status(void)
-+{
-+ int status = 0;
-+
-+ if (RecoverySemID <= 0)
-+ return 0;
-+ PGRsem_lock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ if (Recovery_Status_Inf != (RecoveryStatusInf *)NULL)
-+ {
-+ status = Recovery_Status_Inf->recovery_status;
-+ PGRsem_unlock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ return status;
-+ }
-+ PGRsem_unlock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ return 0;
-+}
-+#endif
-+
-+int
-+PGRwait_transaction_count_clear(HostTbl *host)
-+{
-+ int cnt = 0;
-+ int transaction=-1;
-+
-+ for(cnt=0 ;
-+ cnt < PGR_RECOVERY_RETRY_CNT && transaction!=0;
-+ cnt++)
-+ {
-+ PGRsem_lock(SemID, 1);
-+ transaction = host->transaction_count;
-+ PGRsem_unlock(SemID, 1);
-+ usleep(PGR_RECOVERY_WAIT_MSEC);
-+ }
-+ show_debug("transaction count is %d",transaction);
-+ return transaction==0
-+ ? STATUS_OK
-+ : STATUS_ERROR;
-+}
-+
-+int
-+PGRcheck_recovered_host(void)
-+{
-+ char * func = "PGRcheck_recovered_host()";
-+ HostTbl * ptr = NULL;
-+ int rtn = STATUS_OK;
-+
-+ if (RecoverySemID <= 0)
-+ return STATUS_ERROR;
-+ PGRsem_lock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ if (Recovery_Status_Inf != (RecoveryStatusInf *)NULL)
-+ {
-+ if (Recovery_Status_Inf->useFlag != DB_TBL_FREE)
-+ {
-+ ptr = PGRadd_HostTbl((HostTbl
*)&(Recovery_Status_Inf->target_host),Recovery_Status_Inf->useFlag);
-+ if (ptr == (HostTbl *) NULL)
-+ {
-+ show_error("%s:PGRadd_HostTbl failed",func);
-+ rtn = STATUS_ERROR;
-+ }
-+ Recovery_Status_Inf->useFlag = DB_TBL_FREE;
-+ memset((HostTbl
*)&(Recovery_Status_Inf->target_host),0,sizeof(HostTbl));
-+
-+ }
-+ }
-+ PGRsem_unlock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ return rtn;
-+}
-+
-+int
-+PGRset_recovered_host(HostTbl * target, int useFlag)
-+{
-+ if (RecoverySemID <= 0)
-+ return -1;
-+ PGRsem_lock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ if (Recovery_Status_Inf != (RecoveryStatusInf *)NULL)
-+ {
-+ Recovery_Status_Inf->useFlag = useFlag;
-+ if (target != (HostTbl*)NULL)
-+ {
-+ memcpy((HostTbl
*)&(Recovery_Status_Inf->target_host),target,sizeof(HostTbl));
-+ PGRset_host_status(target,useFlag);
-+ }
-+
-+ }
-+ PGRsem_unlock(RecoverySemID, SEM_NUM_OF_RECOVERY);
-+ return 0;
-+}
-+
-+
-+static bool
-+is_master_in_recovery(char * host , int port,int recovery_status)
-+{
-+ HostTbl * master = NULL;
-+
-+ // status = PGRget_recovery_status();
-+ if (recovery_status == RECOVERY_START)
-+ {
-+ master = PGRget_master();
-+ if (master == (HostTbl *)NULL)
-+ {
-+ return false;
-+ }
-+ if
((!strncmp(host,master->hostName,sizeof(master->hostName))) &&
-+ (port == master->port))
-+ {
-+ return true;
-+ }
-+ }
-+ return false;
-+}
-+
-+int
-+PGRinit_recovery(void)
-+{
-+ char * func = "PGRinit_recovery()";
-+ int size = 0;
-+ union semun sem_arg;
-+ int i = 0;
-+
-+ if ((RecoverySemID = semget(IPC_PRIVATE,2,IPC_CREAT | IPC_EXCL |
0600)) < 0)
-+ {
-+ show_error("%s:semget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ for ( i = 0 ; i < 2 ; i ++)
-+ {
-+ semctl(RecoverySemID, i, GETVAL, sem_arg);
-+ sem_arg.val = 1;
-+ semctl(RecoverySemID, i, SETVAL, sem_arg);
-+ }
-+
-+ size = sizeof(RecoveryStatusInf);
-+ RecoveryShmid = shmget(IPC_PRIVATE,size,IPC_CREAT | IPC_EXCL | 0600);
-+ if (RecoveryShmid < 0)
-+ {
-+ show_error("%s:shmget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ Recovery_Status_Inf = (RecoveryStatusInf *)shmat(RecoveryShmid,0,0);
-+ if (Recovery_Status_Inf == (RecoveryStatusInf *)-1)
-+ {
-+ show_error("%s:shmat() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(Recovery_Status_Inf,0,size);
-+ Recovery_Status_Inf->check_point = PGR_CHECK_POINT ;
-+
-+ size = sizeof(unsigned int);
-+ ReplicateSerializationShmid = shmget(IPC_PRIVATE,size,IPC_CREAT |
IPC_EXCL | 0600);
-+ if (ReplicateSerializationShmid < 0)
-+ {
-+ show_error("%s:shmget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+
-+ PGR_ReplicateSerializationID = (unsigned int
*)shmat(ReplicateSerializationShmid,0,0);
-+ if( PGR_ReplicateSerializationID == (unsigned int *)-1) {
-+ show_error("%s:shmat() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(PGR_ReplicateSerializationID,0,size);
-+ PGRset_recovery_status(RECOVERY_INIT);
-+ PGRset_recovered_host((HostTbl *)NULL, DB_TBL_FREE);
-+ set_transaction_status(0);
-+
-+ /*
-+ * create message queue
-+ */
-+ RecoveryMsgShmid = shmget(IPC_PRIVATE,size,IPC_CREAT | IPC_EXCL |
0600);
-+ if (RecoveryMsgShmid < 0)
-+ {
-+ show_error("%s:shmget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+
-+ RecoveryMsgid = (int *)shmat(RecoveryMsgShmid,0,0);
-+ if( RecoveryMsgid < 0) {
-+ show_error("%s:shmat() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ *RecoveryMsgid = msgget (IPC_PRIVATE, 00666 | IPC_CREAT );
-+ if (*RecoveryMsgid < 0)
-+ {
-+ show_error("%s:msgget() failed. (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+
-+
-+ return STATUS_OK;
-+}
-+
-+static void
-+clearHostTbl(void)
-+{
-+
-+ HostTbl * ptr = NULL;
-+
-+ if (Host_Tbl_Begin == NULL)
-+ return;
-+ /* normal socket close */
-+ ptr = Host_Tbl_Begin;
-+ while(ptr && ptr->useFlag != DB_TBL_END)
-+ {
-+ ptr = deleteHostTbl(ptr);
-+ }
-+}
-+
-+void
-+set_exit_processing(int signo)
-+{
-+ exit_signo = signo;
-+ exit_processing = true;
-+ signal(signo, SIG_IGN);
-+}
-+
-+void
-+PGRreplicate_exit(int exit_status)
-+{
-+ char fname[256];
-+ int rtn = 0;
-+
-+ signal(SIGCHLD, SIG_IGN);
-+ kill (0, exit_signo);
-+
-+ child_wait(0);
-+
-+ if (RidFp != NULL)
-+ {
-+ rewind(RidFp);
-+ if (Recovery_Status_Inf != NULL)
-+ {
-+
PGRwrite_log_file(RidFp,"%u",Recovery_Status_Inf->replication_id);
-+ }
-+ fflush(RidFp);
-+ fclose(RidFp);
-+ RidFp = NULL;
-+ }
-+
-+ if (ReplicateSock > 0)
-+ close(ReplicateSock);
-+
-+ /* recovery status clear */
-+ if (RecoverySemID > 0)
-+ Recovery_Status_Inf->recovery_status = RECOVERY_INIT;
-+
-+ /* normal socket close */
-+ clearHostTbl();
-+
-+ if (Host_Tbl_Begin != (HostTbl *)NULL)
-+ {
-+ rtn = shmdt((char *)Host_Tbl_Begin);
-+ shmctl(HostTblShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ }
-+
-+ if (Cascade_Tbl != (ReplicateServerInfo *)NULL)
-+ {
-+ rtn = shmdt((char *)Cascade_Tbl);
-+ shmctl(CascadeTblShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ }
-+
-+ if (Cascade_Inf != (CascadeInf *)NULL)
-+ {
-+ rtn = shmdt((char *)Cascade_Inf);
-+ shmctl(CascadeInfShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ }
-+
-+ if (Commit_Log_Tbl != (CommitLogInf *)NULL)
-+ {
-+ rtn = shmdt((char *)Commit_Log_Tbl);
-+ shmctl(CommitLogShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ }
-+
-+ if (Recovery_Status_Inf != (RecoveryStatusInf *)NULL)
-+ {
-+ rtn = shmdt((char *)Recovery_Status_Inf);
-+ shmctl(RecoveryShmid,IPC_RMID,(struct shmid_ds *)NULL);
-+ }
-+ if (PGR_ReplicateSerializationID!=NULL)
-+ {
-+ shmdt(PGR_ReplicateSerializationID);
-+ shmctl(ReplicateSerializationShmid,IPC_RMID,(struct shmid_ds
*)NULL);
-+ }
-+
-+ if (RecoveryMsgid)
-+ {
-+ if (*RecoveryMsgid >= 0)
-+ msgctl(*RecoveryMsgid,IPC_RMID,(struct msqid_ds
*)NULL);
-+
-+ shmdt(RecoveryMsgid);
-+ shmctl(RecoveryMsgShmid, IPC_RMID, NULL);
-+ }
-+
-+ if (StatusFp != NULL)
-+ {
-+ fflush(StatusFp);
-+ fclose(StatusFp);
-+ StatusFp = NULL;
-+ }
-+ if (LogFp != NULL)
-+ {
-+ fflush(LogFp);
-+ fclose(LogFp);
-+ LogFp = NULL;
-+ }
-+
-+ if (PGR_Result != NULL)
-+ {
-+ free(PGR_Result);
-+ PGR_Result = NULL;
-+ }
-+ if (PGR_Response_Inf != NULL)
-+ {
-+ free(PGR_Response_Inf);
-+ PGR_Response_Inf = NULL;
-+ }
-+
-+ if (LoadBalanceTbl != NULL)
-+ {
-+ free(LoadBalanceTbl);
-+ LoadBalanceTbl = NULL;
-+ }
-+
-+ if (PGR_Log_Header != NULL)
-+ {
-+ free(PGR_Log_Header);
-+ PGR_Log_Header = NULL;
-+ }
-+
-+ if (PGR_Send_Query_ID != NULL)
-+ {
-+ free(PGR_Send_Query_ID);
-+ PGR_Send_Query_ID = NULL;
-+ }
-+
-+ if (CascadeSemID > 0)
-+ {
-+ sem_quit(CascadeSemID);
-+ CascadeSemID = 0;
-+ }
-+ if (SemID > 0)
-+ {
-+ sem_quit(SemID);
-+ SemID = 0;
-+ }
-+ if (RecoverySemID > 0)
-+ {
-+ sem_quit(RecoverySemID);
-+ RecoverySemID = 0;
-+ }
-+ if (VacuumSemID > 0)
-+ {
-+ sem_quit(VacuumSemID);
-+ }
-+
-+ snprintf(fname, sizeof(fname), "%s/%s", PGR_Data_Path,
PGREPLICATE_PID_FILE);
-+ unlink(fname);
-+
-+ /* close socket between rlog process */
-+
-+ if (Replicateion_Log->r_log_sock >= 0)
-+ {
-+ close(Replicateion_Log->r_log_sock);
-+ Replicateion_Log->r_log_sock = -1;
-+ }
-+ if (Replicateion_Log->RLog_Sock_Path != NULL)
-+ {
-+ unlink(Replicateion_Log->RLog_Sock_Path);
-+ free(Replicateion_Log->RLog_Sock_Path);
-+ Replicateion_Log->RLog_Sock_Path = NULL;
-+ }
-+ exit(exit_status);
-+}
-+
-+static int
-+send_cluster_status_to_load_balance(HostTbl * host_ptr,int status)
-+{
-+ RecoveryPacket packet;
-+ int rtn = 0;
-+
-+ memset(&packet,0,sizeof(RecoveryPacket));
-+ packet.packet_no = htons(status);
-+ strncpy(packet.hostName,host_ptr->hostName,sizeof(packet.hostName));
-+ packet.port = htons(host_ptr->port);
-+ rtn = PGRsend_load_balance_packet(&packet);
-+ return rtn;
-+}
-+
-+int
-+PGRset_host_status(HostTbl * host_ptr,int status)
-+{
-+ if (host_ptr == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (host_ptr->useFlag != status)
-+ {
-+ host_ptr->useFlag = status;
-+ if (status == DB_TBL_ERROR )
-+ {
-+ host_ptr->transaction_count = 0;
-+
send_cluster_status_to_load_balance(host_ptr,RECOVERY_ERROR_CONNECTION);
-+ }
-+ write_host_status_file(host_ptr);
-+ }
-+ return STATUS_OK;
-+}
-+
-+static void
-+write_host_status_file(HostTbl * host_ptr)
-+{
-+ switch( host_ptr->useFlag)
-+ {
-+ case DB_TBL_FREE:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s free",
-+ host_ptr->port,
-+ host_ptr->hostName);
-+ break;
-+ case DB_TBL_INIT:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s
initialize",
-+ host_ptr->port,
-+ host_ptr->hostName);
-+ break;
-+ case DB_TBL_USE:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s start
use",
-+ host_ptr->port,
-+ host_ptr->hostName);
-+ break;
-+ case DB_TBL_ERROR:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s error",
-+ host_ptr->port,
-+ host_ptr->hostName);
-+ break;
-+ case DB_TBL_END:
-+ PGRwrite_log_file(StatusFp,"port(%d) host:%s end",
-+ host_ptr->port,
-+ host_ptr->hostName);
-+ break;
-+ }
-+}
-+
-+#if 0
-+static int
-+check_result( PGresult * res )
-+{
-+ int status = 0;
-+
-+ status = PQresultStatus(res);
-+ if ((status == PGRES_NONFATAL_ERROR ) ||
-+ (status == PGRES_FATAL_ERROR ))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+#endif
-+
-+/*--------------------------------------------------
-+ * SYMBOL
-+ * PGRsend_replicate_packet_to_server()
-+ * NOTES
-+ * Send query data to the cluster DB and recieve result data.
-+ * ARGS
-+ * HostTbl * host_ptr: the record of cluster DB table (target)
-+ * ReplicateHeader * header: header data
-+ * char *query: query data
-+ * char * result: returned result data
-+ * RETURN
-+ * STATUS_OK: OK
-+ * STATUS_ERROR: NG
-+ * STATUS_LOCK_CONFLICT: Lock conflicted
-+ *---------------------------------------------------
-+ */
-+int
-+PGRsend_replicate_packet_to_server( HostTbl * host_ptr, ReplicateHeader *
header, char *query , char * result,unsigned int replicationId, bool recovery)
-+{
-+ char * func = "PGRsend_replicate_packet_to_server()";
-+ TransactionTbl * transaction_tbl = NULL;
-+ char *database = NULL;
-+ char port[8];
-+ char *userName = NULL;
-+ char * host = NULL;
-+ int rtn = 0;
-+ int current_cluster = 0;
-+ int query_size = 0;
-+
-+ if ((query == NULL) || (header == NULL))
-+ {
-+ show_error("%s: query is broken",func);
-+ return STATUS_ERROR;
-+ }
-+ query_size = ntohl(header->query_size);
-+ if (query_size < 0)
-+ {
-+ show_error("%s: query size is broken",func);
-+ return STATUS_ERROR;
-+ }
-+ if (host_ptr == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ if (PGR_Response_Inf != NULL)
-+ {
-+ current_cluster = PGR_Response_Inf->current_cluster;
-+ }
-+
-+ /*
-+ * set up the connection
-+ */
-+ database = (char *)header->dbName;
-+ snprintf(port,sizeof(port),"%d", host_ptr->port);
-+ userName = (char *)header->userName;
-+ host = host_ptr->resolvedName;
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:host(%s) : port(%s)",func,host,port);
-+#endif
-+ /*
-+ * get the transaction table data
-+ * it has the connection data with each cluster DB
-+ */
-+ transaction_tbl = getTransactionTbl(host_ptr,header);
-+ /*
-+ * if the transaction process is new one,
-+ * create connection data and add the transaction table
-+ */
-+ if (transaction_tbl == (TransactionTbl *)NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:set new Transaction ",func);
-+#endif
-+ StartReplication[current_cluster] = true;
-+ transaction_tbl = setTransactionTbl(host_ptr, header);
-+ if (transaction_tbl == (TransactionTbl *)NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:setTransactionTbl failed",func);
-+#endif
-+ if ( header->cmdSts != CMD_STS_NOTICE )
-+ {
-+ PGRset_host_status(host_ptr,DB_TBL_ERROR);
-+ }
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else
-+ {
-+ /*
-+ * re-use the connection data
-+ */
-+ if ((transaction_tbl->conn != (PGconn *)NULL) &&
-+ (transaction_tbl->conn->sock > 0))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:re-use Transaction ",func);
-+#endif
-+ StartReplication[current_cluster] = false;
-+ }
-+ else
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:re-use failed. create new Transaction
",func);
-+#endif
-+ if (transaction_tbl->conn != (PGconn *)NULL)
-+ {
-+ PQfinish(transaction_tbl->conn);
-+ transaction_tbl->conn = NULL;
-+ }
-+ transaction_tbl->conn =
pgr_createConn(host,port,database,userName);
-+ StartReplication[current_cluster] = true;
-+ }
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:connect db:%s port:%s user:%s host:%s ",
-+ func, database,port,userName,host);
-+#endif
-+ rtn = send_replicate_packet_to_server( transaction_tbl,
current_cluster, host_ptr, header, query ,result ,replicationId, recovery);
-+ return rtn;
-+}
-+
-+static int
-+send_replicate_packet_to_server( TransactionTbl * transaction_tbl, int
current_cluster, HostTbl * host_ptr, ReplicateHeader * header, char *query ,
char * result,unsigned int replicationId, bool recovery)
-+{
-+ char * func = "send_replicate_packet_to_server()";
-+ PGconn * conn = (PGconn *)NULL;
-+ PGresult * res = (PGresult *)NULL;
-+ char sync_command[256];
-+ bool sync_command_flg = false;
-+ char * str = NULL;
-+ int rtn = 0;
-+ int query_size = 0;
-+ int hostNum = 0;
-+ StringInfoData input_message;
-+
-+ if (( transaction_tbl == (TransactionTbl *)NULL) ||
-+ ( host_ptr == (HostTbl *) NULL) ||
-+ (header == (ReplicateHeader *) NULL) ||
-+ (query == NULL) ||
-+ ( result == NULL))
-+ {
-+ show_debug("%s:unexpected NULL variable");
-+ return STATUS_ERROR;
-+ }
-+
-+ query_size = ntohl(header->query_size);
-+ if (query_size < 0)
-+ {
-+ show_error("%s: query size is broken",func);
-+
-+ return STATUS_ERROR;
-+ }
-+
-+ if(header->cmdSts == CMD_STS_OTHER &&
-+ header->cmdType == CMD_TYPE_CONNECTION_CLOSE)
-+ {
-+ check_delete_transaction(host_ptr,header);
-+ return STATUS_OK;
-+ }
-+
-+ conn = transaction_tbl->conn;
-+ if (conn == NULL)
-+ {
-+ show_error("%s:[%d@%s] may be
down",func,host_ptr->port,host_ptr->hostName);
-+ if ( header->cmdSts != CMD_STS_NOTICE )
-+ {
-+ PGRset_host_status(host_ptr,DB_TBL_ERROR);
-+ }
-+ return STATUS_ERROR;
-+ }
-+ hostNum = host_ptr->hostNum;
-+
-+#if 0
-+ /* check query id */
-+ if (*(PGR_Send_Query_ID + hostNum ) == ntohl(header->query_id))
-+ {
-+ return STATUS_OK;
-+ }
-+#endif
-+
-+ /*
-+ * When the query is transaction query...
-+ */
-+ if (is_need_sync_time(header) == true)
-+ {
-+ if (transaction_tbl->transaction_count >1 )
-+ {
-+ sync_command_flg = false;
-+ }
-+ else
-+ {
-+ sync_command_flg = true;
-+ }
-+ }
-+ /*
-+ if ((header->cmdSts == CMD_STS_TRANSACTION ) ||
-+ (header->cmdSts == CMD_STS_SET_SESSION_AUTHORIZATION ))
-+ {
-+ if ((header->cmdSts == CMD_STS_TRANSACTION ) &&
-+ ((header->cmdType != CMD_TYPE_BEGIN) ||
-+ (transaction_tbl->transaction_count >1 )))
-+ {
-+ sync_command_flg = false;
-+ }
-+ }
-+ */
-+
-+ /*
-+ * execute query
-+ */
-+
-+ if (header->rlog > 0 )
-+ {
-+
-+ if (is_executed_query( conn, header) == true)
-+ {
-+ return STATUS_OK;
-+ }
-+ else
-+ {
-+ show_debug("%s:check replication log issue ,
id=%d,rlog=%d,query=%s
status=not_replicated",func,ntohl(header->replicate_id),header->rlog,query);
-+ }
-+ }
-+ if (( header->cmdSts != CMD_STS_NOTICE ) &&
-+ ( header->cmdSts != CMD_STS_PREPARE ) &&
-+ ((sync_command_flg == true) ||
-+ (StartReplication[current_cluster] == true)))
-+ {
-+ snprintf(sync_command,sizeof(sync_command),
-+ "SELECT %s(%d,%u,%u,%u,%d,%u) ",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_SET_CURRENT_TIME_FUNC_NO,
-+ (unsigned int)ntohl(header->tv.tv_sec),
-+ (unsigned int)ntohl(header->tv.tv_usec),
-+ (unsigned int)ntohl(PGR_Log_Header->replicate_id),
-+ PGR_Response_Inf->response_mode,
-+ *PGR_ReplicateSerializationID);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command(%s)",func,sync_command);
-+#endif
-+ res = PQexec(conn, sync_command);
-+ if (res != NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command returns
%s",func,PQcmdStatus(res));
-+#endif
-+ PQclear(res);
-+ }
-+ StartReplication[current_cluster] = false;
-+ }
-+
-+ res = NULL;
-+ if ((header->cmdType == CMD_TYPE_COPY_DATA) ||
-+ (header->cmdType == CMD_TYPE_COPY_DATA_END))
-+ {
-+ /* copy data replication */
-+ rtn =PQputnbytes(conn, query,query_size);
-+ if (header->cmdType == CMD_TYPE_COPY_DATA_END)
-+ {
-+ rtn = PQendcopy(conn);
-+ if (rtn == 1) /* failed */
-+ {
-+ if (transaction_tbl->conn != NULL)
-+ {
-+ PQfinish(transaction_tbl->conn);
-+ transaction_tbl->conn = (PGconn
*)NULL;
-+ StartReplication[current_cluster] =
true;
-+ }
-+ }
-+ }
-+ *(PGR_Send_Query_ID + hostNum ) == ntohl(header->query_id);
-+ return STATUS_OK;
-+ }
-+ else if (header->cmdSts == CMD_STS_LARGE_OBJECT)
-+ {
-+ replicate_lo(conn, header,(LOArgs *)query);
-+ return STATUS_OK;
-+ }
-+ else if (header->cmdSts == CMD_STS_PREPARE)
-+ {
-+
-+ if ( !PGR_Parse_Session_Started)
-+ {
-+ snprintf(sync_command,sizeof(sync_command),
-+ "SELECT %s(%d,%u,%u,%u,%d,%u) ",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_SET_CURRENT_TIME_FUNC_NO,
-+ (unsigned int)ntohl(header->tv.tv_sec),
-+ (unsigned int)ntohl(header->tv.tv_usec),
-+ (unsigned
int)ntohl(PGR_Log_Header->replicate_id),
-+ PGR_Response_Inf->response_mode,
-+ *PGR_ReplicateSerializationID);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command [%s]",func,sync_command);
-+#endif
-+ res = PQexec(conn, sync_command);
-+ if (res != NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command returns
%s",func,PQcmdStatus(res));
-+#endif
-+ PQclear(res);
-+ res = NULL;
-+ }
-+ while ((res = PQgetResult(conn)) != NULL)
-+ {
-+ if (res->resultStatus == PGRES_COPY_IN)
-+ {
-+ PQclear(res);
-+ return STATUS_ERROR;
-+ }
-+ else if (res->resultStatus == PGRES_COPY_OUT)
-+ {
-+ conn->asyncStatus = PGASYNC_BUSY;
-+ }
-+ else if (conn->status == CONNECTION_BAD)
-+ {
-+ PQclear(res);
-+ return STATUS_ERROR;
-+ }
-+ PQclear(res);
-+ }
-+ }
-+ set_string_info(&input_message,header,query);
-+ switch (header->cmdType)
-+ {
-+ case CMD_TYPE_P_PARSE :
-+ if (send_p_parse(conn, &input_message) !=
STATUS_OK)
-+ {
-+ pqHandleSendFailure(conn);
-+ PGR_Parse_Session_Started = false;
-+ return STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_P_BIND :
-+ if (send_p_bind(conn, &input_message) !=
STATUS_OK)
-+ {
-+ pqHandleSendFailure(conn);
-+ PGR_Parse_Session_Started = false;
-+ return STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_P_DESCRIBE :
-+ if (send_p_describe(conn, &input_message) !=
STATUS_OK)
-+ {
-+ pqHandleSendFailure(conn);
-+ PGR_Parse_Session_Started = false;
-+ return STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_P_EXECUTE :
-+ if (send_p_execute(conn,&input_message) !=
STATUS_OK)
-+ {
-+ pqHandleSendFailure(conn);
-+ PGR_Parse_Session_Started = false;
-+ return STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_P_SYNC :
-+ if (send_p_sync(conn, &input_message) !=
STATUS_OK)
-+ {
-+ pqHandleSendFailure(conn);
-+ PGR_Parse_Session_Started = false;
-+ return STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_P_CLOSE :
-+ if (send_p_close(conn, &input_message) !=
STATUS_OK)
-+ {
-+ pqHandleSendFailure(conn);
-+ PGR_Parse_Session_Started = false;
-+ return STATUS_ERROR;
-+ }
-+ break;
-+ default :
-+ break;
-+ }
-+ return STATUS_OK;
-+ }
-+ else
-+ {
-+ if (transaction_tbl->lock != STATUS_OK)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:[%d]transaction_tbl->lock is
[%d]",func,current_cluster,transaction_tbl->lock );
-+#endif
-+ transaction_tbl->lock = STATUS_OK;
-+ }
-+ snprintf(sync_command,sizeof(sync_command),
-+ "SELECT %s(%d,%u,%u,%d) ",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_SET_CURRENT_REPLICATION_QUERY_ID_NO,
-+ replicationId,
-+ 0,
-+ PGR_Response_Inf->response_mode);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command(%s)",func,sync_command);
-+#endif
-+ res = PQexec(conn, sync_command);
-+ if (res != NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command returns
%s",func,PQcmdStatus(res));
-+#endif
-+ PQclear(res);
-+ res = NULL;
-+ }
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:execute query(%s)",func,query);
-+#endif
-+ res = PQexec(conn, query);
-+
-+ }
-+
-+ if (res == NULL)
-+ {
-+ StartReplication[current_cluster] = true;
-+ show_debug("%s:PQexec status error",func);
-+ return STATUS_ERROR;
-+ }
-+
-+ str = PQcmdStatus(res);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PQexec returns :%s",func,str);
-+#endif
-+ if ((str == NULL) || (*str == '\0'))
-+ {
-+ if ((result != NULL) && (res != NULL) && (res->errMsg !=
NULL))
-+ {
-+
snprintf(result,PGR_MESSAGE_BUFSIZE,"E%s",res->errMsg);
-+ }
-+ else
-+ {
-+ strcpy(result,"E");
-+ }
-+ StartReplication[current_cluster] = true;
-+ }
-+ else
-+ {
-+ if
(!strncmp(str,PGR_LOCK_CONFLICT_NOTICE_CMD,strlen(PGR_LOCK_CONFLICT_NOTICE_CMD)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:LOCK CONFLICT from PQexec",func);
-+#endif
-+ if (res != NULL)
-+ PQclear(res);
-+
-+ transaction_tbl->lock = STATUS_LOCK_CONFLICT;
-+ return STATUS_LOCK_CONFLICT;
-+ }
-+ else if
(!strncmp(str,PGR_DEADLOCK_DETECT_NOTICE_CMD,strlen(PGR_DEADLOCK_DETECT_NOTICE_CMD)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:DEADLOCK DETECTED from PQexec",func);
-+#endif
-+ if (res != NULL)
-+ PQclear(res);
-+ transaction_tbl->lock = STATUS_DEADLOCK_DETECT;
-+ return STATUS_DEADLOCK_DETECT;
-+ }
-+ snprintf(result,PGR_MESSAGE_BUFSIZE,"C%s",str);
-+ }
-+ if (res != NULL)
-+ PQclear(res);
-+
-+ /* set send query id */
-+ *(PGR_Send_Query_ID + hostNum ) = ntohl(header->query_id);
-+
-+ /*
-+ * if the query is end transaction process...
-+ */
-+ check_delete_transaction(host_ptr,header);
-+ return STATUS_OK;
-+
-+}
-+
-+static int
-+check_delete_transaction (HostTbl * host_ptr, ReplicateHeader * header)
-+{
-+ char *database = NULL;
-+
-+ if ((host_ptr == NULL) || (header == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ database = (char *)header->dbName;
-+ if(header->cmdSts == CMD_STS_OTHER &&
-+ header->cmdType == CMD_TYPE_CONNECTION_CLOSE)
-+ {
-+ notice_abort(host_ptr, header);
-+ deleteTransactionTbl(host_ptr,header);
-+ }
-+
-+ delete_template(host_ptr, header);
-+ return STATUS_OK;
-+}
-+
-+static void
-+check_transaction_status(ReplicateHeader * header,
-+ HostTbl *host,
-+ TransactionTbl *transaction)
-+{
-+ static bool exec_copy = false;
-+ if (header == (ReplicateHeader *)NULL)
-+ {
-+ return;
-+ }
-+ if (header->cmdSts == CMD_STS_TRANSACTION )
-+ {
-+ if (header->cmdType == CMD_TYPE_BEGIN )
-+ {
-+ host->transaction_count++;
-+ transaction->in_transaction = true;
-+ transaction->transaction_count ++;
-+ }
-+ else if ((header->cmdType == CMD_TYPE_COMMIT) ||
-+ (header->cmdType == CMD_TYPE_ROLLBACK))
-+ {
-+ host->transaction_count--;
-+ transaction->transaction_count --;
-+ if (transaction->transaction_count == 0)
-+ {
-+ transaction->in_transaction = false;
-+ }
-+ }
-+ }
-+ else
-+ {
-+ if ( header->cmdType == CMD_TYPE_COPY )
-+ {
-+ exec_copy = true;
-+ host->transaction_count--;
-+ }
-+ else if (header->cmdType == CMD_TYPE_COPY_DATA_END)
-+ {
-+ if (exec_copy)
-+ host->transaction_count--;
-+ exec_copy = false;

-+ }
-+ }
-+
-+}
-+/*
-+ * set query in queue
-+ */
-+int
-+PGRset_queue(ReplicateHeader * header,char * query)
-+{
-+ char * func = "PGRset_queue()";
-+ RecoveryQueueHeader * msg_header = NULL;
-+ RecoveryQueueQuery * msg_query = NULL;
-+ int size = 0;
-+ long mtype = 0;
-+ int rtn = 0;
-+ int query_size = 0;
-+
-+ if ((*RecoveryMsgid < 0) || (header == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ query_size = ntohl(header->query_size);
-+ if (query_size < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ /*
-+ * set header data
-+ */
-+ size = sizeof(ReplicateHeader) + sizeof(RecoveryQueueHeader);
-+ mtype = *PGR_ReplicateSerializationID;
-+ msg_header = (RecoveryQueueHeader *)malloc(size+4);
-+ if (msg_header == NULL)
-+ {
-+ show_error("%s:malloc() failed. reason: %s", func,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(msg_header,0,size+4);
-+ msg_header->mtype = RECOVERY_HEADER_MTYPE;
-+ msg_header->query_mtype = mtype;
-+ memcpy(msg_header->mdata,header,sizeof(ReplicateHeader));
-+
-+ /*
-+ * set query data
-+ */
-+ size = query_size + sizeof(RecoveryQueueQuery);
-+ msg_query = (RecoveryQueueQuery *) malloc(size+4);
-+ if (msg_query == NULL)
-+ {
-+ show_error("%s:malloc() failed. reason: %s", func,
strerror(errno));
-+ free(msg_header);
-+ msg_header = NULL;
-+ return STATUS_ERROR;
-+ }
-+ memset(msg_query,0,size+4);
-+ msg_query->mtype = mtype;
-+ msg_query->replicationId=*PGR_ReplicateSerializationID;
-+ memcpy(msg_query->mdata,query,query_size);
-+
-+
-+
-+ /*
-+ * send header data to queue
-+ */
-+ rtn = msgsnd(*RecoveryMsgid, msg_header,
sizeof(long)+sizeof(ReplicateHeader), IPC_NOWAIT);
-+ if (rtn < 0)
-+ {
-+ show_error("%s:msgsnd failed. reason: %s", func,
strerror(errno));
-+ free(msg_header);
-+ free(msg_query);
-+ msgctl(*RecoveryMsgid, IPC_RMID, NULL);
-+ *RecoveryMsgid = msgget (IPC_PRIVATE, 00666 | IPC_CREAT );
-+ return STATUS_ERROR;
-+ }
-+ /*
-+ * send query data to queue
-+ */
-+ rtn = msgsnd(*RecoveryMsgid, msg_query, sizeof(unsigned
int)+query_size, IPC_NOWAIT);
-+ if (rtn < 0)
-+ {
-+ show_error("%s:msgsnd failed. reason: %s", func,
strerror(errno));
-+ free(msg_header);
-+ free(msg_query);
-+ msgctl(*RecoveryMsgid, IPC_RMID, NULL);
-+ *RecoveryMsgid = msgget (IPC_PRIVATE, 00666 | IPC_CREAT );
-+ return STATUS_ERROR;
-+ }
-+
-+ /*
-+ * release memory
-+ */
-+ free(msg_header);
-+ free(msg_query);
-+ msg_header = NULL;
-+ msg_query = NULL;
-+
-+ return STATUS_OK;
-+}
-+
-+HostTbl *
-+PGRget_HostTbl(char * hostName, int port)
-+{
-+ HostTbl * ptr = NULL;
-+ int len = 0;
-+
-+ if (Host_Tbl_Begin == NULL)
-+ {
-+ return NULL;
-+ }
-+ len = strlen(hostName);
-+ ptr = Host_Tbl_Begin;
-+ if (len > sizeof(ptr->hostName))
-+ {
-+ len = sizeof(ptr->hostName);
-+ }
-+ while(ptr->useFlag != DB_TBL_END)
-+ {
-+ if ((! memcmp(ptr->hostName,hostName,len)) &&
-+ (ptr->port == port))
-+ {
-+ return ptr;
-+ }
-+ ptr ++;
-+ }
-+ return (HostTbl*)NULL;
-+}
-+
-+static void
-+sem_quit(int semid)
-+{
-+ semctl(semid, 0, IPC_RMID);
-+}
-+
-+void
-+PGRclear_connections(void)
-+{
-+ Dlelem *ptr = NULL, *next;
-+
-+ pthread_mutex_lock(&transaction_table_mutex);
-+ ptr = DLGetHead(Transaction_Tbl_Begin);
-+ while (ptr)
-+ {
-+ TransactionTbl *transaction = DLE_VAL(ptr);
-+ if (transaction->conn != NULL)
-+ {
-+ PQfinish(transaction->conn);
-+ }
-+ next = DLGetSucc(ptr);
-+ DLRemove(ptr);
-+ DLFreeElem(ptr);
-+ ptr = next;
-+ }
-+ DLFreeList(Transaction_Tbl_Begin);
-+ Transaction_Tbl_Begin = NULL;
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+}
-+
-+static bool
-+is_need_sync_time(ReplicateHeader * header)
-+{
-+ bool rtn = false;
-+
-+ if ((header->cmdSts == CMD_STS_QUERY ) &&
-+ ((header->cmdType == CMD_TYPE_INSERT) ||
-+ (header->cmdType == CMD_TYPE_UPDATE) ||
-+ (header->cmdType == CMD_TYPE_DELETE) ||
-+ (header->cmdType == CMD_TYPE_SET) ||
-+ (header->cmdType == CMD_TYPE_EXECUTE)))
-+ {
-+ rtn = true;
-+ }
-+ else
-+ {
-+ if ((header->cmdType == CMD_TYPE_COPY) ||
-+ (header->cmdType == CMD_TYPE_SELECT) ||
-+ (header->cmdType == CMD_TYPE_VACUUM) ||
-+ (header->cmdType == CMD_TYPE_ANALYZE) ||
-+ (header->cmdType == CMD_TYPE_BEGIN))
-+ {
-+ rtn = true;
-+ }
-+ if ((header->cmdSts == CMD_STS_TRANSACTION ) &&
-+ (header->cmdType != CMD_TYPE_BEGIN))
-+ {
-+ rtn = false;
-+ }
-+ }
-+ return rtn;
-+}
-+
-+static bool
-+is_need_wait_answer(ReplicateHeader * header)
-+{
-+ bool rtn = false;
-+
-+ if (header->cmdSts == CMD_STS_PREPARE)
-+ {
-+ rtn = false;
-+ }
-+ else if ((header->cmdType == CMD_TYPE_COPY) ||
-+ (header->cmdType == CMD_TYPE_COPY_DATA) ||
-+ (header->cmdType == CMD_TYPE_COPY_DATA_END))
-+ {
-+ rtn = false;
-+ }
-+ else if ((header->cmdSts == CMD_STS_QUERY ) &&
-+ ((header->cmdType == CMD_TYPE_INSERT) ||
-+ (header->cmdType == CMD_TYPE_UPDATE) ||
-+ (header->cmdType == CMD_TYPE_DELETE) ||
-+ (header->cmdType == CMD_TYPE_VACUUM) ||
-+ (header->cmdType == CMD_TYPE_ANALYZE) ||
-+ (header->cmdType == CMD_TYPE_EXECUTE)))
-+ {
-+ rtn = true;
-+ }
-+ else if ((header->cmdSts == CMD_STS_TRANSACTION ) ||
-+ (header->cmdSts == CMD_STS_SET_SESSION_AUTHORIZATION
) ||
-+ (header->cmdSts == CMD_STS_TEMP_TABLE ) ||
-+ (header->cmdType == CMD_TYPE_SELECT))
-+ {
-+ rtn = true;
-+ }
-+
-+ return rtn;
-+}
-+
-+static void
-+delete_template(HostTbl * ptr, ReplicateHeader * header)
-+{
-+ if ((ptr == (HostTbl *)NULL ) ||
-+ (header == (ReplicateHeader *)NULL) )
-+ {
-+ return;
-+ }
-+
-+ if ((! strncmp(header->dbName,"template1",9)) ||
-+ (! strncmp(header->dbName,"template0",9)))
-+ {
-+ if ((header->cmdSts != CMD_STS_TRANSACTION ) &&
-+ ( header->cmdSts != CMD_STS_SET_SESSION_AUTHORIZATION
) &&
-+ ( header->cmdSts != CMD_STS_TEMP_TABLE ))
-+ {
-+ deleteTransactionTbl(ptr,header);
-+ }
-+ }
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * check_copy_command()
-+ * NOTES
-+ * check the query which it is copy command or not
-+ * when the query is 'copy from', set 'stdin' after 'from'
-+ * ARGS
-+ * char * query: query strings(I)
-+ * RETURN
-+ * copy command : changed copy command
-+ * other command : NULL
-+ *--------------------------------------------------------------------
-+ */
-+static char *
-+check_copy_command(char * query)
-+{
-+ char * p;
-+ char * p1, *p2, *wp;
-+ char * buf;
-+ int size;
-+
-+ if (query == NULL)
-+ return NULL;
-+ size = strlen(query) + strlen(" stdin ");
-+ p = p1 = query;
-+ wp = strstr(p,"FROM");
-+ if (wp == NULL)
-+ wp = strstr(p,"from");
-+
-+ if (wp != NULL)
-+ {
-+ p = wp + strlen("FROM");
-+ *p = '\0';
-+ p ++;
-+ while ((isspace(*p)) && (*p != '\0')) p++;
-+ while ((!isspace(*p)) && (*p != '\0')) p++;
-+ p2 = p;
-+ buf = malloc(size);
-+ if (buf == NULL)
-+ {
-+ return NULL;
-+ }
-+ snprintf(buf,size,"%s stdin %s",p1,p2);
-+ return buf;
-+ }
-+ return NULL;
-+}
-+
-+static int
-+next_replication_id(void)
-+{
-+ char * func = "next_replication_id()";
-+
-+ if (Recovery_Status_Inf == (RecoveryStatusInf *)NULL)
-+ {
-+ show_error("%s: Recovery_Status_Inf is NULL",func);
-+ return -1;
-+ }
-+ Recovery_Status_Inf->replication_id ++;
-+ Recovery_Status_Inf->check_point --;
-+ return (Recovery_Status_Inf->replication_id);
-+}
-+
-+static void
-+check_replication_id(void)
-+{
-+ char * func = "check_replication_id()";
-+
-+ if (Recovery_Status_Inf == (RecoveryStatusInf *)NULL)
-+ {
-+ show_error("%s: Recovery_Status_Inf is NULL",func);
-+ return ;
-+ }
-+ if (Recovery_Status_Inf->check_point < 0)
-+ {
-+ Recovery_Status_Inf->check_point = PGR_CHECK_POINT ;
-+ rewind(RidFp);
-+
PGRwrite_log_file(RidFp,"%u",Recovery_Status_Inf->replication_id +
PGR_CHECK_POINT );
-+ }
-+}
-+
-+int
-+PGRset_replication_id(uint32_t id)
-+{
-+ char * func = "set_replication_id()";
-+
-+ Recovery_Status_Inf->replication_id = id;
-+ return (Recovery_Status_Inf->replication_id);
-+}
-+
-+int
-+PGRdo_replicate(int sock,ReplicateHeader *header, char * query)
-+{
-+
-+ char * func = "PGRdo_replicate()";
-+
-+ struct timeval tv;
-+ int status = STATUS_OK;
-+ int recovery_status = 0;
-+ char * query_string = NULL;
-+
-+ if (header->cmdType == CMD_TYPE_COPY)
-+ {
-+ query_string = check_copy_command(query);
-+ if (query_string == NULL)
-+ {
-+ return LOOP_CONTINUE;
-+ }
-+ }
-+ else
-+ {
-+ query_string = query;
-+ if (header->cmdType == CMD_TYPE_SET)
-+ {
-+ if (is_autocommit_off(query_string) == true)
-+ {
-+ PGR_AutoCommit = false;
-+ }
-+ else if (is_autocommit_on(query_string) == true)
-+ {
-+ PGR_AutoCommit = true;
-+ }
-+ }
-+ }
-+ header->isAutoCommit=PGR_AutoCommit ? 1 : 0;
-+ gettimeofday(&tv,NULL);
-+ header->tv.tv_sec = htonl(tv.tv_sec);
-+ header->tv.tv_usec = htonl(tv.tv_usec);
-+
-+ /* set query id */
-+ header->query_id = htonl(PGRget_next_query_id());
-+
-+ /* save header for logging */
-+ if (is_need_sync_time(header) == true)
-+ {
-+ if (PGR_Log_Header != NULL)
-+ {
-+ memcpy(PGR_Log_Header,header,sizeof(ReplicateHeader));
-+ if (header->rlog == 0)
-+ {
-+ PGR_Log_Header->replicate_id =
htonl(next_replication_id());
-+ }
-+ }
-+ }
-+ /* check rlog */
-+ if (header->rlog == CONNECTION_SUSPENDED_TYPE )
-+ {
-+ if (PGRget_rlog_header(header) == STATUS_OK)
-+ {
-+ header->rlog = CONNECTION_SUSPENDED_TYPE;
-+
-+ }
-+ }
-+
-+ /* check recovery mode */
-+
-+ recovery_status = PGRget_recovery_status();
-+ PGRcheck_recovered_host();
-+
-+ /* send replication packet */
-+ status = PGRreplicate_packet_send(
header,query_string,sock,recovery_status);
-+ show_debug("%s:PGRreplicate_packet_send returns %d",func,status);
-+
-+#if 0
-+ if(recovery_status == RECOVERY_START &&
-+ PGRset_queue(header,query_string)!= STATUS_OK)
-+ {
-+ /*
-+ *Failed to set queue. abort.
-+ */
-+ show_error("%s:failed to put query to queue.abort to
recovery",func);
-+ PGRset_recovery_status(RECOVERY_INIT);
-+ }
-+#endif
-+
-+ if ((header->cmdType == CMD_TYPE_COPY) &&
-+ (query_string != NULL))
-+ {
-+ free(query_string);
-+ query_string = NULL;
-+ }
-+
-+ if (status == STATUS_ABORTED )
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:status is STATUS_ABORTED",func);
-+#endif
-+ return LOOP_END;
-+ }
-+ if (status == STATUS_DEADLOCK_DETECT)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:status is STATUS_DEADLOCK_DETECT",func);
-+#endif
-+ return LOOP_END;
-+ }
-+ return LOOP_CONTINUE;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * PGRreturn_result()
-+ * NOTES
-+ * Return result of execution
-+ * ARGS
-+ * int dest: socket of destination server (I)
-+ * char *result: result data(I)
-+ * int wait: wait flag (I)
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ * NG: STATUS_LOCK_CONFLICT
-+ * NG: STATUS_DEADLOCK_DETECT
-+ *--------------------------------------------------------------------
-+ */
-+int
-+PGRreturn_result(int dest, char * result, int wait)
-+{
-+ char * func = "PGRreturn_result()";
-+ fd_set wmask;
-+ struct timeval timeout;
-+ int rtn = 0;
-+ char * send_ptr = NULL;
-+ int send_size= 0;
-+ int buf_size = 0;
-+ int s = 0;
-+ int status = 0;
-+ int flag = 0;
-+
-+ if (result == NULL)
-+ {
-+ show_error("%s:result is not initialize",func);
-+ return STATUS_ERROR;
-+ }
-+ if (dest < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ send_ptr = result;
-+ buf_size = PGR_MESSAGE_BUFSIZE;
-+ if (buf_size < 1)
-+ buf_size = 1;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+#ifdef MSG_DONTWAIT
-+ flag |= MSG_DONTWAIT;
-+#endif
-+#ifdef MSG_NOSIGNAL
-+ flag |= MSG_NOSIGNAL;
-+#endif
-+
-+ for (;;)
-+ {
-+ timeout.tv_sec = PGR_SEND_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ FD_ZERO(&wmask);
-+ FD_SET(dest,&wmask);
-+
-+ rtn = select(dest+1, (fd_set *)NULL, &wmask, (fd_set *)NULL,
&timeout);
-+ if (rtn < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+
-+ show_error("%s:select failed ,errno is %s",func ,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ else if (rtn && FD_ISSET(dest, &wmask))
-+ {
-+ s = send(dest,send_ptr + send_size,buf_size -
send_size ,flag);
-+ if (s < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+ else
-+ {
-+ show_error("%s:send error: %d(%s)",
func, errno, strerror(errno));
-+ memset(send_ptr, 0,
PGR_MESSAGE_BUFSIZE);
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else if (s > 0)
-+ {
-+ send_size += s;
-+ if (send_size == buf_size)
-+ {
-+ status = STATUS_OK;
-+ if (wait == PGR_WAIT_ANSWER)
-+ {
-+ status = read_answer(dest);
-+ }
-+ return status;
-+ }
-+ }
-+ else /* s == 0 */
-+ {
-+ show_error("%s:unexpected EOF", func);
-+ memset(send_ptr, 0, PGR_MESSAGE_BUFSIZE);
-+ return STATUS_ERROR;
-+ }
-+ }
-+ }
-+ memset(send_ptr, 0, PGR_MESSAGE_BUFSIZE);
-+ return STATUS_ERROR;
-+}
-+
-+/*--------------------------------------------------------------------
-+ * SYMBOL
-+ * read_answer()
-+ * NOTES
-+ * Receive answer packet
-+ * ARGS
-+ * int dest: socket of destination server (I)
-+ * RETURN
-+ * OK: STATUS_OK
-+ * NG: STATUS_ERROR
-+ * NG: STATUS_LOCK_CONFLICT
-+ * NG: STATUS_DEADLOCK_DETECT
-+ *--------------------------------------------------------------------
-+ */
-+static int
-+read_answer(int dest)
-+{
-+ char * func = "read_answer()";
-+ fd_set rmask;
-+ struct timeval timeout;
-+ int rtn;
-+ ReplicateHeader header;
-+ char * answer = NULL;
-+ int status = STATUS_ERROR;
-+
-+ for(;;)
-+ {
-+ if (answer != NULL)
-+ {
-+ free(answer);
-+ answer = NULL;
-+ }
-+ timeout.tv_sec = PGR_RECV_TIMEOUT;
-+ timeout.tv_usec = 0;
-+ FD_ZERO(&rmask);
-+ FD_SET(dest,&rmask);
-+ rtn = select(dest+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+ if (rtn < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+
-+ show_error("%s:select failed ,errno is %s",func ,
strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ else if (rtn && FD_ISSET(dest, &rmask))
-+ {
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ answer = PGRread_packet(dest,&header);
-+ if (answer == NULL)
-+ {
-+ status = STATUS_ERROR;
-+ break;
-+ }
-+ if ((header.cmdSts != CMD_STS_RESPONSE) &&
-+ (header.cmdSts != CMD_STS_NOTICE))
-+ {
-+ show_error("%s:[%c]none response packet
received",func,header.cmdSts);
-+ free(answer);
-+ answer = NULL;
-+ status = STATUS_ERROR;
-+ break;
-+ }
-+ if (answer != NULL)
-+ {
-+ if
(!strncmp(answer,PGR_QUERY_DONE_NOTICE_CMD,strlen(PGR_QUERY_DONE_NOTICE_CMD)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:QUERY DONE",func);
-+#endif
-+ status = STATUS_OK;
-+ }
-+ else if
(!strncmp(answer,PGR_QUERY_ABORTED_NOTICE_CMD,strlen(PGR_QUERY_ABORTED_NOTICE_CMD)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:QUERY ABORTED",func);
-+#endif
-+ status = STATUS_ABORTED;
-+ }
-+ else if
(!strncmp(answer,PGR_LOCK_CONFLICT_NOTICE_CMD,strlen(PGR_LOCK_CONFLICT_NOTICE_CMD)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:LOCK CONFLICT
!!",func);
-+#endif
-+ status = STATUS_LOCK_CONFLICT;
-+ }
-+ else if
(!strncmp(answer,PGR_DEADLOCK_DETECT_NOTICE_CMD,strlen(PGR_DEADLOCK_DETECT_NOTICE_CMD)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:DEADLOCK DETECT
!!",func);
-+#endif
-+ status = STATUS_DEADLOCK_DETECT;
-+ }
-+ free(answer);
-+ answer = NULL;
-+ }
-+ return status;
-+ }
-+ }
-+ return status;
-+}
-+
-+/*--------------------------------------------------
-+ * SYMBOL
-+ * PGRreplicate_packet_send()
-+ * NOTES
-+ * Send query to each cluster DB servers and return result.
-+ * ARGS
-+ * ReplicateHeader * header : packet header (I)
-+ * char * query : query for replication (I)
-+ * int dest : destination socket for return result (I)
-+ * RETURN
-+ * OK : STATUS_OK
-+ * NG : STATUS_ERROR
-+ * DEADLOCK : STATUS_DEADLOCK_DETECT
-+ *---------------------------------------------------
-+ */
-+int
-+PGRreplicate_packet_send( ReplicateHeader * header, char * query,int
dest,int recovery_status) {
-+ return
replicate_packet_send_internal(header,query,dest,recovery_status,false);
-+}
-+
-+
-+int
-+replicate_packet_send_internal(ReplicateHeader * header, char * query,int
dest,int recovery_status,bool isHeldLock)
-+{
-+ char * func = "PGRreplicate_packet_send()";
-+ HostTbl * host_ptr = (HostTbl*)NULL;
-+ HostTbl * source_host_ptr = (HostTbl*)NULL;
-+ int status = STATUS_OK;
-+ int sem_cnt = 0;
-+ int sem_id = 0;
-+ char *database = NULL;
-+ char port[8];
-+ char *userName = NULL;
-+ char * host = NULL;
-+ char result[PGR_MESSAGE_BUFSIZE];
-+
-+ pthread_attr_t attr;
-+ int rc = 0;
-+ int t = 0;
-+ int t_cnt = 0;
-+ int source_t_cnt = -1;
-+ int transaction_count = 0;
-+
-+
-+ pthread_t thread[MAX_DB_SERVER];
-+ ThreadArgInf thread_arg[MAX_DB_SERVER];
-+
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("cmdSts=%c",header->cmdSts);
-+ if(header->cmdType!='\0')
-+ show_debug("cmdType=%c",header->cmdType);
-+ show_debug("rlog=%d",header->rlog);
-+ show_debug("port=%d",ntohs(header->port));
-+ show_debug("pid=%d",ntohs(header->pid));
-+ show_debug("from_host=%s",header->from_host);
-+ show_debug("dbName=%s",header->dbName);
-+ show_debug("userName=%s",header->userName);
-+ show_debug("recieve sec=%u",ntohl(header->tv.tv_sec));
-+ show_debug("recieve usec=%u",ntohl(header->tv.tv_usec));
-+ show_debug("query_size=%d",ntohl(header->query_size));
-+ show_debug("request_id=%d",ntohl(header->request_id));
-+ show_debug("replicate_id=%d",ntohl(header->replicate_id));
-+ if (header->cmdSts != CMD_STS_PREPARE)
-+ {
-+ show_debug("query=%s",query);
-+ }
-+#endif
-+
-+ /* check rlog type */
-+ if (header->rlog == FROM_R_LOG_TYPE)
-+ {
-+ if (is_executed_query_in_origin(header) == false)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("this query is not yet done in source
cluster db. so it wait for receive re-replicate request");
-+#endif
-+ /* wait re-replicate request */
-+ return STATUS_SKIP_REPLICATE;
-+ }
-+ }
-+ /*
-+ * loop while registrated cluster DB exist
-+ */
-+ if (Host_Tbl_Begin == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ host_ptr = Host_Tbl_Begin;
-+ PGR_Response_Inf->current_cluster = 0;
-+ memset(result,0,sizeof(result));
-+ sem_cnt = 1;
-+
-+ if (is_need_queue_jump(header,query) == false)
-+ {
-+ sem_id = SemID;
-+ }
-+ else
-+ {
-+ sem_id = VacuumSemID;
-+ }
-+ if(!isHeldLock) {
-+#ifdef PRINT_DEBUG
-+
-+ show_debug("sem_lock [%d] req",sem_cnt);
-+#endif
-+
-+ PGRsem_lock(sem_id,sem_cnt);
-+#ifdef PRINT_DEBUG
-+ show_debug("sem_lock [%d] got it",sem_cnt);
-+#endif
-+ }
-+ ++*PGR_ReplicateSerializationID;
-+
-+ /* set replication log */
-+ if (is_need_use_rlog(header) == true)
-+ {
-+ PGRset_rlog(header,query);
-+ }
-+
-+ pthread_attr_init(&attr);
-+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-+ PGR_Response_Inf->current_cluster = 0;
-+ t_cnt = 0;
-+ while(host_ptr->useFlag != DB_TBL_END)
-+ {
-+ show_debug("%s:checking host %s for creating
threads",func,host_ptr->hostName);
-+ /*
-+ * check the status of the cluster DB
-+ */
-+ if (host_ptr->useFlag != DB_TBL_USE)
-+ {
-+ host_ptr ++;
-+ continue;
-+ }
-+ /*
-+ * skip loop during recover and the host name is master DB
-+ */
-+ if (is_master_in_recovery(host_ptr->hostName,
host_ptr->port,recovery_status) == true)
-+ {
-+ TransactionTbl *transaction_tbl =
getTransactionTbl(host_ptr,header);
-+ if (host_ptr->transaction_count == 0 ||
-+ transaction_tbl == NULL ||
-+ transaction_tbl->in_transaction == false)
-+ {
-+ if (PGRset_queue(header,query) != STATUS_OK)
-+ {
-+ show_error("%s:failed to put query to
queue.abort to recovery",func);
-+ PGRset_recovery_status(RECOVERY_INIT);
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s master is using for
recovery",func);
-+#endif
-+ host_ptr ++;
-+ continue;
-+ }
-+ }
-+ /*
-+ * compare with the host name and the exceptional host name
-+ */
-+ thread_arg[t_cnt].header = header;
-+ thread_arg[t_cnt].query = query;
-+ thread_arg[t_cnt].dest = dest;
-+ thread_arg[t_cnt].host_ptr = host_ptr;
-+ thread_arg[t_cnt].current_cluster = t_cnt;
-+ thread_arg[t_cnt].transaction_tbl = (TransactionTbl *)NULL;
-+
-+ if
(PGRis_same_host(header->from_host,ntohs(header->port),host_ptr->resolvedName,
host_ptr->port) == true)
-+ {
-+ show_debug("[%d] is same host",t_cnt);
-+ /* replication to source cluster db */
-+ source_host_ptr = host_ptr;
-+ source_t_cnt = t_cnt;
-+
-+ if (header->rlog == FROM_R_LOG_TYPE )
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: This simple query was
suspended. Therefore this query is not re-replicated to source cluster
db.",func);
-+#endif
-+ }
-+ t_cnt++;
-+ }
-+ /* replication to other cluster db */
-+ else
-+ {
-+ show_debug("[%d] is not same host",t_cnt);
-+ if ((header->rlog == CONNECTION_SUSPENDED_TYPE ) &&
-+ (header->cmdSts == CMD_STS_TRANSACTION) )
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: This transaction query was
suspended. Therefore this query is not replicated to other cluster
dbs.",func);
-+#endif
-+ }
-+ else
-+ {
-+ /*
-+ * get the transaction table data
-+ * it has the connection data with each
cluster DB
-+ */
-+ thread_arg[t_cnt].transaction_tbl =
getTransactionTbl(host_ptr,header);
-+ /*
-+ * if the transaction process is new one,
-+ * create connection data and add the
transaction table
-+ */
-+ if (thread_arg[t_cnt].transaction_tbl ==
(TransactionTbl *)NULL)
-+ {
-+ thread_arg[t_cnt].transaction_tbl =
setTransactionTbl(host_ptr, header);
-+ if (thread_arg[t_cnt].transaction_tbl
== (TransactionTbl *)NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+
show_debug("%s:setTransactionTbl failed",func);
-+#endif
-+ if ( header->cmdSts !=
CMD_STS_NOTICE )
-+ {
-+
PGRset_host_status(host_ptr,DB_TBL_ERROR);
-+ }
-+ host_ptr ++;
-+ continue;
-+ }
-+ StartReplication[t_cnt] = true;
-+ }
-+ else
-+ {
-+ /*
-+ * re-use the connection data
-+ */
-+ if
((thread_arg[t_cnt].transaction_tbl->conn != (PGconn *)NULL) &&
-+
(thread_arg[t_cnt].transaction_tbl->conn->sock > 0))
-+ {
-+ /*
-+
memset(thread_arg[t_cnt].transaction_tbl->conn->inBuffer,0,thread_arg[t_cnt].transaction_tbl->conn->inBufSize);
-+
memset(thread_arg[t_cnt].transaction_tbl->conn->outBuffer,0,thread_arg[t_cnt].transaction_tbl->conn->outBufSize);
-+ */
-+ StartReplication[t_cnt] =
false;
-+ }
-+ else
-+ {
-+ if
(thread_arg[t_cnt].transaction_tbl->conn != (PGconn *)NULL)
-+ {
-+
PQfinish(thread_arg[t_cnt].transaction_tbl->conn);
-+
thread_arg[t_cnt].transaction_tbl->conn = NULL;
-+ }
-+
-+ database = (char
*)header->dbName;
-+
snprintf(port,sizeof(port),"%d", host_ptr->port);
-+ userName = (char
*)header->userName;
-+ host = host_ptr->hostName;
-+
-+
thread_arg[t_cnt].transaction_tbl->conn =
pgr_createConn(host,port,database,userName);
-+ StartReplication[t_cnt] =
true;
-+ }
-+ }
-+ check_transaction_status(header, host_ptr,
thread_arg[t_cnt].transaction_tbl);
-+ transaction_count =
thread_arg[t_cnt].transaction_tbl->transaction_count;
-+ rc = pthread_create(&thread[t_cnt], &attr,
thread_send_cluster, (void*)&thread_arg[t_cnt]);
-+
-+ if (rc)
-+ {
-+ show_error("pthread_create error");
-+ }
-+ t_cnt++;
-+ }
-+ }
-+ /*
-+ * send replication query to each cluster server
-+ */
-+
-+ host_ptr++;
-+ PGR_Response_Inf->current_cluster ++;
-+ status = STATUS_OK;
-+ }
-+ pthread_attr_destroy(&attr);
-+ for ( t = 0 ; t < t_cnt; )
-+ {
-+ if (t == source_t_cnt)
-+ {
-+ t++;
-+ continue;
-+ }
-+ rc = pthread_join(thread[t], (void **)NULL);
-+ if ((rc != 0) && (errno == EINTR))
-+ {
-+ usleep(100);
-+ continue;
-+ }
-+ pthread_detach(thread[t]);
-+ t++;
-+ }
-+
-+ thread_arg[source_t_cnt].transaction_count = transaction_count;
-+ /*
-+ * send replication query to source cluster server.
-+ */
-+ if (source_t_cnt >= 0)
-+ {
-+ thread_send_source( (void*)&thread_arg[source_t_cnt]);
-+ }
-+ else
-+ {
-+ show_debug("thread_send_source was not executed");
-+ }
-+ /* unset replication log */
-+ if (is_need_use_rlog(header) == true)
-+ {
-+ PGRunset_rlog(header,query);
-+ }
-+
-+ check_replication_id();
-+ if (header->cmdSts == CMD_STS_PREPARE)
-+ {
-+ if (header->cmdType != CMD_TYPE_P_SYNC)
-+ {
-+ if (PGR_Parse_Session_Started == false)
-+ {
-+ PGR_Parse_Session_Started = true;
-+ }
-+ }
-+ }
-+ else
-+ {
-+ PGR_Parse_Session_Started = false;
-+ }
-+
-+ if(!isHeldLock) {
-+#ifdef PRINT_DEBUG
-+ show_debug("sem_unlock[%d]",sem_cnt);
-+#endif
-+ PGRsem_unlock(sem_id,sem_cnt);
-+ }
-+ return status;
-+}
-+
-+static void *
-+thread_send_source(void * arg)
-+{
-+ char * func = "thread_send_source()";
-+ ThreadArgInf * thread_arg = NULL;
-+ ReplicateHeader * header = (ReplicateHeader*)NULL;
-+ char * query = NULL;
-+ int dest = 0;
-+ HostTbl * host_ptr = (HostTbl*)NULL;
-+ int status = STATUS_OK;
-+ int transaction_count = 0;
-+ char result[PGR_MESSAGE_BUFSIZE];
-+ bool sync_command_flg = false;
-+
-+ if (arg == NULL)
-+ {
-+ show_error("%s:arg is NULL",func);
-+ status = STATUS_ERROR;
-+ pthread_exit((void *) status);
-+ }
-+ thread_arg = (ThreadArgInf *)arg;
-+ header = thread_arg->header;
-+ query = thread_arg->query;
-+ dest = thread_arg->dest;
-+ host_ptr = thread_arg->host_ptr;
-+ transaction_count = thread_arg->transaction_count;
-+
-+ if(header->cmdSts==CMD_STS_OTHER &&
-+ header->cmdType==CMD_TYPE_CONNECTION_CLOSE)
-+ {
-+ return (void *)0;
-+ }
-+
-+ if (header->rlog == FROM_R_LOG_TYPE )
-+ {
-+ /* It is not necessary to return rlog to source DB. */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: It is not necessary to return rlog to source
DB",func);
-+#endif
-+ status = STATUS_OK;
-+ // pthread_exit((void *) status);
-+ return (void *)status;
-+ }
-+
-+ /**
-+ * NOTE:
-+ * We can use PGR_ReplicateSerializationID here , because
-+ * all queries from cluster server isn't recovery query.
-+ *
-+ */
-+ if (is_need_sync_time(header) == true)
-+ {
-+ if (transaction_count >1 )
-+ {
-+ sync_command_flg = false;
-+ }
-+ else
-+ {
-+ sync_command_flg = true;
-+ }
-+ }
-+ if (sync_command_flg == true)
-+ {
-+ snprintf(result,PGR_MESSAGE_BUFSIZE,
-+ "%d,%u,%u,%u,%d,%u",
-+ PGR_SET_CURRENT_TIME_FUNC_NO,
-+ (unsigned int)ntohl(header->tv.tv_sec),
-+ (unsigned int)ntohl(header->tv.tv_usec),
-+ (unsigned int)ntohl(PGR_Log_Header->replicate_id),
-+ PGR_Response_Inf->response_mode,
-+ *PGR_ReplicateSerializationID);
-+ }
-+ else
-+ {
-+ snprintf(result,PGR_MESSAGE_BUFSIZE,
-+ "%d,%u,%u,%d",
-+ PGR_SET_CURRENT_REPLICATION_QUERY_ID_NO,
-+ *PGR_ReplicateSerializationID,
-+ 0,
-+ PGR_Response_Inf->response_mode);
-+ }
-+ /* execute query in the exceptional host */
-+ /* it is not use replication */
-+ if (is_need_wait_answer(header) == true)
-+ {
-+ status = PGRreturn_result(dest,result, PGR_WAIT_ANSWER);
-+ }
-+ else
-+ {
-+ status = PGRreturn_result(dest, result, PGR_NOWAIT_ANSWER);
-+ }
-+
-+ if (status == STATUS_ERROR )
-+ {
-+ show_error("%s: %s[%d] should be down
",func,host_ptr->hostName,host_ptr->port);
-+ PGRset_host_status(host_ptr,DB_TBL_ERROR);
-+ }
-+
-+ /* delete server table when query use template db */
-+ if (PGR_Response_Inf->response_mode != PGR_RELIABLE_MODE)
-+ {
-+ delete_template(host_ptr,header);
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("end thread_send_source()");
-+#endif
-+ return (void *)0;
-+ // pthread_exit((void *) 0);
-+}
-+
-+static void *
-+thread_send_cluster(void * arg)
-+{
-+ char * func = "thread_send_cluster()";
-+ ThreadArgInf * thread_arg = NULL;
-+ ReplicateHeader * header = (ReplicateHeader*)NULL;
-+ char * query = NULL;
-+ int dest = 0;
-+ HostTbl * host_ptr = (HostTbl*)NULL;
-+ int rtn = 0;
-+ int status = STATUS_OK;
-+ TransactionTbl * transaction_tbl = (TransactionTbl *)NULL;
-+ int current_cluster = 0;
-+ char result[PGR_MESSAGE_BUFSIZE];
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("start thread_send_cluster()");
-+#endif
-+ if (arg == NULL)
-+ {
-+ show_error("%s:arg is NULL",func);
-+ status = STATUS_ERROR;
-+ pthread_exit((void *) status);
-+ }
-+
-+ thread_arg = (ThreadArgInf *)arg;
-+ header = thread_arg->header;
-+ query = thread_arg->query;
-+ dest = thread_arg->dest;
-+ host_ptr = thread_arg->host_ptr;
-+ transaction_tbl = thread_arg->transaction_tbl;
-+ current_cluster = thread_arg->current_cluster;
-+
-+
-+ if(header->cmdSts==CMD_STS_OTHER &&
-+ header->cmdType==CMD_TYPE_CONNECTION_CLOSE)
-+ {
-+ check_delete_transaction(host_ptr, header);
-+ return (void *)0;
-+ }
-+
-+
-+ rtn = send_replicate_packet_to_server( transaction_tbl,
current_cluster, host_ptr, header, query ,
result,*PGR_ReplicateSerializationID, false);
-+ show_debug("%s:return value from send_replicate_packet_to_server() is
%d",func,rtn);
-+ if (rtn == STATUS_ABORTED)
-+ {
-+ snprintf(result,PGR_MESSAGE_BUFSIZE,"%d",
PGR_NOTICE_ABORT_FUNC_NO);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:pthread abort[%d]",func,current_cluster );
-+#endif
-+ status = PGRreturn_result(dest, result, PGR_NOWAIT_ANSWER);
-+ status = STATUS_ABORTED;
-+ pthread_exit((void *) status);
-+ }
-+ /* delete server table when query use template db */
-+ delete_template(host_ptr,header);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:pthread_exit[%d]",func,current_cluster );
-+#endif
-+
-+ pthread_exit((void *) 0);
-+}
-+
-+/*--------------------------------------------------
-+ * SYMBOL
-+ * PGRreplicate_packet_send_each_server()
-+ * NOTES
-+ * Send query to a cluster DB server and return result.
-+ * ARGS
-+ * HostTbl * ptr : cluster server info table (I)
-+ * bool return_response : flag for return result(I)
-+ * ReplicateHeader * header: header data (I)
-+ * char * query : query data (I)
-+ * int dest : socket of destination server(I)
-+ * RETURN
-+ * OK : STATUS_OK
-+ * NG : STATUS_ERROR
-+ *---------------------------------------------------
-+ */
-+int
-+PGRreplicate_packet_send_each_server( HostTbl * ptr, bool return_response,
ReplicateHeader * header, char * query,int dest)
-+{
-+ char * func = "PGRreplicate_packet_send_each_server()";
-+ char * host;
-+ int rtn;
-+
-+ host = ptr->hostName;
-+ /*
-+ * send query to cluster DB
-+ */
-+ if (PGR_Result == NULL)
-+ {
-+ show_error("%s:PGR_Result is not initialize",func);
-+ return STATUS_ERROR;
-+ }
-+
-+ rtn = PGRsend_replicate_packet_to_server( ptr,
header,query,PGR_Result, dest, false);
-+
-+ return rtn;
-+}
-+
-+/*--------------------------------------------------
-+ * SYMBOL
-+ * PGRread_packet()
-+ * NOTES
-+ * Read packet data and send the query to each cluster DB.
-+ * The packet data has header data and query data.
-+ * ARGS
-+ * int sock : socket (I)
-+ * ReplicateHeader *header : header data (O)
-+ * RETURN
-+ * OK: pointer of read query
-+ * NG: NULL
-+ *---------------------------------------------------
-+ */
-+char *
-+PGRread_packet(int sock, ReplicateHeader *header)
-+{
-+ char * func = "PGRread_packet()";
-+ int r =0;
-+ int cnt = 0;
-+ char * read_ptr = NULL;
-+ int read_size = 0;
-+ int header_size = 0;
-+ char * query = NULL;
-+ fd_set rmask;
-+ struct timeval timeout;
-+ int rtn;
-+
-+ if (header == NULL)
-+ {
-+ return NULL;
-+ }
-+ memset(header,0,sizeof(ReplicateHeader));
-+ read_ptr = (char*)header;
-+ header_size = sizeof(ReplicateHeader);
-+ cnt = 0;
-+
-+ for (;;){
-+ /*
-+ * read header data
-+ */
-+
-+ timeout.tv_sec = 1;
-+ timeout.tv_usec = 0;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(sock,&rmask);
-+ rtn = select(sock+1, &rmask, (fd_set *)NULL,(fd_set *)NULL,
&timeout);
-+
-+ if (rtn < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+
-+ show_error("%s:select failed ,errno is %s",func ,
strerror(errno));
-+ return NULL;
-+ }
-+
-+ if (rtn && FD_ISSET(sock, &rmask))
-+ {
-+ r = recv(sock,read_ptr + read_size ,header_size -
read_size, MSG_WAITALL);
-+ /*
-+ r = recv(sock,read_ptr + read_size ,header_size -
read_size, 0);
-+ */
-+ if (r < 0)
-+ {
-+ show_debug("%s:recv failed:
(%s)",func,strerror(errno));
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+ else
-+ {
-+ show_error("%s:recv failed:
(%s)",func,strerror(errno));
-+ return NULL;
-+ }
-+ }
-+ else if (r > 0)
-+ {
-+ read_size += r;
-+ if ( read_size == header_size)
-+ {
-+ query = PGRread_query(sock,header);
-+ return query;
-+ }
-+ }
-+ else if (r == 0)
-+ {
-+ return NULL;
-+ }
-+ }
-+ }
-+ return NULL;
-+}
-+
-+char *
-+PGRread_query(int sock, ReplicateHeader *header)
-+{
-+ char * func = "PGRread_query()";
-+ int r =0;
-+ int cnt = 0;
-+ char * read_ptr;
-+ int read_size = 0;
-+ int query_size = 0;
-+ char * query = NULL;
-+
-+ query_size = ntohl(header->query_size);
-+ if (query_size < 0)
-+ {
-+ show_error("%s:receive size less than 0",func);
-+ return NULL;
-+ }
-+ query = malloc(query_size+4);
-+ if (query == NULL)
-+ {
-+ /*
-+ * buffer allocation failed
-+ */
-+ show_error("%s:malloc failed: (%s)",func,strerror(errno));
-+ return NULL;
-+ }
-+ memset(query,0,query_size+4);
-+ if (query_size == 0)
-+ {
-+ return query;
-+ }
-+ read_size = 0;
-+ cnt = 0;
-+ read_ptr = (char *)query;
-+ for (;;)
-+ {
-+ /*
-+ * read query data
-+ */
-+
-+ /*r = recv(sock,read_ptr + read_size ,query_size - read_size,
MSG_WAITALL); */
-+ r = recv(sock,read_ptr + read_size ,query_size - read_size,
0);
-+ if (r < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+ else
-+ {
-+ show_error("%s:recv failed:
(%s)",func,strerror(errno));
-+ free(query);
-+ query = NULL;
-+ return NULL;
-+ }
-+ }
-+ else if (r > 0)
-+ {
-+ read_size += r;
-+ if ( read_size == query_size)
-+ {
-+ return query;
-+ }
-+ }
-+ else /* r == 0 */
-+ {
-+ show_error("%s:unexpected EOF", func);
-+ free(query);
-+ query = NULL;
-+ return NULL;
-+ }
-+ }
-+ free(query);
-+ query = NULL;
-+ return NULL;
-+}
-+
-+static bool
-+is_autocommit_off(char * query)
-+{
-+ int i;
-+ char buf[256];
-+ char * p = NULL;
-+
-+ if (query == NULL)
-+ return false;
-+ memset(buf,0,sizeof(buf));
-+ p = query;
-+ i = 0;
-+ while ( *p != '\0' )
-+ {
-+ buf[i++] = toupper(*p);
-+ p++;
-+ if (i >= (sizeof(buf) -2))
-+ break;
-+ }
-+ p = strstr(buf,"AUTOCOMMIT");
-+ if ( p == NULL)
-+ {
-+ return false;
-+ }
-+ p = strstr(buf,"OFF");
-+ if ( p == NULL )
-+ {
-+ return false;
-+ }
-+ return true;
-+}
-+
-+static bool
-+is_autocommit_on(char * query)
-+{
-+ int i;
-+ char buf[256];
-+ char * p = NULL;
-+
-+ if (query == NULL)
-+ return false;
-+ memset(buf,0,sizeof(buf));
-+ p = query;
-+ i = 0;
-+ while ( *p != '\0' )
-+ {
-+ buf[i++] = toupper(*p);
-+ p++;
-+ if (i >= (sizeof(buf) -2))
-+ break;
-+ }
-+ p = strstr(buf,"AUTOCOMMIT");
-+ if ( p == NULL)
-+ {
-+ return false;
-+ }
-+ p = strstr(buf,"ON");
-+ if ( p == NULL )
-+ {
-+ return false;
-+ }
-+ return true;
-+}
-+
-+static unsigned int
-+get_host_ip_from_tbl(char * host)
-+{
-+ Dlelem * ptr = NULL;
-+
-+ pthread_mutex_lock(&transaction_table_mutex);
-+ if (Transaction_Tbl_Begin == NULL)
-+ {
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+ return 0;
-+ }
-+ ptr = DLGetHead(Transaction_Tbl_Begin);
-+ while (ptr)
-+ {
-+ TransactionTbl *transaction = DLE_VAL(ptr);
-+ if
(!strncmp(transaction->host,host,sizeof(transaction->host)))
-+ {
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+ return transaction->hostIP;
-+ }
-+ ptr = DLGetSucc(ptr);
-+ }
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+
-+ return 0;
-+}
-+
-+static unsigned int
-+get_srcHost_ip_from_tbl(char * srcHost)
-+{
-+ Dlelem * ptr = NULL;
-+
-+ pthread_mutex_lock(&transaction_table_mutex);
-+
-+ if (Transaction_Tbl_Begin == NULL)
-+ {
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+
-+ return 0;
-+ }
-+ ptr = DLGetHead(Transaction_Tbl_Begin);
-+ while (ptr)
-+ {
-+ TransactionTbl *transaction = DLE_VAL(ptr);
-+ if
(!strncmp(transaction->srcHost,srcHost,sizeof(transaction->srcHost)))
-+ {
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+
-+ return transaction->srcHostIP;
-+ }
-+ ptr = DLGetSucc(ptr);
-+ }
-+ pthread_mutex_unlock(&transaction_table_mutex);
-+
-+ return 0;
-+}
-+
-+unsigned int
-+PGRget_next_query_id(void)
-+{
-+ if (PGR_Query_ID >= PGR_MAX_QUERY_ID)
-+ {
-+ PGR_Query_ID = 0;
-+ }
-+ PGR_Query_ID ++;
-+ return PGR_Query_ID;
-+}
-+
-+
-+void
-+PGRnotice_replication_server(char * hostName, unsigned short
portNumber,unsigned short recoveryPortNumber, unsigned short
lifecheckPortNumber, char * userName)
-+{
-+ char * func ="PGRnotice_replication_server()";
-+ ReplicateHeader header;
-+ char query[PGR_MESSAGE_BUFSIZE];
-+
-+ if (((hostName == NULL) || (*hostName == 0)) ||
-+ ((userName == NULL) || (*userName == 0)) ||
-+ ((portNumber == 0) || (recoveryPortNumber == 0)))
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: can not connect
server[%s][%s][%d][%d]",func,hostName,userName,portNumber,recoveryPortNumber);
-+#endif
-+ return;
-+ }
-+ memset(&header,0,sizeof(ReplicateHeader));
-+ memset(query,0,sizeof(query));
-+ snprintf(query,sizeof(query)-1,"SELECT %s(%d,'%s',%d,%d,%d)",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_STARTUP_REPLICATION_SERVER_FUNC_NO,
-+ hostName,
-+ portNumber,
-+ recoveryPortNumber,
-+ lifecheckPortNumber);
-+ header.cmdSys = CMD_SYS_CALL;
-+ header.cmdSts = CMD_STS_NOTICE;
-+ header.query_size = htonl(strlen(query));
-+ header.query_id = htonl(PGRget_next_query_id());
-+ strncpy(header.from_host,hostName,sizeof(header.from_host));
-+ strncpy(header.userName,userName,sizeof(header.userName));
-+ strcpy(header.dbName,"template1");
-+ PGRreplicate_packet_send( &header, query, NOTICE_SYSTEM_CALL_TYPE
,RECOVERY_INIT);
-+}
-+
-+static bool
-+is_need_use_rlog(ReplicateHeader * header)
-+{
-+ bool rtn = false;
-+ if ((Cascade_Inf->useFlag != DB_TBL_USE) ||
-+ (PGR_Use_Replication_Log != true) ||
-+ (header->rlog > 0))
-+ {
-+ rtn=false;
-+ }
-+ else if ((header->cmdSts == CMD_STS_QUERY ) &&
-+ ((header->cmdType == CMD_TYPE_INSERT) ||
-+ (header->cmdType == CMD_TYPE_UPDATE) ||
-+ (header->cmdType == CMD_TYPE_DELETE) ||
-+ (header->cmdType == CMD_TYPE_EXECUTE)))
-+ {
-+ rtn = true;
-+ }
-+ else
-+ {
-+ if ((header->cmdSts == CMD_STS_TRANSACTION ) &&
-+ (header->cmdType == CMD_TYPE_COMMIT))
-+ {
-+ rtn = true;
-+ }
-+ }
-+ return rtn;
-+}
-+
-+
-+
-+int
-+PGRinit_transaction_table(void)
-+{
-+ if (Transaction_Tbl_Begin != NULL)
-+ {
-+ DLFreeList(Transaction_Tbl_Begin);
-+ }
-+
-+ Transaction_Tbl_Begin = DLNewList();
-+
-+ return STATUS_OK;
-+}
-+
-+
-+static bool
-+is_need_queue_jump( ReplicateHeader * header,char *query)
-+{
-+ if (header == NULL)
-+ {
-+ return true;
-+ }
-+
-+ if (header->cmdSts == CMD_STS_QUERY)
-+ {
-+ if ((header->cmdType == CMD_TYPE_VACUUM ) ||
-+ (header->cmdType == CMD_TYPE_ANALYZE ))
-+ {
-+ if ((strstr(query,"full") == NULL) &&
-+ (strstr(query,"FULL") == NULL))
-+ {
-+ return true;
-+ }
-+ }
-+ }
-+ return false;
-+}
-+
-+
-+static bool
-+is_executed_query_in_origin( ReplicateHeader *header )
-+{
-+ char *database = NULL;
-+ char port[8];
-+ char *userName = NULL;
-+ char * host = NULL;
-+ HostTbl * host_ptr = (HostTbl*)NULL;
-+ TransactionTbl * transaction_tbl = (TransactionTbl*)NULL;
-+ PGconn * conn = (PGconn *)NULL;
-+ bool result = false;
-+
-+ if (Host_Tbl_Begin == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ host_ptr = Host_Tbl_Begin;
-+ while(host_ptr->useFlag != DB_TBL_END)
-+ {
-+ /*
-+ * check the status of the cluster DB
-+ */
-+ if (host_ptr->useFlag != DB_TBL_USE)
-+ {
-+ host_ptr ++;
-+ continue;
-+ }
-+ if
(PGRis_same_host(header->from_host,ntohs(header->port),host_ptr->hostName,
host_ptr->port) == true)
-+ {
-+ break;
-+ }
-+ host_ptr ++;
-+ }
-+ if (host_ptr->useFlag == DB_TBL_END)
-+ {
-+ return false;
-+ }
-+ /*
-+ * set up the connection
-+ */
-+ transaction_tbl = getTransactionTbl(host_ptr,header);
-+ if (transaction_tbl == (TransactionTbl *)NULL)
-+ {
-+ transaction_tbl = setTransactionTbl(host_ptr, header);
-+ if (transaction_tbl == (TransactionTbl *)NULL)
-+ {
-+ return false;
-+ }
-+ }
-+ else
-+ {
-+ if ((transaction_tbl->conn == (PGconn *)NULL) ||
-+ (transaction_tbl->conn->sock <= 0))
-+ {
-+ database = (char *)header->dbName;
-+ snprintf(port,sizeof(port),"%d", host_ptr->port);
-+ userName = (char *)header->userName;
-+ host = host_ptr->hostName;
-+ transaction_tbl->conn =
pgr_createConn(host,port,database,userName);
-+ }
-+ }
-+ conn = transaction_tbl->conn;
-+ if (conn == NULL)
-+ {
-+ return false;
-+ }
-+
-+ result = is_executed_query( conn, header);
-+ deleteTransactionTbl(host_ptr,header);
-+ return result;
-+}
-+
-+
-+static bool
-+is_executed_query( PGconn *conn, ReplicateHeader * header)
-+{
-+ char * func = "is_executed_query()";
-+ static PGresult * res = (PGresult *)NULL;
-+ char sync_command[PGR_MESSAGE_BUFSIZE];
-+ char * str = NULL;
-+
-+ snprintf(sync_command,sizeof(sync_command),
-+ "SELECT %s(%d,%u,%u,%u,%d) ",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_QUERY_CONFIRM_ANSWER_FUNC_NO,
-+ (unsigned int)ntohl(header->tv.tv_sec),
-+ (unsigned int)ntohl(header->tv.tv_usec),
-+ (unsigned int)ntohl(header->replicate_id),
-+ PGR_Response_Inf->response_mode);
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command(%s)",func,sync_command);
-+#endif
-+ res = PQexec(conn, sync_command);
-+ if (res != NULL)
-+ {
-+ str = PQcmdStatus(res);
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PQcmdStatus return[%s]",func,str);
-+#endif
-+ if ((str != NULL) &&
-+
(!strncmp(str,PGR_ALREADY_REPLICATED_NOTICE_CMD,strlen(PGR_ALREADY_REPLICATED_NOTICE_CMD))))
-+ {
-+ PQclear(res);
-+ return true;
-+ }
-+ PQclear(res);
-+
-+ }
-+ return false;
-+}
-+
-+static int
-+replicate_lo( PGconn * conn, ReplicateHeader * header, LOArgs * query)
-+{
-+ int status = STATUS_OK;
-+ int mode = 0;
-+ Oid lobjId = 0;
-+ int fd = 0;
-+ char * buf = NULL;
-+ char * filename = NULL;
-+ size_t len = 0;
-+ int offset = 0;
-+ int whence = 0;
-+
-+ if ((conn == (PGconn *)NULL) || (query == (LOArgs *)NULL) || (header
== (ReplicateHeader *)NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ switch (header->cmdType)
-+ {
-+ case CMD_TYPE_LO_IMPORT :
-+ filename = query->buf;
-+ if (lo_import(conn, filename) > 0 )
-+ {
-+ status = STATUS_OK;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_LO_CREATE :
-+ mode = (int)ntohl(query->arg1);
-+ if (lo_creat(conn, mode) > 0)
-+ {
-+ status = STATUS_OK;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_LO_OPEN :
-+ lobjId = (Oid)ntohl(query->arg1);
-+ mode = (int)ntohl(query->arg2);
-+ if (lo_open(conn, lobjId, mode) > 0)
-+ {
-+ status = STATUS_OK;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_LO_WRITE :
-+ fd = (int)ntohl(query->arg1);
-+ len = (int)ntohl(query->arg2);
-+ buf = query->buf;
-+ if (lo_write(conn, fd, buf, len) == len )
-+ {
-+ status = STATUS_OK;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_LO_LSEEK :
-+ fd = (int)ntohl(query->arg1);
-+ offset = (int)ntohl(query->arg2);
-+ whence = (int)ntohl(query->arg3);
-+ if (lo_lseek(conn, fd, offset, whence) >= 0)
-+ {
-+ status = STATUS_OK;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_LO_CLOSE :
-+ fd = (int)ntohl(query->arg1);
-+ if (lo_close(conn, fd) == 0)
-+ {
-+ status = STATUS_OK;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ break;
-+ case CMD_TYPE_LO_UNLINK :
-+ lobjId = (Oid)ntohl(query->arg1);
-+ if (lo_unlink(conn,lobjId) >= 0)
-+ {
-+ status = STATUS_OK;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ break;
-+ default :
-+ break;
-+ }
-+ return status;
-+}
-+
-+static int
-+send_func(HostTbl * host_ptr,ReplicateHeader * header, char * func,char *
result)
-+{
-+ char * f ="send_func()";
-+ char *database = NULL;
-+ char port[8];
-+ char *userName = NULL;
-+ char * host = NULL;
-+ char * str = NULL;
-+ TransactionTbl * transaction_tbl = (TransactionTbl *)NULL;
-+ PGresult * res = (PGresult *)NULL;
-+ PGconn * conn = (PGconn *)NULL;
-+ int rtn = 0;
-+ int current_cluster = 0;
-+
-+ if ((host_ptr == (HostTbl *)NULL) ||
-+ (header == (ReplicateHeader *)NULL) ||
-+ (func == NULL) ||
-+ (result == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ /*
-+ * set up the connection
-+ */
-+ database = (char *)header->dbName;
-+ snprintf(port,sizeof(port),"%d", host_ptr->port);
-+ userName = (char *)header->userName;
-+ host = host_ptr->hostName;
-+ if (PGR_Response_Inf != NULL)
-+ {
-+ current_cluster = PGR_Response_Inf->current_cluster;
-+ }
-+
-+ /*
-+ * get the transaction table data
-+ * it has the connection data with each cluster DB
-+ */
-+ transaction_tbl = getTransactionTbl(host_ptr,header);
-+ /*
-+ * if the transaction process is new one,
-+ * create connection data and add the transaction table
-+ */
-+ if (transaction_tbl == (TransactionTbl *)NULL)
-+ {
-+ transaction_tbl = setTransactionTbl(host_ptr, header);
-+ if (transaction_tbl == (TransactionTbl *)NULL)
-+ {
-+ StartReplication[current_cluster] = true;
-+ show_error("%s:setTransactionTbl failed",f);
-+ if ( header->cmdSts != CMD_STS_NOTICE )
-+ {
-+ PGRset_host_status(host_ptr,DB_TBL_ERROR);
-+ }
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else
-+ {
-+ /*
-+ * re-use the connection data
-+ */
-+ if ((transaction_tbl->conn != (PGconn *)NULL) &&
-+ (transaction_tbl->conn->sock > 0))
-+ {
-+ StartReplication[current_cluster] = false;
-+ }
-+ else
-+ {
-+ if (transaction_tbl->conn != (PGconn *)NULL)
-+ {
-+ PQfinish(transaction_tbl->conn);
-+ }
-+ transaction_tbl->conn =
pgr_createConn(host,port,database,userName);
-+ StartReplication[current_cluster] = true;
-+ }
-+ }
-+ conn = transaction_tbl->conn;
-+
-+ if (conn == NULL)
-+ {
-+ show_error("%s:[%d@%s] may be
down",f,host_ptr->port,host_ptr->hostName);
-+ if ( header->cmdSts != CMD_STS_NOTICE )
-+ {
-+ StartReplication[current_cluster] = true;
-+ PGRset_host_status(host_ptr,DB_TBL_ERROR);
-+ }
-+ return STATUS_ERROR;
-+ }
-+ res = PQexec(conn, func);
-+ if (res == NULL)
-+ {
-+ StartReplication[current_cluster] = true;
-+ return STATUS_ERROR;
-+ }
-+ str = PQcmdStatus(res);
-+ if ((str == NULL) || (*str == '\0'))
-+ {
-+ rtn = STATUS_ERROR;
-+ }
-+ else
-+ {
-+ snprintf(result, PGR_MESSAGE_BUFSIZE, "%s",str);
-+ rtn = STATUS_OK;
-+ }
-+ if (res != NULL)
-+ PQclear(res);
-+ return rtn;
-+}
-+
-+static uint32_t
-+get_oid(HostTbl * host_ptr,ReplicateHeader * header)
-+{
-+ char * func = "get_oid()";
-+ char sync_command[PGR_MESSAGE_BUFSIZE];
-+ char result[PGR_MESSAGE_BUFSIZE];
-+
-+ memset(result,0,sizeof(result));
-+ snprintf(sync_command,sizeof(sync_command),
-+ "SELECT %s(%d)",
-+ PGR_SYSTEM_COMMAND_FUNC, PGR_GET_OID_FUNC_NO);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command(%s)",func,sync_command);
-+#endif
-+
-+ if (send_func(host_ptr, header, sync_command, result) == STATUS_OK)
-+ {
-+ return (strtoul(result, NULL, 10));
-+ }
-+ return 0;
-+}
-+
-+static int
-+set_oid(HostTbl * host_ptr,ReplicateHeader * header, uint32_t oid)
-+{
-+ char * func = "set_oid()";
-+ char sync_command[PGR_MESSAGE_BUFSIZE];
-+ char result[PGR_MESSAGE_BUFSIZE];
-+
-+ memset(result,0,sizeof(result));
-+ snprintf(sync_command,sizeof(sync_command),
-+ "SELECT %s(%d,%u)",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_SET_OID_FUNC_NO,
-+ oid);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command(%s)",func,sync_command);
-+#endif
-+ return ( send_func(host_ptr, header, sync_command, result) );
-+}
-+
-+/*
-+ * sync oid during cluster DB's
-+ */
-+int
-+PGRsync_oid(ReplicateHeader *header)
-+{
-+ HostTbl * host_ptr = (HostTbl*)NULL;
-+ uint32_t max_oid = 0;
-+ uint32_t oid = 0;
-+ int recovery_status = 0;
-+
-+ /* get current oid of all cluster db's */
-+ host_ptr = Host_Tbl_Begin;
-+ if (host_ptr == (HostTbl *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ recovery_status = PGRget_recovery_status();
-+ while(host_ptr->useFlag != DATA_END)
-+ {
-+ /*
-+ * check the status of the cluster DB
-+ */
-+ if (host_ptr->useFlag != DATA_USE)
-+ {
-+ host_ptr ++;
-+ continue;
-+ }
-+ /*
-+ * skip loop during recover and the host name is master DB
-+ */
-+ if (is_master_in_recovery(host_ptr->hostName,
host_ptr->port,recovery_status) == true)
-+ {
-+ host_ptr ++;
-+ continue;
-+ }
-+ oid = get_oid(host_ptr,header);
-+ if (max_oid < oid )
-+ {
-+ max_oid = oid;
-+ }
-+ host_ptr ++;
-+ }
-+ if (max_oid <= 0)
-+ return STATUS_ERROR;
-+
-+ /* set oid in cluster db */
-+ host_ptr = Host_Tbl_Begin;
-+ while(host_ptr->useFlag != DATA_END)
-+ {
-+ /*
-+ * check the status of the cluster DB
-+ */
-+ if (host_ptr->useFlag != DATA_USE)
-+ {
-+ host_ptr ++;
-+ continue;
-+ }
-+ /*
-+ * skip loop during recover and the host name is master DB
-+ */
-+ if (is_master_in_recovery(host_ptr->hostName,
host_ptr->port,recovery_status) == true)
-+ {
-+ host_ptr ++;
-+ continue;
-+ }
-+ set_oid(host_ptr,header,max_oid);
-+ host_ptr ++;
-+ }
-+
-+ return STATUS_OK;
-+}
-+
-+int
-+PGRload_replication_id(void)
-+{
-+ char * func = "PGRload_replication_id()";
-+ char buf[256];
-+ char *p;
-+
-+ if (Recovery_Status_Inf == (RecoveryStatusInf *)NULL)
-+ {
-+ show_error("%s: Recovery_Status_Inf is NULL",func);
-+ return STATUS_ERROR;
-+ }
-+ if (RidFp == (FILE *)NULL)
-+ {
-+ show_error("%s: replication id file is not open",func);
-+ return STATUS_ERROR;
-+ }
-+ rewind(RidFp);
-+ if (fgets(buf,sizeof(buf),RidFp) == NULL)
-+ {
-+ show_debug(" replication id file is empty");
-+ Recovery_Status_Inf->replication_id = 0;
-+ }
-+ else
-+ {
-+ p = strrchr(buf,' ');
-+ if (p != NULL)
-+ {
-+ p++;
-+ Recovery_Status_Inf->replication_id = (uint32_t)
atol(p);
-+ show_debug(" set replication id
[%u]",Recovery_Status_Inf->replication_id);
-+ }
-+ else
-+ {
-+ Recovery_Status_Inf->replication_id = 0;
-+ show_debug("no replicationid in this file");
-+ }
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+notice_abort(HostTbl * host_ptr,ReplicateHeader * header)
-+{
-+ char * func = "PGR_Notice_Abort()";
-+ char sync_command[PGR_MESSAGE_BUFSIZE];
-+ char result[PGR_MESSAGE_BUFSIZE];
-+
-+ memset(result,0,sizeof(result));
-+ snprintf(sync_command,sizeof(sync_command),
-+ "SELECT %s(%d)",
-+ PGR_SYSTEM_COMMAND_FUNC,
-+ PGR_NOTICE_ABORT_FUNC_NO);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:sync_command(%s)",func,sync_command);
-+#endif
-+ return ( send_func(host_ptr, header, sync_command, result) );
-+}
-+
-+static int
-+send_p_parse (PGconn * conn, StringInfo input_message)
-+{
-+ const char *stmt_name;
-+ const char *query_string;
-+ int numParams;
-+ Oid paramTypes;
-+
-+ /* get name,query */
-+ stmt_name = pq_getmsgstring(input_message);
-+ query_string = pq_getmsgstring(input_message);
-+ /* send name,query */
-+ if (pqPutMsgStart('P', false, conn) < 0 ||
-+ pqPuts(stmt_name, conn) < 0 ||
-+ pqPuts(query_string, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ /* get number of parameter */
-+ numParams = pq_getmsgint(input_message, 2);
-+ /* send number of parameter */
-+ if (pqPutInt(numParams, 2, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (numParams > 0)
-+ {
-+ int i;
-+ for (i = 0; i < numParams; i++)
-+ {
-+ paramTypes = pq_getmsgint(input_message, 4);
-+ if (pqPutInt(paramTypes, 4, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ }
-+ if (pqPutMsgEnd(conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+send_p_bind (PGconn * conn, StringInfo input_message)
-+{
-+ const char *portal_name;
-+ const char *stmt_name;
-+ int numPFormats;
-+ int16 pformats;
-+ int numParams;
-+ int numRFormats;
-+ int16 rformats;
-+ int i;
-+
-+ /* Get&Send the fixed part of the message */
-+ portal_name = pq_getmsgstring(input_message);
-+ stmt_name = pq_getmsgstring(input_message);
-+ if (pqPutMsgStart('B', false, conn) < 0 ||
-+ pqPuts(portal_name, conn) < 0 ||
-+ pqPuts(stmt_name, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ /* Get&Send the parameter format codes */
-+ numPFormats = pq_getmsgint(input_message, 2);
-+ if (pqPutInt(numPFormats, 2, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (numPFormats > 0)
-+ {
-+ for (i = 0; i < numPFormats; i++)
-+ {
-+ pformats = pq_getmsgint(input_message, 2);
-+ if (pqPutInt(pformats, 2, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ }
-+
-+ /* Get&Send the parameter value count */
-+ numParams = pq_getmsgint(input_message, 2);
-+ if (pqPutInt(numParams, 2, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (numParams > 0)
-+ {
-+ int32 plength;
-+ for (i = 0 ; i < numParams ; i ++)
-+ {
-+ plength = pq_getmsgint(input_message, 4);
-+ if (plength != -1)
-+ {
-+ const char *pvalue =
pq_getmsgbytes(input_message, plength);
-+ if (pqPutInt(plength, 4, conn) < 0 ||
-+ pqPutnchar(pvalue, plength, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else
-+ {
-+ if (pqPutInt(plength, 4, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Get&Send the result format codes */
-+ numRFormats = pq_getmsgint(input_message, 2);
-+ if (pqPutInt(numRFormats, 2, conn) < 0 )
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (numRFormats > 0)
-+ {
-+ for (i = 0; i < numRFormats; i++)
-+ {
-+ rformats = pq_getmsgint(input_message, 2);
-+ if (pqPutInt(rformats, 2, conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ }
-+ }
-+ if (pqPutMsgEnd(conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+send_p_describe (PGconn * conn, StringInfo input_message)
-+{
-+
-+ int describe_type;
-+ const char *describe_target;
-+
-+ describe_type = pq_getmsgbyte(input_message);
-+ describe_target = pq_getmsgstring(input_message);
-+
-+ /* construct the Describe Portal message */
-+ if (pqPutMsgStart('D', false, conn) < 0 ||
-+ pqPutc(describe_type, conn) < 0 ||
-+ pqPuts(describe_target, conn) < 0 ||
-+ pqPutMsgEnd(conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+send_p_execute (PGconn * conn, StringInfo input_message)
-+{
-+ const char *portal_name;
-+ int max_rows;
-+
-+ portal_name = pq_getmsgstring(input_message);
-+ max_rows = pq_getmsgint(input_message, 4);
-+ /* construct the Execute message */
-+ if (pqPutMsgStart('E', false, conn) < 0 ||
-+ pqPuts(portal_name, conn) < 0 ||
-+ pqPutInt(max_rows, 4, conn) < 0 ||
-+ pqPutMsgEnd(conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+send_p_sync (PGconn * conn, StringInfo input_message)
-+{
-+ PGresult *result;
-+ PGresult *lastResult;
-+
-+ /* construct the Sync message */
-+ if (pqPutMsgStart('S', false, conn) < 0 ||
-+ pqPutMsgEnd(conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ /* remember we are using extended query protocol */
-+ conn->queryclass = PGQUERY_EXTENDED;
-+
-+ /*
-+ * Give the data a push. In nonblock mode, don't complain if we're
unable
-+ * to send it all; PQgetResult() will do any additional flushing
needed.
-+ */
-+ if (pqFlush(conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ /* OK, it's launched! */
-+ conn->asyncStatus = PGASYNC_BUSY;
-+
-+ lastResult = NULL;
-+ while ((result = PQgetResult(conn)) != NULL)
-+ {
-+ if (lastResult)
-+ {
-+ if (lastResult->resultStatus == PGRES_FATAL_ERROR &&
-+ result->resultStatus == PGRES_FATAL_ERROR)
-+ {
-+ PQclear(result);
-+ result = lastResult;
-+ }
-+ else
-+ PQclear(lastResult);
-+ }
-+ lastResult = result;
-+ if (result->resultStatus == PGRES_COPY_IN ||
-+ result->resultStatus == PGRES_COPY_OUT ||
-+ conn->status == CONNECTION_BAD)
-+ break;
-+ }
-+ if (lastResult != NULL)
-+ {
-+ PQclear(lastResult);
-+ }
-+ return STATUS_OK;
-+}
-+
-+static int
-+send_p_close (PGconn * conn, StringInfo input_message)
-+{
-+
-+ int close_type;
-+ const char *close_target;
-+
-+ close_type = pq_getmsgbyte(input_message);
-+ close_target = pq_getmsgstring(input_message);
-+ if (pqPutMsgStart('C', false, conn) < 0 ||
-+ pqPutc(close_type, conn) < 0 ||
-+ pqPuts(close_target, conn) < 0 ||
-+ pqPutMsgEnd(conn) < 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ return STATUS_OK;
-+}
-+static void
-+set_string_info(StringInfo input_message, ReplicateHeader * header, char *
query)
-+{
-+ int len;
-+ len = ntohl(header->query_size);
-+ input_message->data = query;
-+ input_message->maxlen = len;
-+ input_message->len = len -1;
-+ input_message->cursor = 0;
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/pgrp/rlog.c
pgcluster-1.5.0rc7/src/pgcluster/pgrp/rlog.c
---- postgresql-8.1.2/src/pgcluster/pgrp/rlog.c 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/pgrp/rlog.c 2006-01-31
23:47:23.000000000 +0100
-@@ -0,0 +1,1288 @@
-+/*--------------------------------------------------------------------
-+ * FILE:
-+ * rlog.c
-+ *
-+ * NOTE:
-+ * This file is composed of the functions to call with the source
-+ * at pgreplicate for replicate ahead log.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ *--------------------------------------------------------------------
-+ */
-+#ifdef USE_REPLICATION
-+
-+#include "postgres.h"
-+#include "postgres_fe.h"
-+
-+#include <stdio.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/un.h>
-+#include <unistd.h>
-+#ifdef HAVE_FCNTL_H
-+#include <fcntl.h>
-+#endif
-+#include <errno.h>
-+#include <ctype.h>
-+#include <time.h>
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <sys/sem.h>
-+#include <sys/msg.h>
-+#include <signal.h>
-+#include <sys/socket.h>
-+#include <netdb.h>
-+#ifdef HAVE_NETINET_TCP_H
-+#include <netinet/tcp.h>
-+#endif
-+#include <dirent.h>
-+#include <arpa/inet.h>
-+
-+#ifdef HAVE_CRYPT_H
-+#include <crypt.h>
-+#endif
-+
-+#ifdef MULTIBYTE
-+#include "mb/pg_wchar.h"
-+#endif
-+
-+#include "libpq-fe.h"
-+#include "libpq-int.h"
-+#include "fe-auth.h"
-+#include "access/xact.h"
-+#include "replicate_com.h"
-+#include "pgreplicate.h"
-+
-+int RLog_Recv_Sock = -1;
-+/*--------------------------------------
-+ * PROTOTYPE DECLARATION
-+ *--------------------------------------
-+ */
-+int PGRwrite_rlog(ReplicateHeader * header, char * query);
-+ReplicateHeader * PGRget_requested_query(ReplicateHeader * header);
-+void PGRreconfirm_commit(int sock, ReplicateHeader * header);
-+void PGRset_rlog(ReplicateHeader * header, char * query);
-+void PGRunset_rlog(ReplicateHeader * header, char * query);
-+int PGRresend_rlog_to_db(void);
-+pid_t PGR_RLog_Main(void);
-+int PGRcreate_send_rlog_socket(void);
-+int PGRget_sync_data(ReplicateHeader *header);
-+int PGRdelete_sync_data(ReplicateHeader *header);
-+int PGRsend_rlog_packet(int sock,ReplicateHeader * header, const char *
query_string);
-+int PGRrecv_rlog_result(int sock,void * result, int size);
-+int PGRsend_rlog_to_local(ReplicateHeader * header,char * query);
-+int PGRget_rlog_header(ReplicateHeader * header);
-+
-+static int set_query_log(ReplicateHeader * header, char * query);
-+static QueryLogType * get_query_log_by_header(ReplicateHeader * header);
-+static QueryLogType * get_query_log(ReplicateHeader * header);
-+static void delete_query_log(ReplicateHeader * header);
-+static int set_commit_log(ReplicateHeader * header);
-+static CommitLogInf * get_commit_log(ReplicateHeader * header);
-+static void delete_commit_log(ReplicateHeader * header);
-+static bool was_committed_transaction(ReplicateHeader * header);
-+static int create_recv_rlog_socket(void);
-+static int do_rlog(int fd);
-+static int recv_message(int sock,char * buf, int len);
-+static int send_message(int sock, char * msg, int len);
-+static void exit_rlog(int sig);
-+static int reconfirm_commit(ReplicateHeader * header);
-+
-+
-+int
-+PGRwrite_rlog(ReplicateHeader * header, char * query)
-+{
-+ char * func = "PGRwrite_rlog()";
-+
-+ if (header == NULL)
-+ {
-+ show_error("%s:header is null",func);
-+ return STATUS_ERROR;
-+ }
-+ switch (header->cmdSts)
-+ {
-+ case CMD_STS_QUERY:
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:set_query_log",func);
-+#endif
-+ set_query_log(header,query);
-+ break;
-+ case CMD_STS_DELETE_QUERY:
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:delete_query_log",func);
-+#endif
-+ delete_query_log(header);
-+ break;
-+ case CMD_STS_TRANSACTION:
-+ if (header->cmdType == CMD_TYPE_COMMIT)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:set_commit_log call",func);
-+#endif
-+ set_commit_log(header);
-+ }
-+ break;
-+ case CMD_STS_DELETE_TRANSACTION:
-+ if (header->cmdType == CMD_TYPE_COMMIT)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:delete_commit_log call",func);
-+#endif
-+ delete_commit_log(header);
-+ }
-+ break;
-+ default:
-+ show_error("%s:unknown status %c",func,header->cmdSts);
-+ break;
-+ }
-+ return STATUS_OK;
-+}
-+
-+ReplicateHeader *
-+PGRget_requested_query(ReplicateHeader * header)
-+{
-+ QueryLogType * query_log = NULL;
-+
-+ if (Query_Log_Top == NULL)
-+ {
-+ return NULL;
-+ }
-+ query_log = Query_Log_Top;
-+ while(query_log != (QueryLogType *)NULL)
-+ {
-+ if ((query_log->header->request_id == header->request_id) &&
-+ (query_log->header->pid == header->pid) &&
-+ (query_log->header->port == header->port) &&
-+
(!strncmp(query_log->header->from_host,header->from_host,sizeof(header->from_host))))
-+ {
-+ return query_log->header;
-+ }
-+ query_log = (QueryLogType *)(query_log->next);
-+ }
-+ return (ReplicateHeader *)NULL;
-+}
-+
-+static int
-+set_query_log(ReplicateHeader * header, char * query)
-+{
-+ char * func = "set_query_log()";
-+ int size = 0;
-+ QueryLogType * query_log = NULL;
-+
-+ if (Query_Log_Top == NULL)
-+ {
-+ Query_Log_Top = (QueryLogType *)malloc(sizeof(QueryLogType));
-+ if (Query_Log_Top == (QueryLogType *)NULL)
-+ {
-+ show_error("%s:malloc failed:
(%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ Query_Log_Top->next = NULL;
-+ Query_Log_Top->last = NULL;
-+ Query_Log_End = Query_Log_Top;
-+ Query_Log_End->next = NULL;
-+ Query_Log_End->last = NULL;
-+ query_log = Query_Log_Top;
-+ }
-+ else
-+ {
-+ query_log = (QueryLogType *)malloc(sizeof(QueryLogType));
-+ if (query_log == (QueryLogType *)NULL)
-+ {
-+ show_error("%s:malloc failed:
(%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ Query_Log_End->next = (char *)query_log;
-+ query_log->last = (char *)Query_Log_End;
-+ query_log->next = NULL;
-+ Query_Log_End = query_log;
-+ }
-+ query_log->header = (ReplicateHeader
*)malloc(sizeof(ReplicateHeader));
-+ if (query_log->header == (ReplicateHeader *)NULL)
-+ {
-+ show_error("%s:malloc failed: (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ size = ntohl(header->query_size);
-+
-+ query_log->query = (char *)malloc(size+4);
-+ if (query_log->query == (char *)NULL)
-+ {
-+ show_error("%s:malloc failed: (%s)",func,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ memset(query_log->query,0,size+4);
-+ memcpy(query_log->header,header,sizeof(ReplicateHeader));
-+ query_log->header->rlog = FROM_R_LOG_TYPE ;
-+ memcpy(query_log->query,query,size);
-+
-+ return STATUS_OK;
-+}
-+
-+static QueryLogType *
-+get_query_log_by_header(ReplicateHeader * header)
-+{
-+ QueryLogType * query_log = NULL;
-+
-+ if (Query_Log_Top == NULL)
-+ {
-+ return (QueryLogType *)NULL;
-+ }
-+ query_log = Query_Log_Top;
-+#ifdef PRINT_DEBUG
-+ show_debug("get_query_log_by_header:header is %d,%d,%d,%s",
-+ header->request_id,
-+ header->pid,
-+ header->port,
-+ header->from_host);
-+#endif
-+
-+ while(query_log != (QueryLogType *)NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("get_query_log_by_header:comparing to %d,%d,%d,%s",
-+ query_log->header->request_id,
-+ query_log->header->pid,
-+ query_log->header->port,
-+ query_log->header->from_host);
-+#endif
-+ if ((query_log->header->request_id == header->request_id) &&
-+ (query_log->header->pid == header->pid) &&
-+ (query_log->header->port == header->port) &&
-+
(!strncmp(query_log->header->from_host,header->from_host,sizeof(header->from_host))))
-+ {
-+ return query_log;
-+ }
-+ query_log = (QueryLogType *)(query_log->next);
-+ }
-+ return (QueryLogType *)NULL;
-+}
-+
-+static QueryLogType *
-+get_query_log(ReplicateHeader * header)
-+{
-+ QueryLogType * query_log = NULL;
-+
-+ if (Query_Log_Top == NULL)
-+ {
-+ return NULL;
-+ }
-+ query_log = Query_Log_Top;
-+ while(query_log != (QueryLogType *)NULL)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("get_qurey_log: comparing in log is %d,header is
%d",query_log->header->replicate_id,header->replicate_id);
-+#endif
-+ if (query_log->header->replicate_id == header->replicate_id)
-+ {
-+ return query_log;
-+ }
-+ query_log = (QueryLogType *)(query_log->next);
-+ }
-+ return (QueryLogType*)NULL;
-+}
-+
-+static void
-+delete_query_log(ReplicateHeader * header)
-+{
-+ QueryLogType * query_log = NULL;
-+ QueryLogType * last = NULL;
-+ QueryLogType * next = NULL;
-+
-+ query_log = get_query_log(header);
-+
-+ if (query_log == NULL)
-+ {
-+ return ;
-+ }
-+ last = (QueryLogType *)query_log->last;
-+ next = (QueryLogType *)query_log->next;
-+
-+ /* change link */
-+ if (last != (QueryLogType *)NULL)
-+ {
-+ last->next = (char *)next;
-+ }
-+ else
-+ {
-+ Query_Log_Top = next;
-+ }
-+ if (next != (QueryLogType *)NULL)
-+ {
-+ next->last = (char *)last;
-+ }
-+ else
-+ {
-+ Query_Log_End = last;
-+ }
-+
-+ /* delete contents */
-+ if (query_log->header != NULL)
-+ {
-+ free(query_log->header);
-+ }
-+ if (query_log->query != NULL)
-+ {
-+ free(query_log->query);
-+ }
-+ free(query_log);
-+}
-+
-+static int
-+set_commit_log(ReplicateHeader * header)
-+{
-+
-+ CommitLogInf * commit_log = NULL;
-+ ReplicateHeader * c_header;
-+
-+ if (Commit_Log_Tbl == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ commit_log = Commit_Log_Tbl + 1;
-+ while ( commit_log->inf.useFlag != DB_TBL_END )
-+ {
-+ if (commit_log->inf.useFlag != DB_TBL_USE)
-+ {
-+ commit_log->inf.useFlag = DB_TBL_USE;
-+ c_header = &(commit_log->header);
-+ memcpy(c_header,header,sizeof(ReplicateHeader));
-+ Commit_Log_Tbl->inf.commit_log_num ++;
-+ break;
-+ }
-+ commit_log ++;
-+ }
-+ return STATUS_OK;
-+}
-+
-+static CommitLogInf *
-+get_commit_log(ReplicateHeader * header)
-+{
-+ CommitLogInf * commit_log = NULL;
-+ ReplicateHeader * c_header;
-+ int cnt = 0;
-+
-+ if (Commit_Log_Tbl == NULL)
-+ {
-+ return (CommitLogInf *)NULL;
-+ }
-+ commit_log = Commit_Log_Tbl + 1;
-+ while ( commit_log->inf.useFlag != DB_TBL_END )
-+ {
-+ if (commit_log->inf.useFlag == DB_TBL_USE)
-+ {
-+ cnt ++;
-+ c_header = &(commit_log->header);
-+ if (c_header == NULL)
-+ {
-+ commit_log ++;
-+ continue;
-+ }
-+ if (c_header->replicate_id == header->replicate_id)
-+ {
-+ return commit_log;
-+ }
-+ }
-+ else
-+ {
-+ }
-+ if (cnt >= Commit_Log_Tbl->inf.commit_log_num)
-+ {
-+ break;
-+ }
-+ commit_log ++;
-+ }
-+ return (CommitLogInf *)NULL;
-+}
-+
-+static void
-+delete_commit_log(ReplicateHeader * header)
-+{
-+ CommitLogInf * commit_log = NULL;
-+
-+ commit_log = get_commit_log(header);
-+ if (commit_log != NULL)
-+ {
-+ memset(&(commit_log->header),0,sizeof(commit_log->header));
-+ commit_log->inf.useFlag = DB_TBL_INIT;
-+ Commit_Log_Tbl->inf.commit_log_num --;
-+ }
-+}
-+
-+static bool
-+was_committed_transaction(ReplicateHeader * header)
-+{
-+ CommitLogInf * commit_log = NULL;
-+
-+ commit_log = get_commit_log(header);
-+ if (commit_log != NULL)
-+ {
-+ return true;
-+ }
-+ return false;
-+}
-+
-+void
-+PGRreconfirm_commit(int sock, ReplicateHeader * header)
-+{
-+ int result = PGR_NOT_YET_COMMIT;
-+
-+ if (Replicateion_Log == NULL)
-+ {
-+ return ;
-+ }
-+
-+ if (Replicateion_Log->r_log_sock > 0)
-+ {
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+ }
-+ Replicateion_Log->r_log_sock = PGRcreate_send_rlog_socket();
-+ if (Replicateion_Log->r_log_sock == -1)
-+ return;
-+
-+ header->query_size = 0;
-+ PGRsend_rlog_packet(Replicateion_Log->r_log_sock,header,"");
-+ PGRrecv_rlog_result(Replicateion_Log->r_log_sock,&result,
sizeof(result));
-+
-+
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+
-+ snprintf(PGR_Result,PGR_MESSAGE_BUFSIZE,"%d,%d",
PGR_TRANSACTION_CONFIRM_ANSWER_FUNC_NO,result);
-+
-+ PGRreturn_result(sock, PGR_Result,PGR_NOWAIT_ANSWER);
-+}
-+
-+static int
-+reconfirm_commit(ReplicateHeader * header)
-+{
-+ char * func = "reconfirm_commit()";
-+ int result = PGR_NOT_YET_COMMIT;
-+
-+ /* check the transaction was committed */
-+ if (was_committed_transaction(header) == true)
-+ {
-+ result = PGR_ALREADY_COMMITTED;
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PGR_ALREADY_COMMITTED",func);
-+#endif
-+ }
-+ else
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:PGR_NOT_YET_COMMIT",func);
-+#endif
-+ }
-+ return result;
-+}
-+
-+void
-+PGRset_rlog(ReplicateHeader * header, char * query)
-+{
-+ char * func = "PGRset_rlog()";
-+ int status = STATUS_OK;
-+ bool send_flag = false;
-+
-+ if (PGR_Log_Header == NULL)
-+ {
-+ return;
-+ }
-+ switch (header->cmdSts)
-+ {
-+ case CMD_STS_QUERY:
-+ send_flag = true;
-+ break;
-+ case CMD_STS_TRANSACTION:
-+ if (header->cmdType ==
CMD_TYPE_COMMIT)
-+ {
-+ send_flag =
true;
-+
PGR_Log_Header->cmdType = header->cmdType;
-+
PGR_Log_Header->query_size = htonl(strlen(query));
-+ }
-+ break;
-+ }
-+ if (send_flag != true)
-+ {
-+ show_error("%s:send_flag is false",func);
-+ return;
-+ }
-+ PGR_Log_Header->cmdSys = CMD_SYS_LOG;
-+ if (Cascade_Inf->useFlag == DB_TBL_USE)
-+ {
-+ /* save log data in remote server */
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:set rlog %s",func,query);
-+#endif
-+ status =
PGRsend_lower_cascade(PGR_Log_Header, query);
-+ if (status == STATUS_OK) {
-+
status=PGRwait_notice_rlog_done();
-+ }
-+ if (status != STATUS_OK)
-+ {
-+#ifdef PRINT_DEBUG
-+
show_debug("%s:PGRsend_lower_cascade failed",func);
-+#endif
-+ PGRwrite_rlog(PGR_Log_Header,
query);
-+ }
-+ }
-+ else
-+ {
-+ /* save log data in local server */
-+ PGRwrite_rlog(PGR_Log_Header, query);
-+ }
-+}
-+
-+void
-+PGRunset_rlog(ReplicateHeader * header, char * query)
-+{
-+ int status = STATUS_OK;
-+ bool send_flag = false;
-+
-+ if (PGR_Log_Header == NULL)
-+ {
-+ return;
-+ }
-+ switch (header->cmdSts)
-+ {
-+ case CMD_STS_QUERY:
-+ send_flag = true;
-+ PGR_Log_Header->cmdSts = CMD_STS_DELETE_QUERY;
-+ break;
-+ case CMD_STS_TRANSACTION:
-+ if (PGR_Log_Header->cmdType == CMD_TYPE_COMMIT)
-+ {
-+ PGR_Log_Header->cmdSts =
CMD_STS_DELETE_TRANSACTION;
-+ PGR_Log_Header->query_size =
htonl(strlen(query));
-+ send_flag = true;
-+ }
-+ break;
-+ }
-+ if (send_flag != true)
-+ {
-+ return;
-+ }
-+ PGR_Log_Header->cmdSys = CMD_SYS_LOG;
-+ if (Cascade_Inf->useFlag == DB_TBL_USE)
-+ {
-+ /* save log data in remote server */
-+#ifdef PRINT_DEBUG
-+ show_debug("unset rlog %s",query);
-+#endif
-+
-+ status = PGRsend_lower_cascade(PGR_Log_Header, query);
-+ if (status == STATUS_OK)
-+ {
-+ status=PGRwait_notice_rlog_done();
-+ }
-+ if (status != STATUS_OK)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("PGRsend_lower_cascade recv failed");
-+#endif
-+ PGRwrite_rlog(PGR_Log_Header, query);
-+ }
-+ }
-+ else
-+ {
-+ /* save log data in local server */
-+ PGRwrite_rlog(PGR_Log_Header, query);
-+ }
-+}
-+
-+int
-+PGRresend_rlog_to_db(void)
-+{
-+ char *func="PGRresend_rlog_to_db";
-+ QueryLogType * query_log = NULL;
-+ QueryLogType * next = NULL;
-+ int status = STATUS_OK;
-+ int dest = 0;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:enter.",func);
-+#endif
-+
-+ query_log = Query_Log_Top;
-+
-+ while (query_log != NULL)
-+ {
-+
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:processing qlog,query=%s",func,query_log->query);
-+#endif
-+ if (query_log->header->rlog != FROM_R_LOG_TYPE )
-+ {
-+ query_log = (QueryLogType *)query_log->next;
-+ continue;
-+ }
-+ status =
replicate_packet_send_internal(query_log->header,query_log->query,
dest,RECOVERY_INIT,false);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:status=%d",func,status);
-+#endif
-+ if (status == STATUS_SKIP_REPLICATE )
-+ {
-+ Query_Log_Top = query_log;
-+ query_log = (QueryLogType *)query_log->next;
-+ }
-+ else
-+ {
-+ if (query_log->header != NULL)
-+ {
-+ free(query_log->header );
-+ }
-+ if (query_log->query != NULL)
-+ {
-+ free(query_log->query );
-+ }
-+ next = (QueryLogType *)query_log->next;
-+ free(query_log);
-+ query_log = next;
-+ Query_Log_Top = query_log;
-+ }
-+ if (query_log != NULL)
-+ {
-+ Query_Log_End = (QueryLogType *)query_log->next;
-+ }
-+ else
-+ {
-+ Query_Log_End = (QueryLogType *)NULL;
-+ }
-+ }
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:exit.",func);
-+#endif
-+
-+ return STATUS_OK;
-+}
-+
-+pid_t
-+PGR_RLog_Main(void)
-+{
-+ char * func = "PGR_RLog_Main()";
-+ int afd = -1;
-+ int rtn;
-+ struct sockaddr addr;
-+ socklen_t addrlen;
-+ pid_t pid = 0;
-+ pid_t pgid = 0;
-+
-+ extern int fork_wait_time;
-+
-+ if (Replicateion_Log == NULL)
-+ {
-+ show_error("%s:Replicateion_Log is NULL",func);
-+ return -1;
-+ }
-+ pgid = getpgid(0);
-+ if ((pid = fork()) != 0 )
-+ {
-+ return pid;
-+ }
-+ signal(SIGTERM,exit_rlog);
-+ signal(SIGINT,exit_rlog);
-+ signal(SIGQUIT,exit_rlog);
-+ signal(SIGPIPE,SIG_IGN);
-+
-+ if (PGRinit_transaction_table() != STATUS_OK)
-+ {
-+ show_error("RLog process transaction table memory allocate
failed");
-+ return -1;
-+ }
-+
-+ setpgid(0,pgid);
-+ RLog_Recv_Sock = create_recv_rlog_socket();
-+ if(RLog_Recv_Sock == -1)
-+ {
-+ show_error("rlog socket creation failure.quit all process.");
-+ kill(pgreplicate_pid, SIGINT);
-+ exit_rlog(0);
-+ }
-+
-+ if (fork_wait_time > 0) {
-+#ifdef PRINT_DEBUG
-+ show_debug("rlog process: wait fork(): pid = %d", getpid());
-+#endif
-+ sleep(fork_wait_time);
-+ }
-+
-+ for (;;)
-+ {
-+ fd_set rmask;
-+ struct timeval timeout;
-+
-+ timeout.tv_sec = PGR_RECV_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ Idle_Flag = IDLE_MODE ;
-+ if (Exit_Request)
-+ {
-+ exit_rlog(0);
-+ }
-+ /*
-+ * Wait for something to happen.
-+ */
-+ FD_ZERO(&rmask);
-+ FD_SET(RLog_Recv_Sock,&rmask);
-+ rtn = select(RLog_Recv_Sock+1, &rmask, (fd_set *)NULL,
(fd_set *)NULL, &timeout);
-+ if (rtn && FD_ISSET(RLog_Recv_Sock, &rmask))
-+ {
-+ Idle_Flag = BUSY_MODE ;
-+ addrlen = sizeof(addr);
-+ afd = accept(RLog_Recv_Sock, &addr, &addrlen);
-+ if (afd < 0)
-+ {
-+ continue;
-+ }
-+ else
-+ {
-+ do_rlog(afd);
-+ close(afd);
-+ }
-+ }
-+ }
-+ exit(0);
-+}
-+
-+static int
-+create_recv_rlog_socket(void)
-+{
-+ char * func = "create_recv_socket()";
-+ struct sockaddr_un addr;
-+ int fd;
-+ int status;
-+ int len;
-+
-+ /* set unix domain socket path */
-+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
-+ if (fd == -1)
-+ {
-+ show_error("%s:Failed to create UNIX domain socket. reason:
%s",func, strerror(errno));
-+ return -1;
-+ }
-+ memset((char *) &addr, 0, sizeof(addr));
-+ ((struct sockaddr *)&addr)->sa_family = AF_UNIX;
-+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/.s.PGRLOG.%d",
-+ PGR_Write_Path,
-+ Replicateion_Log->RLog_Port_Number);
-+fprintf(stderr,"addr.sun_path[%s]\n",addr.sun_path);
-+ if (Replicateion_Log->RLog_Sock_Path == NULL)
-+ {
-+ Replicateion_Log->RLog_Sock_Path = strdup(addr.sun_path);
-+fprintf(stderr,"Replicateion_Log->RLog_Sock_Path[%s]\n",Replicateion_Log->RLog_Sock_Path);
-+ }
-+ len = sizeof(struct sockaddr_un);
-+ status = bind(fd, (struct sockaddr *)&addr, len);
-+ if (status == -1)
-+ {
-+ show_error("%s: bind() failed. reason: %s", func,
strerror(errno));
-+ return -1;
-+ }
-+
-+ if (chmod(addr.sun_path, 0770) == -1)
-+ {
-+ show_error("%s: chmod() failed. reason: %s", func,
strerror(errno));
-+ return -1;
-+ }
-+
-+ status = listen(fd, 1000000);
-+ if (status < 0)
-+ {
-+ show_error("%s: listen() failed. reason: %s", func,
strerror(errno));
-+ return -1;
-+ }
-+ return fd;
-+}
-+
-+int
-+PGRcreate_send_rlog_socket(void)
-+{
-+ char * func = "create_recv_socket()";
-+ struct sockaddr_un addr;
-+ int fd;
-+ int len;
-+
-+ /* set unix domain socket path */
-+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
-+ if (fd == -1)
-+ {
-+ show_error("%s:Failed to create UNIX domain socket. reason:
%s",func, strerror(errno));
-+ return -1;
-+ }
-+ memset((char *) &addr, 0, sizeof(addr));
-+ ((struct sockaddr *)&addr)->sa_family = AF_UNIX;
-+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/.s.PGRLOG.%d",
-+ PGR_Write_Path,
-+ Replicateion_Log->RLog_Port_Number);
-+ if (Replicateion_Log->RLog_Sock_Path == NULL)
-+ {
-+ Replicateion_Log->RLog_Sock_Path = strdup(addr.sun_path);
-+ }
-+ len = sizeof(struct sockaddr_un);
-+ if (connect(fd, (struct sockaddr *)&addr, len) < 0)
-+ {
-+ close(fd);
-+ return -1;
-+ }
-+ return fd;
-+}
-+
-+static int
-+do_rlog(int fd)
-+{
-+ char * func = "do_rlog()";
-+ QueryLogType * query_log = NULL;
-+ ReplicateHeader header;
-+ char * query = NULL;
-+ int status = STATUS_OK;
-+
-+ memset(&header,0,sizeof(header));
-+ query = PGRread_packet(fd, &header);
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:got result:cmdSys='%c'",func,header.cmdSys);
-+#endif
-+ if (header.cmdSys == 0)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ switch (header.cmdSys)
-+ {
-+ case CMD_SYS_REPLICATE:
-+ if (header.cmdSts != CMD_STS_DELETE_QUERY)
-+ {
-+ query_log = get_query_log_by_header(&header);
-+ if (query_log != (QueryLogType*)NULL)
-+ {
-+
memcpy(&header,query_log->header,sizeof(ReplicateHeader));
-+ }
-+ send_message(fd,(char
*)&header,sizeof(ReplicateHeader));
-+ header.cmdSts = CMD_STS_DELETE_QUERY;
-+ PGRwrite_rlog(&header, NULL);
-+ }
-+ else
-+ {
-+ status =
PGRwrite_rlog((ReplicateHeader*)&header,(char *)NULL);
-+ send_message(fd,(char
*)&status,sizeof(status));
-+ }
-+ break;
-+ case CMD_SYS_LOG:
-+ status = PGRwrite_rlog((ReplicateHeader*)&header,
query);
-+ send_message(fd,(char *)&status,sizeof(status));
-+ break;
-+ case CMD_SYS_CALL:
-+ if (header.cmdSts == CMD_STS_TRANSACTION_ABORT)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:
CMD_STS_TRANSACTION_ABORT",func);
-+#endif
-+ status = reconfirm_commit(&header);
-+ }
-+ else if (header.cmdSts == CMD_STS_QUERY_SUSPEND)
-+ {
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: CMD_STS_QUERY_SUSPEND",func);
-+#endif
-+ // status =
PGRresend_rlog_to_db();
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s: SYS_CALL process done",func);
-+#endif
-+ send_message(fd,(char *)&status,sizeof(status));
-+ break;
-+ }
-+#ifdef PRINT_DEBUG
-+ show_debug("%s:process result done:cmdSys='%c'",func,header.cmdSys);
-+#endif
-+ return STATUS_OK;
-+}
-+
-+int
-+PGRget_sync_data(ReplicateHeader *header)
-+{
-+ ReplicateHeader rlog_header;
-+
-+ if (header == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+
-+ if (Replicateion_Log->r_log_sock > 0)
-+ {
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+ }
-+ Replicateion_Log->r_log_sock = PGRcreate_send_rlog_socket();
-+ if (Replicateion_Log->r_log_sock == -1)
-+ return STATUS_ERROR;
-+
-+ memset(&rlog_header,0,sizeof(ReplicateHeader));
-+ send_message( Replicateion_Log->r_log_sock, (char
*)header,sizeof(ReplicateHeader));
-+ recv_message( Replicateion_Log->r_log_sock, (char
*)&rlog_header,sizeof(ReplicateHeader));
-+ if (rlog_header.cmdSts != 0)
-+ {
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+ memcpy(header,&rlog_header, sizeof(ReplicateHeader));
-+ return STATUS_OK;
-+ }
-+
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+
-+ return STATUS_ERROR;
-+
-+}
-+
-+int
-+PGRdelete_sync_data(ReplicateHeader *header)
-+{
-+ int status;
-+ char cmdSts;
-+
-+ cmdSts = header->cmdSts;
-+ header->cmdSts = CMD_STS_DELETE_QUERY;
-+ if (header == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ if (Replicateion_Log->r_log_sock > 0)
-+ {
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+ }
-+ Replicateion_Log->r_log_sock = PGRcreate_send_rlog_socket();
-+ if (Replicateion_Log->r_log_sock == -1)
-+ return STATUS_ERROR;
-+
-+ send_message( Replicateion_Log->r_log_sock, (char
*)header,sizeof(ReplicateHeader));
-+ recv_message( Replicateion_Log->r_log_sock, (char
*)&status,sizeof(status));
-+ header->cmdSts = cmdSts;
-+
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+
-+ return status;
-+
-+}
-+
-+int
-+PGRsend_rlog_packet(int sock,ReplicateHeader * header, const char *
query_string)
-+{
-+ char * buf = NULL;
-+ int buf_size = 0;
-+ int header_size = 0;
-+ int query_size = 0;
-+ int rtn = 0;
-+
-+ /* check parameter */
-+ if ((sock <= 0) || (header == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ if (query_string != NULL)
-+ {
-+ query_size = ntohl(header->query_size);
-+ }
-+ header_size = sizeof(ReplicateHeader);
-+ buf_size = header_size + query_size + 4;
-+ buf = (char *)malloc(buf_size);
-+ if (buf == (char *)NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+ memset(buf,0,buf_size);
-+ buf_size -= 4;
-+ memcpy(buf,header,header_size);
-+ if (query_size > 0)
-+ {
-+ memcpy((char *)(buf+header_size),query_string,query_size+1);
-+ }
-+ rtn = send_message(sock,buf,buf_size);
-+ free(buf);
-+ return rtn;
-+}
-+
-+int
-+PGRrecv_rlog_result(int sock,void * result, int size)
-+{
-+ char *func = "PGRrecv_rlog_result";
-+ fd_set rmask;
-+ struct timeval timeout;
-+ int rtn;
-+
-+ if ((result == (void *)NULL) || (size <= 0))
-+ {
-+ return -1;
-+ }
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+ rtn = 1;
-+ for (;;)
-+ {
-+ timeout.tv_sec = PGR_RECV_TIMEOUT;
-+ timeout.tv_usec = 0;
-+
-+ FD_ZERO(&rmask);
-+ FD_SET(sock,&rmask);
-+ rtn = select(sock+1, &rmask, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
-+ if (rtn < 0)
-+ {
-+ if (errno != EINTR || errno != EAGAIN)
-+ {
-+ show_error("%s: select() failed
(%s)",func,strerror(errno));
-+ return -1;
-+ }
-+ }
-+ else if (rtn && FD_ISSET(sock, &rmask))
-+ {
-+ return (recv_message(sock, (char*)result, size));
-+ }
-+ }
-+ return -1;
-+}
-+
-+
-+static int
-+recv_message(int sock,char * buf, int len)
-+{
-+ char *func = "recv_message";
-+ int cnt = 0;
-+ int r = 0;
-+ char * read_ptr;
-+ int read_size = 0;
-+ cnt = 0;
-+ read_ptr = buf;
-+
-+ for (;;)
-+ {
-+ r = recv(sock,read_ptr + read_size ,len - read_size, 0);
-+ if (r < 0)
-+ {
-+ if (errno == EINTR || errno == EAGAIN)
-+ continue;
-+ else
-+ {
-+ show_error("%s:recv failed: %d(%s)",func,
errno, strerror(errno));
-+ return -1;
-+ }
-+ }
-+ else if (r > 0)
-+ {
-+ read_size += r;
-+ if (read_size == len)
-+ return read_size;
-+ }
-+ else /* r == 0 */
-+ {
-+ show_error("%s:unexpected EOF", func);
-+ return -1;
-+ }
-+ }
-+ return -1;
-+}
-+
-+int
-+PGRsend_rlog_to_local(ReplicateHeader * header,char * query)
-+{
-+ int status = STATUS_OK;
-+
-+ if (Replicateion_Log == NULL)
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ if (Replicateion_Log->r_log_sock > 0)
-+ {
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+ }
-+
-+ Replicateion_Log->r_log_sock = PGRcreate_send_rlog_socket();
-+ if (Replicateion_Log->r_log_sock == -1)
-+ return STATUS_ERROR;
-+
-+#ifdef PRINT_DEBUG
-+ show_debug("send_to_local %s",query);
-+#endif
-+ status =
PGRsend_rlog_packet(Replicateion_Log->r_log_sock,header,query);
-+#ifdef PRINT_DEBUG
-+ show_debug("send_to_local result is %d,errno=%d(%s)",status,errno
,strerror(errno));
-+#endif
-+
-+ if (status != STATUS_ERROR)
-+ {
-+ PGRrecv_rlog_result(Replicateion_Log->r_log_sock,&status,
sizeof(status));
-+ }
-+
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+
-+ return status;
-+}
-+
-+int
-+PGRget_rlog_header(ReplicateHeader * header)
-+{
-+ int status = STATUS_OK;
-+ ReplicateHeader rlog_header;
-+
-+ if ((Replicateion_Log == NULL) ||
-+ (header == NULL))
-+ {
-+ return STATUS_ERROR;
-+ }
-+
-+ if (Replicateion_Log->r_log_sock > 0)
-+ {
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+ }
-+ Replicateion_Log->r_log_sock = PGRcreate_send_rlog_socket();
-+ if (Replicateion_Log->r_log_sock == -1)
-+ return STATUS_ERROR;
-+
-+ memcpy(&rlog_header,header,sizeof(ReplicateHeader));
-+ rlog_header.cmdSys = CMD_SYS_REPLICATE;
-+ rlog_header.query_size = 0;
-+ status
=PGRsend_rlog_packet(Replicateion_Log->r_log_sock,&rlog_header,"");
-+ if (status != STATUS_ERROR)
-+ {
-+ status =
PGRrecv_rlog_result(Replicateion_Log->r_log_sock,&rlog_header,
sizeof(ReplicateHeader));
-+ if (status > 0)
-+ {
-+ memcpy(header,&rlog_header,sizeof(ReplicateHeader));
-+ status = STATUS_OK;
-+ }
-+ else
-+ {
-+ status = STATUS_ERROR;
-+ }
-+ }
-+
-+ close(Replicateion_Log->r_log_sock );
-+ Replicateion_Log->r_log_sock = -1;
-+
-+ return status;
-+}
-+
-+static int
-+send_message(int sock, char * msg, int len)
-+{
-+ char * func = "send_message()";
-+ fd_set wmask;
-+ struct timeval timeout;
-+ int rtn = 0;
-+ char * send_ptr = NULL;
-+ int send_size= 0;
-+ int buf_size = 0;
-+ int s = 0;
-+ int flag = 0;
-+
-+ if ((msg == NULL) || (len <= 0) || (sock <= 0))
-+ {
-+ return STATUS_ERROR;
-+ }
-+ send_ptr = msg;
-+ buf_size = len;
-+
-+ /*
-+ * Wait for something to happen.
-+ */
-+#ifdef MSG_DONTWAIT
-+ flag |= MSG_DONTWAIT;
-+#endif
-+#ifdef MSG_NOSIGNAL
-+ flag |= MSG_NOSIGNAL;
-+#endif
-+
-+ for (;;)
-+ {
-+ timeout.tv_sec = PGR_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;
-+
-+ show_error("%s:send-select error:
%d(%s)",func,errno,strerror(errno));
-+ return STATUS_ERROR;
-+ }
-+ 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
-+ {
-+ show_error("%s:send error:
%d(%s)",func,errno,strerror(errno));
-+ memset(send_ptr, 0, len);
-+ return STATUS_ERROR;
-+ }
-+ }
-+ else if (s == 0)
-+ {
-+ show_error("%s:unexpected EOF");
-+ memset(send_ptr, 0, len);
-+ return STATUS_ERROR;
-+ }
-+ else /* s > 0 */
-+ {
-+ send_size += s;
-+ if (send_size == buf_size)
-+ {
-+ return STATUS_OK;
-+ }
-+ }
-+ }
-+ }
-+ show_error("%s:send-select unknown error: %d(%s)",
-+ func,errno,strerror(errno));
-+ return STATUS_ERROR;
-+}
-+
-+static void
-+exit_rlog(int sig)
-+{
-+ sigset_t mask;
-+
-+ Exit_Request = true;
-+ if (sig == SIGTERM)
-+ {
-+ if (Idle_Flag == BUSY_MODE)
-+ {
-+ return;
-+ }
-+ }
-+
-+ sigemptyset(&mask);
-+ sigaddset(&mask, SIGINT);
-+ sigaddset(&mask, SIGTERM);
-+ sigaddset(&mask, SIGQUIT);
-+ sigprocmask(SIG_BLOCK, &mask, NULL);
-+
-+ if (RLog_Recv_Sock >= 0)
-+ {
-+ close(RLog_Recv_Sock);
-+ RLog_Recv_Sock = -1;
-+ }
-+ if (Replicateion_Log->RLog_Sock_Path != NULL)
-+ {
-+ unlink(Replicateion_Log->RLog_Sock_Path);
-+ free(Replicateion_Log->RLog_Sock_Path);
-+ }
-+ exit(0);
-+}
-+#endif /* USE_REPLICATION */
-diff -aruN postgresql-8.1.2/src/pgcluster/tool/Makefile
pgcluster-1.5.0rc7/src/pgcluster/tool/Makefile
---- postgresql-8.1.2/src/pgcluster/tool/Makefile 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/tool/Makefile 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,32 @@
-+#-------------------------------------------------------------------------
-+#
-+# Makefile for src/pgcluster/pgrp
-+#
-+#-------------------------------------------------------------------------
-+
-+subdir = src/pgcluster/tool
-+top_builddir = ../../..
-+include $(top_builddir)/src/Makefile.global
-+
-+OBJS= pgcbench.o
-+
-+# EXTRA_OBJS = $(top_builddir)/src/backend/libpq/replicate_com.o
-+
-+override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) -DBINDIR=\"$(bindir)\"
-+
-+all: pgcbench
-+
-+pgcbench: $(OBJS) $(libpq_builddir)/libpq.a
-+ $(CC) $(CFLAGS) $(OBJS) $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o
$@
-+
-+install: all installdirs
-+ $(INSTALL_PROGRAM) pgcbench$(X) $(DESTDIR)$(bindir)/pgcbench$(X)
-+
-+installdirs:
-+ $(mkinstalldirs) $(DESTDIR)$(bindir)
-+
-+uninstall:
-+ rm -f $(addprefix $(DESTDIR)$(bindir)/, pgcbench$(X))
-+
-+clean distclean maintainer-clean:
-+ rm -f pgcbench$(X) $(OBJS)
-diff -aruN postgresql-8.1.2/src/pgcluster/tool/README
pgcluster-1.5.0rc7/src/pgcluster/tool/README
---- postgresql-8.1.2/src/pgcluster/tool/README 1970-01-01 01:00:00.000000000
+0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/tool/README 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,127 @@
-+-----------------------------------------------------
-+About pgcbench
-+-----------------------------------------------------
-+
-+The pgcbench is the program which performs the benchmark test of PGCluster.
-+Of course, it can use for benchmark not only PGCluster but PostgreSQL.
-+
-+The pgcbench displays the number of executed transaction per second (tps)
which performed transaction containing SELECT, UPDATE, and INSERT.
-+The table set as the object of transaction contains data of 100,000 lines
by a default.
-+
-+A display is actually as follows.
-+ number of clients: 4
-+ number of transactions actually processed: 100
-+ run time (sec) = 4.416423
-+ tps = 22.642759 (including connections establishing)
-+
-+
-+The pgcbench is calculating tps not based on the actually completed number
of transactions but based on the number that is specified at beginning.
-+So, the tps displayed may not be right when the benchmark has been
suspended.
-+
-+The pgcbench was created based on pgbench which is the benchmark program
for PostgreSQL written by Tatsuo Ishii.
-+
-+
-+-----------------------------------------------------
-+Feature of pgcbench
-+-----------------------------------------------------
-+- Although the pgbench is simulating multi-user connections in the single
process, pgcbench has made multi-user connections in the multi-process by
fork.
-+- There are some options which specifies the contents of transaction in
pgcbench.
-+
-+
-+-----------------------------------------------------
-+Installation of pgcbench
-+-----------------------------------------------------
-+1. Install with the PGCluster
-+Your installation of PGCluster also installs pgcbench automatically.
-+
-+2. Install only pgcbench
-+If you want install only pgcbench, you do not need to compile all of the
PGCluster.
-+pgcbench is compiled as follow.
-+
-+ $ cd $TOP_PGCusters_Source
-+ $ ./configure
-+ $ cd src/interface/libpq
-+ $ make all
-+ $ cd $TOP_PGCusters_Source/src/pgcluster/tool
-+ $ make
-+
-+-----------------------------------------------------
-+Usage of pgcbench
-+-----------------------------------------------------
-+pgcbench [options] [DB name]
-+pgcbench -i [options] [DB name] (for initialization of DB)
-+
-+[options]
-+-h: host name
-+-p: port number
-+-c: number of clients connected simultaneously (default is 1)
-+-t: number of transaction which each client executed
-+-s: scaling factor of table size. 1 means 100,000 records. ( use with '-i' )
-+-u: user name
-+-P: password
-+-n: it does not execute VACUUM and is not cleared history table.
-+-v: execute VACUUM and clear history table
-+-I: execute INSERT query only
-+-U: execute UPDATE query only
-+-S: execute SELECT query only
-+-f: command script file name
-+-T: transaction is performed in the transaction bloc surrounded by BEGIN
and END.
-+-C: each session is reconnected for every transaction
-+-l: The execution time of each transaction is recorded. That log file is
created under current directory as "pgcbench_log.xxx".
-+-d: debug option
-+
-+-----------------------------------------------------
-+Initialization of the database
-+-----------------------------------------------------
-+In order to execute a default benchmark test by pgcbench, the data base
should be initialized and made test data.
-+You can execute the following commands for initialization of the data base.
-+
-+ $ pgcbench -i [DB name ]
-+
-+Thereby, the following tables are created (when a scaling factor is 1) .
-+
-+ table name | row num
-+ -----------+--------
-+ branches | 1
-+ tellers | 10
-+ accounts | 100000
-+ history | 0
-+
-+When a scaling factor is changed into 10, 100, 1000, etc., according to it,
the number of table rows will increase 10 times, 100 times, and 1000 times.
-+For example, when the scaling factor is set to 100, the number of table
rows is as follows.
-+
-+ table name | row num
-+ -----------+----------
-+ branches | 100
-+ tellers | 1000
-+ accounts | 10000000
-+ history | 0
-+
-+
-+-----------------------------------------------------
-+Format of the command script file
-+-----------------------------------------------------
-+The pgcbench read the command script file that is specified with '-f'
option, and executes the specified transaction.
-+The specified command can be described one per one line.
-+The null line is disregarded and the row which starts with double hyphen
means a comment line.
-+In addition to the SQL command, the meta-command which starts with a
backslash can be described in this file.
-+
-+The following meta-commands can be used.
-+
-+\setrandom name min max
-+ Random digits are set into variable 'name'.
-+ The sphere of random digits is between 'min' and 'max'.
-+ For example, when you want to execute the benchmark like TPC-B, you
can describes as follows.
-+
-+
-+ \setrandom aid 1 100000
-+ \setrandom bid 1 1
-+ \setrandom tid 1 10
-+ \setrandom delta 1 1000
-+ BEGIN
-+ UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid
-+ SELECT abalance FROM accounts WHERE aid = :aid
-+ UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid
-+ UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid
-+ INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid,
:aid, :delta, 'now')
-+ END
-diff -aruN postgresql-8.1.2/src/pgcluster/tool/README.jp
pgcluster-1.5.0rc7/src/pgcluster/tool/README.jp
---- postgresql-8.1.2/src/pgcluster/tool/README.jp 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/tool/README.jp 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,296 @@
-+$Id: README,v 1.2 2005/08/02 01:24:53 tom-sato Exp $
-+
-+$B"#(B pgcbench $B$H$O(B
-+
-+pgcbench $B$O(B PGCluster
$B$N%Y%s%A%^!<%/%F%9%H$r9T$&%W%m%0%i%`$G$9!#$b$A$m(B
-+$B$s!"(BPGCluster $B$@$1$G$O$J$/(B PostgreSQL
$B$N%Y%s%A%^!<%/$r<B;\$9$k$3$H$b$G(B
-+$B$-$^$9!#(B
-+
-+pgcbench $B$O(B SELECT$B!"(BUPDATE$B!"(BINSERT
$B$r4^$`%H%i%s%6%/%7%g%s$r<B9T$7!"A4(B
-+$BBN$N<B9T;~4V$H<B:]$K40N;$7$?$G$"$m$&%H%i%s%6%/%7%g%s$N?t$+$i(B 1
$BIC4V$K(B
-+$B<B9T$G$-$?%H%i%s%6%/%7%g%s?t(B (tps)
$B$rI=<($7$^$9!#=hM}$NBP>]$H$J$k%F!<(B
-+$B%V%k$O%G%U%)%k%H$G$O(B 10 $BK|9T$N%G!<%?$r4^$_$^$9!#(B
-+
-+$B<B:]$KI=<($O0J2<$N$h$&$K$J$j$^$9!#(B
-+
-+ number of clients: 4
-+ number of transactions actually processed: 100
-+ run time (sec) = 4.416423
-+ tps = 22.642759 (including connections establishing)
-+
-+$B"((B $BCm0U(B
-+
-+ pgcbench $B$G$O!"%H%i%s%6%/%7%g%s$,<B:]$K40N;$7$?$+$I$&$+$K4X78$J$/!"(B
-+ $B:G=i$K;XDj$5$l$?%H%i%s%6%/%7%g%s$N?t$r$b$H$K(B tps
$B$r5a$a$F$$$k$?$a!"(B
-+ $B%Y%s%A%^!<%/$,ESCf$G=*N;$7$F$7$^$C$?>l9g!"I=<($5$l$k(B tps
$B$,?.MQ$G$-(B
-+ $B$J$$2DG=@-$,$"$k$3$H$KCm0U$7$F$/$@$5$$!#(B
-+
-+$B$J$*!"(Bpgcbench $B$O(B pgbench $B$H$$$&(B PostgreSQL
$BMQ$K=q$+$l$?%Y%s%A%^!<%/%F(B
-+$B%9%H$r9T$J$&%W%m%0%i%`$r$b$H$K:n@.$5$l$^$7$?!#(B
-+
-+
-+$B"#(B pgbench $B$H$N0c$$(B
-+
-+$B!&(B $B%^%k%A%f!<%64D6-$N<B8=J}K!(B
-+
-+ pgbench $B$,(B libpq
$B$NHsF14|=hM}5!G=$r;H$C$?%7%s%0%k%W%m%;%9$K$h$C$F%7(B
-+ $B%_%e%l!<%H$7$F$$$k$N$KBP$7$F!"(Bpgcbench $B$G$O(B fork
$B$r;H$C$?%^%k%A%W%m(B
-+ $B%;%9$K$h$C$F<B8=$7$F$$$^$9!#$3$l$O!"%7%s%0%k%W%m%;%9$G$O%m%C%/$,H/(B
-+ $B@8$9$k$H!"(BPGCluster $B$,;_$^$C$F$7$^$&$3$H$rHr$1$k$?$a$G$9!#(B
-+
-+$B!&(B $B%*%W%7%g%s$NJQ99(B
-+
-+ pgcbench $B$K$O!"(BPGCluster
$B$N%Y%s%A%^!<%/%F%9%H$r9T$J$&$N$KJXMx$J!"%H(B
-+ $B%i%s%6%/%7%g%s$NFbMF$r;XDj$9$k%*%W%7%g%s$,!"$$$/$D$+DI2C$5$l$F$$$^(B
-+ $B$9!%(B
-+
-+
-+$B"#(B pgcbench $B$N%$%s%9%H!<%k(B
-+
-+1. PGCluster $B$r(B configure$B!"(Bmake $B$7$^$9!#(B
-+
-+ pgcbench $B$N%$%s%9%H!<%k$@$1$,L\E*$G$"$l$P!"(BPGCluster
$B$N$9$Y$F$r%3%s(B
-+ $B%Q%$%k$9$kI,MW$O$"$j$^$;$s!#(BPGCluster
$B%=!<%9$N%H%C%W%G%#%l%/%H%j$G(B
-+ configure $B$r$7$?8e!"(Bsrc/interface/libpq $B$G(B make all
$B$r<B9T$9$l$P=`(B
-+ $BHw40N;$G$9!#(B
-+
-+2. $B$3$N%G%#%l%/%H%j(B (src/pgcluster/tool) $B$G(B make
$B$r<B9T$7$^$9!#(B
-+
-+ $B$=$&$9$k$H!"(Bpgcbench
$B$H$$$&<B9T%W%m%0%i%`$,$G$-$^$9!#$=$N$^$^<B9T$7(B
-+ $B$F$b9=$$$^$;$s$7!"(Bmake install $B$r<B9T$7$F(B PGCluster
$B$NI8=`<B9T%W%m(B
-+ $B%0%i%`%G%#%l%/%H%j(B ($B%G%U%)%k%H$G$O(B /usr/local/pgsql/bin)
$B$K%$%s%9%H!<(B
-+ $B%k$9$k$3$H$b$G$-$^$9!#(B
-+
-+
-+$B"#(B pgcbench $B$N;H$$J}(B
-+
-+ pgcbench [$B%*%W%7%g%s(B] [$B%G!<%?%Y!<%9L>(B]
-+
-+$B%G!<%?%Y!<%9L>$r>JN,$9$k$H!"%m%0%$%sL>$HF1$8%G!<%?%Y!<%9L>$r;XDj$7$?$b(B
-+$B$N$H8+$J$7$^$9!#$J$*!"(Bpgcbench
$B$G%G%U%)%k%H$N%Y%s%A%^!<%/$r<B;\$9$k$?(B
-+$B$a$K$O!"8e=R$N(B -i
$B%*%W%7%g%s$r;HMQ$7$F%G!<%?%Y!<%9$r$"$i$+$8$a=i4|2=$7(B
-+$B$F$*$/I,MW$,$"$j$^$9!#(B
-+
-+pgcbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!#(B
-+
-+-h $B%[%9%HL>(B
-+
-+ PostgreSQL$B$N(B $B%G!<%?%Y!<%9%G!<%b%s(B postmaster
$B$NF0:n$7$F$$$k%[%9%HL>(B
-+ $B$r;XDj$7$^$9!#>JN,$9$k$H4D6-JQ?t(B PGHOST
$B$K@_Dj$7$?%[%9%HL>$,;XDj$5(B
-+ $B$l$^$9!#(BPGHOST $B$b;XDj$5$l$F$$$J$$$H<+%[%9%H$K(B Unix
$B%I%a%$%s%=%1%C%H(B
-+ $B$G@\B3$7$^$9!#(B
-+
-+-p $B%]!<%HHV9f(B
-+
-+ postmaster $B$N;HMQ$9$k%]!<%HHV9f$r;XDj$7$^$9!#>JN,$9$k$H4D6-JQ?t(B
-+ PGPORT $B$K@_Dj$7$?%]!<%HHV9f$,;XDj$5$l$^$9!#(BPGPORT
$B$b;XDj$5$l$F$$$J(B
-+ $B$$$H(B 5432 $B$,;XDj$5$l$?$b$N$H8+$J$7$^$9!#(B
-+
-+-c $B%/%i%$%"%s%H?t(B
-+
-+ $BF1;~<B9T%/%i%$%"%s%H?t$r;XDj$7$^$9!#>JN,;~$O(B 1
$B$H$J$j$^$9!#(Bpgcbench
-+ $B$OF1;~<B9T%/%i%$%"%s%H$4$H$K%U%!%$%k%G%#%9%/%j%W%?$r;HMQ$9$k$N$G!"(B
-+ $B;HMQ2DG=%U%!%$%k%G%#%9%/%j%W%??t$r1[$($k%/%i%$%"%s%H?t$O;XDj$G$-$^(B
-+ $B$;$s!#;HMQ2DG=%U%!%$%k%G%#%9%/%j%W%??t$O(B limit $B$d(B ulimit
$B%3%^%s%I$G(B
-+ $B3NG'$9$k$3$H$,$G$-$^$9!#(B
-+
-+-t $B%H%i%s%6%/%7%g%s?t(B
-+
-+ $B%H%i%s%6%/%7%g%s?t$r;XDj$7$^$9!#3F%/%i%$%"%s%H$,<B9T$9$k%H%i%s%6%/(B
-+ $B%7%g%s?t$O$3$l$r%/%i%$%"%s%H?t$G3d$C$??t$H$J$j$^$9!#>JN,;~$O(B 10
$B$H(B
-+ $B$J$j$^$9!#(B
-+
-+-s $B%9%1!<%j%s%0%U%!%/%?!<(B
-+
-+ -i $B%*%W%7%g%s$H$H$b$K;HMQ$7$^$9!#%9%1!<%j%s%0%U%!%/%?!<$O(B 1
$B0J>e$N(B
-+ $B@0?t$G$9!#%9%1!<%j%s%0%U%!%/%?!<$rJQ$($k$3$H$K$h$j!"%F%9%H$NBP>]$H(B
-+ $B$J$k%F!<%V%k$NBg$-$5$,(B 10 $BK|(B $B!_(B
$B%9%1!<%j%s%0%U%!%/%?!<$K$J$j$^$9!#(B
-+ $B%G%U%)%k%H$N%9%1!<%j%s%0%U%!%/%?!<$O(B 1 $B$G$9!#(B
-+
-+-u $B%m%0%$%sL>(B
-+
-+ DB $B%f!<%6$N%m%0%$%sL>$r;XDj$7$^$9!#>JN,$9$k$H4D6-JQ?t(B PGUSER
$B$K@_Dj(B
-+ $B$7$?%m%0%$%sL>$,;XDj$5$l$^$9!#(B
-+
-+-P $B%Q%9%o!<%I(B
-+
-+ $B%Q%9%o!<%I$r;XDj$7$^$9!#$J$*!"$3$N%*%W%7%g%s$r;H$&$H!"%Q%9%o!<%I$r(B
-+ ps
$B%3%^%s%I$G8+$i$l$k$J$I!"%;%-%e%j%F%#%[!<%k$K$J$k2DG=@-$,$"$k$N$G!"(B
-+ $B%F%9%HMQ$K$N$_$*;H$$2<$5$$!#(B
-+
-+-n
-+
-+ $B$3$N%*%W%7%g%s$r;XDj$9$k$H!"%Y%s%A%^!<%/3+;OA0$K(B VACUUM $B$H(B
history
-+ $B%F!<%V%k$N%/%j%"$r<B9T$7$^$;$s!#(B
-+
-+-v
-+
-+ $B$3$N%*%W%7%g%s$r;XDj$9$k$H!"%Y%s%A%^!<%/3+;OA0$K(B VACUUM $B$H(B
history
-+ $B%F!<%V%k$N%/%j%"$r<B9T$7$^$9!#(B-v $B$H(B -n
$B$r>JN,$9$k$H!":G>.8B$N(B
-+ VACUUM $B$J$I$r<B9T$7$^$9!#$9$J$o$A!"(Bhistory
$B%F!<%V%k$N%/%j%"$H!"(B
-+ branches$B!"(Btellers$B!"(Bhistory $B%F!<%V%k$N(B VACUUM
$B$r<B9T$7$^$9!#$3$l$O!"(B
-+ VACUUM $B$N;~4V$r:G>.8B$K$7$J$,$i!"%Q%U%)!<%^%s%9$K1F6A$9$k%4%_A]=|$r(B
-+ $B8z2LE*$K<B9T$7$^$9!#DL>o$O(B -v $B$H(B -n
$B$r>JN,$9$k$3$H$r?d>)$7$^$9!#(B
-+
-+-I
-+
-+ $BA^F~$N$_$N%H%i%s%6%/%7%g%s$r<B9T$7$^$9!#A^F~%9%T!<%I$rB,Dj$7$?$$$H(B
-+ $B$-$K;H$$$^$9!#(B
-+
-+-U
-+
-+ $B99?7$N$_$N%H%i%s%6%/%7%g%s$r<B9T$7$^$9!#99?7%9%T!<%I$rB,Dj$7$?$$$H(B
-+ $B$-$K;H$$$^$9!#(B
-+
-+-S
-+
-+ $B8!:w$N$_$N%H%i%s%6%/%7%g%s$r<B9T$7$^$9!#8!:w%9%T!<%I$rB,Dj$7$?$$$H(B
-+ $B$-$K;H$$$^$9!#(B
-+
-+-f $B%U%!%$%kL>(B
-+
-+ $B%H%i%s%6%/%7%g%s$NFbMF$,5-=R$5$l$?%U%!%$%kL>$r;XDj$7$^$9!#$3$N%*%W(B
-+ $B%7%g%s$r;XDj$9$k$H!"%U%!%$%k$K5-=R$5$l$?FbMF$N%H%i%s%6%/%7%g%s$r<B(B
-+ $B9T$7$^$9!#%Y%s%A%^!<%/$G;HMQ$9$k%F!<%V%k$O$"$i$+$8$a=i4|2=$7$F$*$/(B
-+ $BI,MW$,$"$j$^$9!#F~NO%U%!%$%k$N%U%)!<%^%C%H$O8e=R$7$^$9!#(B
-+
-+-T
-+
-+ BEGIN $B$H(B END
$B$G0O$^$l$?%H%i%s%6%/%7%g%s%V%m%C%/Fb$G%H%i%s%6%/%7%g%s(B
-+ $B$r<B9T$7$^$9!#(B
-+
-+-C
-+
-+ $B$3$N%*%W%7%g%s$r;XDj$9$k$H!":G=i$K3NN)$7$?%3%M%/%7%g%s$r;H$$2s$9$N(B
-+ $B$G$O$J$/!"3F%H%i%s%6%/%7%g%s$4$H$K(B DB
$B$X$N@\B3$r9T$$$^$9!#%3%M%/%7%g(B
-+ $B%s$N%*!<%P!<$X%C%I$rB,Dj$9$k$N$KM-8z$G$9!#(B
-+
-+-l
-+
-+ $B8D!9$N%H%i%s%6%/%7%g%s$N<B9T;~4V$r5-O?$7$^$9!#5-O?@h$O%+%l%s%H%G%#(B
-+ $B%l%/%H%j0J2<$N(B pgbench_log.xxx
$B$H$$$&%U%!%$%k$G$9!#%U%!%$%k$N%U%)!<(B
-+ $B%^%C%H$O0J2<$N$h$&$K$J$j$^$9!#;~4V$O%^%$%/%mICC10L$G$9!#(B
-+
-+ <$B%/%i%$%"%s%H(B ID> <$B%H%i%s%6%/%7%g%sHV9f(B> <$B;~4V(B>
-+
-+-d
-+
-+ $B%G%P%C%0%*%W%7%g%s!#MM!9$J>pJs$,I=<($5$l$^$9!#(B
-+
-+
-+$B"#(B $B%G!<%?%Y!<%9$N=i4|2=(B
-+
-+pgcbench $B$G%G%U%)%k%H$N%Y%s%A%^!<%/%F%9%H$r<B;\$9$k$?$a$K$O!"$"$i$+$8(B
-+$B$a%G!<%?%Y!<%9$r=i4|2=$7!"%F%9%H%G!<%?$r:n$kI,MW$,$"$j$^$9!#(B
-+
-+ pgcbench -i [$B%G!<%?%Y!<%9L>(B]
-+
-+$B$3$l$K$h$j0J2<$N%F!<%V%k$,:n@.$5$l$^$9(B
($B%9%1!<%j%s%0%U%!%/%?!<$,(B 1 $B$N(B
-+$B>l9g(B)$B!#(B
-+
-+ $B%F!<%V%kL>(B | $B9T?t(B
-+ ------------+--------
-+ branches | 1
-+ tellers | 10
-+ accounts | 100000
-+ history | 0
-+
-+$B"((B $BCm0U(B
-+
-+ $BF1$8L>A0$N%F!<%V%k$,$"$k$H:o=|$5$l$F$7$^$&$N$G$4Cm0U2<$5$$!#(B
-+
-+$B%9%1!<%j%s%0%U%!%/%?!<$r(B 10$B!"(B100$B!"(B1000
$B$J$I$KJQ99$9$k$H!">e5-9T?t$O$=(B
-+$B$l$K1~$8$F(B 10 $BG\!"(B100 $BG\!"(B1000
$BG\$K$J$j$^$9!#Nc$($P!"%9%1!<%j%s%0%U%!(B
-+$B%/%?!<$r(B 100 $B$H$9$k$H0J2<$N$h$&$K$J$j$^$9!#(B
-+
-+ $B%F!<%V%kL>(B | $B9T?t(B
-+ ------------+----------
-+ branches | 100
-+ tellers | 1000
-+ accounts | 10000000
-+ history | 0
-+
-+
-+$B"#(B $BF~NO%U%!%$%k$N%U%)!<%^%C%H(B
-+
-+pgcbench $B$G$O!"(B-f
$B%*%W%7%g%s$r;XDj$7$F%H%i%s%6%/%7%g%s$K4^$^$l$k(B SQL
-+$B%3%^%s%I$NFbMF$r5-=R$7$?%U%!%$%k$rFI$_9~$`$3$H$,$G$-$^$9!#F~NO%U%!%$%k(B
-+$B$K$O(B 1 $B9T$K$D$-(B 1
$B$D$N%3%^%s%I$r5-=R$7$^$9!#6u9T$OL5;k$5$l!"Fs=E%O%$%U(B
-+$B%s$G;O$^$k9T$O%3%a%s%H$r0UL#$7$^$9!#(B
-+
-+$B%3%^%s%I$K$O!"(BSQL
$B%3%^%s%I$K2C$(!"%P%C%/%9%i%C%7%e$G;O$^$k%a%?%3%^%s%I(B
-+$B$r5-=R$9$k$3$H$,$G$-$^$9!#%a%?%3%^%s%I$O(B pgcbench
$B<+?H$K$h$C$F<B9T$5$l(B
-+$B$^$9!#%a%?%3%^%s%I$N7A<0$O%P%C%/%9%i%C%7%e!"$=$ND>8e$K%3%^%s%I$NF0;l!"(B
-+$B$=$N<!$K0z?t$,B3$-$^$9!#F0;l%3%^%s%I$H0z?t!"$^$?$=$l$>$l$N0z?t$O6uGrJ8(B
-+$B;z$K$h$C$F6hJL$5$l$^$9!#(B
-+
-+$B:#$N$H$3$m!"0J2<$N%a%?%3%^%s%I$,Dj5A$5$l$F$$$^$9!#(B
-+
-+\setrandom name min max
-+
-+ $B:G>.CM(B min $B$H:GBgCM(B max $B$N4V$NCM$r<h$kMp?t$r!"(Bname
$BJQ?t$K@_Dj$7$^$9!#(B
-+
-+$BJQ?t$KMp?t$r@_Dj$9$k$K$O!"(B\setrandom
$B%a%?%3%^%s%I$r;HMQ$7$F0J2<$N$h$&(B
-+$B$K5-=R$7$^$9!#(B
-+
-+ \setrandom aid 1 100000
-+
-+$B$3$l$O!"JQ?t(B aid $B$K(B 1 $B$+$i(B 100000
$B$N4V$NMp?t$r@_Dj$7$^$9!#$^$?!"JQ?t$N(B
-+$BCM$r(B SQL
$B%3%^%s%I$KKd$a9~$`$K$O!"0J2<$N$h$&$K$=$NL>A0$NA0$K%3%m%s$rIU(B
-+$B$1$^$9!#(B
-+
-+ SELECT abalance FROM accounts WHERE aid = :aid
-+
-+$BNc$($P!"(BTPC-B
$B$K;w$?%Y%s%A%^!<%/$r9T$&$K$O!"0J2<$N$h$&$K%H%i%s%6%/%7%g(B
-+$B%s$NFbMF$r%U%!%$%k$K5-=R$7!"(B-f
$B%*%W%7%g%s$K$h$C$F$=$N%U%!%$%k$r;XDj$7(B
-+$B$F(B pgcbench $B$r<B9T$7$^$9!#(B
-+
-+ \setrandom aid 1 100000
-+ \setrandom bid 1 1
-+ \setrandom tid 1 10
-+ \setrandom delta 1 1000
-+ BEGIN
-+ UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid
-+ SELECT abalance FROM accounts WHERE aid = :aid
-+ UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid
-+ UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid
-+ INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid,
:aid, :delta, 'now')
-+
-+$B$J$*!"$3$NNc$G$O!"(B-i $B%*%W%7%g%s$r;H$C$F=i4|2=$7$?%G!<%?%Y!<%9(B
($B%9%1!<(B
-+$B%j%s%0%U%!%/%?!<$,(B 1 $B$N>l9g(B)
$B$KBP$7$F%Y%s%A%^!<%/$r9T$&$3$H$r2>Dj$7$F(B
-+$B$$$^$9!#(B
-+
-+
-+$B"#(B $B%H%i%s%6%/%7%g%s$NDj5A(B
-+
-+pgcbench $B$N%G%U%)%k%H$N%Y%s%A%^!<%/$G$O!"0J2<$N(B SQL
$B%3%^%s%I$rA4It40N;(B
-+$B$7$F(B 1 $B%H%i%s%6%/%7%g%s$H?t$($F$$$^$9!#(B
-+
-+1. SELECT abalance FROM accounts WHERE aid = :aid
-+
-+ :aid $B$O(B 1 $B$+$i%9%1!<%j%s%0%U%!%/%?!<(B $B!_(B 10
$BK|$^$G$NCM$r<h$kMp?t$G$9!#(B
-+ $B$3$3$G$O(B 1
$B7o$@$18!:w$5$l$^$9!#0J2<!"Mp?t$NCM$O$=$l$>$l$3$N%H%i%s%6(B
-+ $B%/%7%g%s$NCf$G$OF1$8CM$r;H$$$^$9!#(B
-+
-+2. UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid
-+
-+ :delta $B$O(B 1 $B$+$i(B 1000 $B$^$G$NCM$r<h$kMp?t$G$9!#(B
-+
-+3. SELECT abalance FROM accounts WHERE aid = :aid
-+
-+4. INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid,
:aid, :delta, 'now')
-+
-+ :tid $B$O(B 1 $B$+$i%9%1!<%j%s%0%U%!%/%?!<(B $B!_(B 10
$B$^$G$NCM$r<h$kMp?t!"(B:bid
-+ $B$O(B 1 $B$+$i%9%1!<%j%s%0%U%!%/%?!<$^$G$NCM$r<h$kMp?t$G$9!#(B
-+
-+5. INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid,
:aid, :delta, 'now')
-+
-+6. INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid,
:aid, :delta, 'now')
-+
-+7. SELECT abalance FROM accounts WHERE aid = :aid
-+
-+-T $B%*%W%7%g%s$r;XDj$7$F%H%i%s%6%/%7%g%s%V%m%C%/Fb$G%H%i%s%6%/%7%g%s$r(B
-+$B<B9T$9$k>l9g!"(B1 $B$r(B BEGIN$B$K!"(B7 $B$r(B END
$B$KCV$-49$($?(B SQL $B%3%^%s%I$,<B9T$5(B
-+$B$l$^$9!#$^$?!"%H%i%s%6%/%7%g%s$H$7$F<B9T$5$l$k(B SQL
$B%3%^%s%I$O!"(B-I $B%*%W(B
-+$B%7%g%s(B ($BA^F~$N$_(B) $B$G$"$l$P(B 4$B!"(B-U ($B99?7$N$_(B)
$B$G$"$l$P(B 2$B!"(B-S ($B8!:w$N$_(B)
-+$B$G$"$l$P(B 1 $B$H$J$j$^$9!#(B
-diff -aruN postgresql-8.1.2/src/pgcluster/tool/pgcbench.c
pgcluster-1.5.0rc7/src/pgcluster/tool/pgcbench.c
---- postgresql-8.1.2/src/pgcluster/tool/pgcbench.c 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/tool/pgcbench.c 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,1626 @@
-+/*
-+ * pgbench: a simple benchmark program for PGCluster
-+ * This program was written based on pgbench by Tatsuo Ishii.
-+ *
-+ * Portions Copyright (c) 2003-2006, Atsushi Mitani
-+ * Portions Copyright (c) 2000-2006, Tatsuo Ishii
-+ *
-+ * 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 "postgres_fe.h"
-+
-+#include "libpq-fe.h"
-+
-+#include <errno.h>
-+
-+
-+#ifdef WIN32
-+#include "win32.h"
-+#else
-+#include <sys/time.h>
-+#include <unistd.h>
-+
-+#ifdef HAVE_GETOPT_H
-+#include <getopt.h>
-+#endif
-+
-+#ifdef HAVE_SYS_SELECT_H
-+#include <sys/select.h>
-+#endif
-+
-+/* for getrlimit */
-+#include <sys/resource.h>
-+#endif /* ! WIN32 */
-+
-+#include <sys/types.h>
-+#include <sys/wait.h>
-+
-+#include <ctype.h>
-+#include <search.h>
-+
-+extern char *optarg;
-+extern int optind;
-+
-+#ifdef WIN32
-+#undef select
-+#endif
-+
-+
-+/********************************************************************
-+ * some configurable parameters */
-+
-+#define MAXCLIENTS 4096 /* max number of clients
allowed */
-+
-+int nclients = 1; /* default number of
simulated clients */
-+int nxacts = 10; /* default number of
transactions per
-+ * clients */
-+
-+/*
-+ * scaling factor. for example, tps = 10 will make 1000000 tuples of
-+ * accounts table.
-+ */
-+int tps = 1;
-+
-+/*
-+ * end of configurable parameters
-+ *********************************************************************/
-+
-+#define nbranches 1
-+#define ntellers 10
-+#define naccounts 100000
-+
-+#define SELECT_ONLY (1)
-+#define INSERT_ONLY (2)
-+#define UPDATE_ONLY (3)
-+#define WITH_TRANSACTION (4)
-+#define TPC_B_LIKE (5)
-+#define CUSTOM_QUERY (6)
-+
-+#define SQL_COMMAND 1
-+#define META_COMMAND 2
-+
-+FILE *LOGFILE = NULL;
-+
-+bool use_log = false; /* log transaction
latencies to a file */
-+
-+int remains; /* number of
remaining clients */
-+
-+int is_connect; /* establish
connection for each
-+ *
transaction */
-+
-+char *pghost = "";
-+char *pgport = NULL;
-+char *pgoptions = NULL;
-+char *pgtty = NULL;
-+char *login = NULL;
-+char *pwd = NULL;
-+char *dbName;
-+
-+typedef struct
-+{
-+ char *name;
-+ char *value;
-+} Variable;
-+
-+typedef struct
-+{
-+ PGconn *con; /* connection handle to DB */
-+ int id; /* client No.
*/
-+ int state; /* state No. */
-+ int cnt; /* xacts count */
-+ int ecnt; /* error count */
-+ int maxAct;
-+ int listen; /* 0 indicates that
an async query has
-+ * been sent
*/
-+ int aid; /* account id for
this transaction */
-+ int bid; /* branch id for this
transaction */
-+ int tid; /* teller id for this
transaction */
-+ int delta;
-+ int abalance;
-+ void *variables;
-+ struct timeval txn_begin; /* used for measuring latencies */
-+} CState;
-+
-+typedef struct
-+{
-+ int type;
-+ int argc;
-+ char **argv;
-+} Command;
-+
-+Command **commands = NULL;
-+
-+static void
-+usage(void)
-+{
-+ fprintf(stderr, "usage: pgcbench [-h hostname][-p port][-c
nclients][-t ntransactions][-s scaling_factor][-I(insert only)][-U(update
only)][-S(select only)][-f filename][-u login][-P
password][-d(debug)][dbname]\n");
-+ fprintf(stderr, "(initialize mode): pgcbench -i [-h hostname][-p
port][-s scaling_factor][-u login][-P password][-d(debug)][dbname]\n");
-+}
-+
-+/* random number generator */
-+static int
-+getrand(int min, int max )
-+{
-+
-+ return (min + (int) (max * 1.0 * rand() / (RAND_MAX + 1.0)));
-+}
-+
-+/* set up a connection to the backend */
-+static PGconn *
-+doConnect(void)
-+{
-+ PGconn *con;
-+ PGresult *res;
-+
-+ con = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName,
-+ login, pwd);
-+ if (con == NULL)
-+ {
-+ fprintf(stderr, "Connection to database '%s' failed.\n",
dbName);
-+ fprintf(stderr, "Memory allocatin problem?\n");
-+ return (NULL);
-+ }
-+
-+ if (PQstatus(con) == CONNECTION_BAD)
-+ {
-+ fprintf(stderr, "Connection to database '%s' failed.\n",
dbName);
-+
-+ if (PQerrorMessage(con))
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ else
-+ fprintf(stderr, "No explanation from the backend\n");
-+
-+ return (NULL);
-+ }
-+
-+ res = PQexec(con, "SET search_path = public");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+
-+ return (con);
-+}
-+
-+/* throw away response from backend */
-+static void
-+discard_response(CState * state)
-+{
-+ PGresult *res;
-+
-+ do
-+ {
-+ res = PQgetResult(state->con);
-+ if (res)
-+ PQclear(res);
-+ } while (res);
-+}
-+
-+/* check to see if the SQL result was good */
-+static int
-+check(CState * st, PGresult *res, int good)
-+{
-+ if (res && PQresultStatus(res) != good)
-+ {
-+ fprintf(stderr, "aborted in state %d: %s", st->state,
PQerrorMessage(st->con));
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ return (-1);
-+ }
-+ return (0); /* OK */
-+}
-+
-+static int
-+compareVariables(const void *v1, const void *v2)
-+{
-+ return strcmp(((Variable *)v1)->name, ((Variable *)v2)->name);
-+}
-+
-+static char *
-+getVariable(CState * st, char *name)
-+{
-+ Variable key = { name }, *var;
-+
-+ var = tfind(&key, &st->variables, compareVariables);
-+ if (var != NULL)
-+ return (*(Variable **)var)->value;
-+ else
-+ return NULL;
-+}
-+
-+static int
-+putVariable(CState * st, char *name, char *value)
-+{
-+ Variable key = { name }, *var;
-+
-+ var = tfind(&key, &st->variables, compareVariables);
-+ if (var == NULL)
-+ {
-+ if ((var = malloc(sizeof(Variable))) == NULL)
-+ return false;
-+
-+ var->name = NULL;
-+ var->value = NULL;
-+
-+ if ((var->name = strdup(name)) == NULL
-+ || (var->value = strdup(value)) == NULL
-+ || tsearch(var, &st->variables, compareVariables) ==
NULL)
-+ {
-+ free(var->name);
-+ free(var->value);
-+ free(var);
-+ return false;
-+ }
-+ }
-+ else
-+ {
-+ free((*(Variable **)var)->value);
-+ if (((*(Variable **)var)->value = strdup(value)) == NULL)
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+static char *
-+assignVariables(CState * st, char *sql)
-+{
-+ int i, j;
-+ char *p, *name, *val;
-+ void *tmp;
-+
-+ i = 0;
-+ while ((p = strchr(&sql[i], ':')) != NULL)
-+ {
-+ i = j = p - sql;
-+ do{
-+ i++;
-+ }while (isalnum((unsigned char) sql[i]) != 0 || sql[i] ==
'_');
-+ if (i == j + 1)
-+ continue;
-+
-+ name = malloc(i - j);
-+ if (name == NULL)
-+ return NULL;
-+ memcpy(name, &sql[j + 1], i-(j+1));
-+ name[i-(j+1)] = '\0';
-+ val = getVariable(st, name);
-+ free(name);
-+ if (val == NULL)
-+ continue;
-+
-+ if (strlen(val) > i - j)
-+ {
-+ tmp = realloc(sql, strlen(sql) - (i - j) +
strlen(val) + 1);
-+ if (tmp == NULL)
-+ {
-+ free(sql);
-+ return NULL;
-+ }
-+ sql = tmp;
-+ }
-+
-+ if (strlen(val) != i - j)
-+ memmove(&sql[j + strlen(val)], &sql[i],
strlen(&sql[i]) + 1);
-+
-+ strncpy(&sql[j], val, strlen(val));
-+
-+ if (strlen(val) < i - j)
-+ {
-+ tmp = realloc(sql, strlen(sql) + 1);
-+ if (tmp == NULL)
-+ {
-+ free(sql);
-+ return NULL;
-+ }
-+ sql = tmp;
-+ }
-+
-+ i = j + strlen(val);
-+ }
-+
-+ return sql;
-+}
-+
-+/* process a transaction */
-+static void
-+doMix(CState * st, int debug, int ttype)
-+{
-+ char sql[256];
-+ PGresult *res;
-+
-+ if (st->listen)
-+ { /* are we
receiver? */
-+ if (debug)
-+ fprintf(stderr, "client receiving\n");
-+ if (!PQconsumeInput(st->con))
-+ { /* there's
something wrong */
-+ fprintf(stderr, "Client aborted in state %d. Probably
the backend died while processing.\n", st->state);
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ return;
-+ }
-+ if (PQisBusy(st->con))
-+ return; /* don't have the
whole result yet */
-+
-+ switch (st->state)
-+ {
-+ case 0: /* response to
"begin" */
-+ res = PQgetResult(st->con);
-+ if (ttype == WITH_TRANSACTION)
-+ {
-+ if (check(st, res, PGRES_COMMAND_OK))
-+ return;
-+ }
-+ else
-+ {
-+ if (check(st, res, PGRES_TUPLES_OK))
-+ return;
-+ }
-+ PQclear(res);
-+ discard_response(st);
-+ break;
-+ case 1: /* response to
"update accounts..." */
-+ res = PQgetResult(st->con);
-+ if (check(st, res, PGRES_COMMAND_OK))
-+ return;
-+ PQclear(res);
-+ discard_response(st);
-+ break;
-+ case 2: /* response to
"select abalance ..." */
-+ res = PQgetResult(st->con);
-+ if (check(st, res, PGRES_TUPLES_OK))
-+ return;
-+ PQclear(res);
-+ discard_response(st);
-+ break;
-+ case 3: /* response to
"update tellers ..." */
-+ res = PQgetResult(st->con);
-+ if (check(st, res, PGRES_COMMAND_OK))
-+ return;
-+ PQclear(res);
-+ discard_response(st);
-+ break;
-+ case 4: /* response to
"update branches ..." */
-+ res = PQgetResult(st->con);
-+ if (check(st, res, PGRES_COMMAND_OK))
-+ return;
-+ PQclear(res);
-+ discard_response(st);
-+ break;
-+ case 5: /* response to
"insert into history ..." */
-+ res = PQgetResult(st->con);
-+ if (check(st, res, PGRES_COMMAND_OK))
-+ return;
-+ PQclear(res);
-+ discard_response(st);
-+ break;
-+ case 6: /* response to "end"
*/
-+
-+ /*
-+ * transaction finished: record the time it
took in the
-+ * log
-+ */
-+ if (use_log)
-+ {
-+ double diff;
-+ struct timeval now;
-+
-+ gettimeofday(&now, NULL);
-+ diff = (int) (now.tv_sec -
st->txn_begin.tv_sec) * 1000000.0 +
-+ (int) (now.tv_usec -
st->txn_begin.tv_usec);
-+
-+ fprintf(LOGFILE, "%d %d %.0f\n",
st->id, st->cnt, diff);
-+ }
-+
-+ res = PQgetResult(st->con);
-+ if (ttype == WITH_TRANSACTION)
-+ {
-+ if (check(st, res, PGRES_COMMAND_OK))
-+ return;
-+ }
-+ else
-+ {
-+ if (check(st, res, PGRES_TUPLES_OK))
-+ return;
-+ }
-+ PQclear(res);
-+ discard_response(st);
-+
-+ if (is_connect)
-+ {
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ }
-+ if (++st->cnt >= st->maxAct)
-+ {
-+ remains--; /*
I've done */
-+ if (st->con != NULL)
-+ {
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ }
-+ return;
-+ }
-+ break;
-+ }
-+
-+ /* increment state counter */
-+ st->state++;
-+ if (st->state > 6)
-+ {
-+ st->state = 0;
-+ remains--; /* I've done */
-+ }
-+ }
-+
-+ if (st->con == NULL)
-+ {
-+ if ((st->con = doConnect()) == NULL)
-+ {
-+ fprintf(stderr, "Client aborted in establishing
connection.\n");
-+ remains--; /* I've aborted */
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ return;
-+ }
-+ }
-+
-+ switch (st->state)
-+ {
-+ case 0: /* about to start */
-+ if (ttype == WITH_TRANSACTION)
-+ {
-+ strcpy(sql, "begin");
-+ }
-+ else
-+ {
-+ st->aid = getrand(1, naccounts * tps);
-+ snprintf(sql, 256, "select abalance from
accounts where aid = %d", st->aid);
-+ }
-+ st->aid = getrand(1, naccounts * tps);
-+ st->bid = getrand(1, nbranches * tps);
-+ st->tid = getrand(1, ntellers * tps);
-+ st->delta = getrand(1, 1000);
-+ if (use_log)
-+ gettimeofday(&(st->txn_begin), NULL);
-+ break;
-+ case 1:
-+ snprintf(sql, 256, "update accounts set abalance =
abalance + %d where aid = %d\n", st->delta, st->aid);
-+ break;
-+ case 2:
-+ snprintf(sql, 256, "select abalance from accounts
where aid = %d", st->aid);
-+ break;
-+ case 3:
-+ if (ttype == 0)
-+ {
-+ snprintf(sql, 256, "update tellers set
tbalance = tbalance + %d where tid = %d\n",
-+ st->delta, st->tid);
-+ break;
-+ }
-+ case 4:
-+ if (ttype == 0)
-+ {
-+ snprintf(sql, 256, "update branches set
bbalance = bbalance + %d where bid = %d", st->delta, st->bid);
-+ break;
-+ }
-+ case 5:
-+ snprintf(sql, 256, "insert into
history(tid,bid,aid,delta,mtime) values(%d,%d,%d,%d,'now')",
-+ st->tid, st->bid, st->aid,
st->delta);
-+ break;
-+ case 6:
-+ if (ttype == WITH_TRANSACTION)
-+ {
-+ strcpy(sql, "end");
-+ }
-+ else
-+ {
-+ st->aid = getrand(1, naccounts * tps);
-+ snprintf(sql, 256, "select abalance from
accounts where aid = %d", st->aid);
-+ }
-+ break;
-+ }
-+
-+ if (debug)
-+ fprintf(stderr, "client sending %s\n", sql);
-+
-+ if (PQsendQuery(st->con, sql) == 0)
-+ {
-+ if (debug)
-+ fprintf(stderr, "PQsendQuery(%s)failed\n", sql);
-+ st->ecnt++;
-+ }
-+ else
-+ {
-+ st->listen++; /* flags that should be
listened */
-+ }
-+}
-+
-+/* process a select only transaction */
-+static void
-+doOne(CState * st, int debug, int ttype )
-+{
-+ char sql[256];
-+ PGresult *res;
-+
-+ if (st->listen)
-+ { /* are we
receiver? */
-+ if (debug)
-+ fprintf(stderr, "client receiving\n");
-+ if (!PQconsumeInput(st->con))
-+ { /* there's
something wrong */
-+ fprintf(stderr, "Client aborted in state %d. Probably
the backend died while processing.\n", st->state);
-+ remains--; /* I've aborted */
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ return;
-+ }
-+ if (PQisBusy(st->con))
-+ return; /* don't have the
whole result yet */
-+
-+ switch (st->state)
-+ {
-+ case 0: /* response to
"select abalance ..." */
-+ res = PQgetResult(st->con);
-+ if (ttype == SELECT_ONLY)
-+ {
-+ if (check(st, res, PGRES_TUPLES_OK))
-+ return;
-+ }
-+ else
-+ {
-+ if (check(st, res, PGRES_COMMAND_OK))
-+ return;
-+ }
-+ PQclear(res);
-+ discard_response(st);
-+
-+ if (is_connect)
-+ {
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ }
-+
-+ if (++st->cnt >= st->maxAct)
-+ {
-+ remains--; /*
I've done */
-+ if (st->con != NULL)
-+ {
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ }
-+ return;
-+ }
-+ break;
-+ }
-+
-+ /* increment state counter */
-+ st->state++;
-+ if (st->state > 0)
-+ {
-+ st->state = 0;
-+ remains--; /* I've done */
-+ }
-+ }
-+
-+ if (st->con == NULL)
-+ {
-+ if ((st->con = doConnect()) == NULL)
-+ {
-+ fprintf(stderr, "Client aborted in establishing
connection.\n");
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ return;
-+ }
-+ }
-+
-+ switch (st->state)
-+ {
-+ case 0:
-+ st->aid = getrand(1, naccounts * tps);
-+ st->bid = getrand(1, nbranches * tps);
-+ st->tid = getrand(1, ntellers * tps);
-+ st->delta = getrand(1, 1000);
-+ if ( ttype == SELECT_ONLY)
-+ {
-+ snprintf(sql, 256, "select abalance from
accounts where aid = %d", st->aid);
-+ }
-+ if ( ttype == UPDATE_ONLY)
-+ {
-+ snprintf(sql, 256, "update accounts set
abalance = abalance + %d where aid = %d\n", st->delta, st->aid);
-+ }
-+ if ( ttype == INSERT_ONLY)
-+ {
-+ snprintf(sql, 256, "insert into
history(tid,bid,aid,delta,mtime) values(%d,%d,%d,%d,'now')",
-+ st->tid, st->bid, st->aid,
st->delta);
-+ }
-+ break;
-+ }
-+
-+ if (debug)
-+ fprintf(stderr, "client sending %s\n", sql);
-+
-+ if (PQsendQuery(st->con, sql) == 0)
-+ {
-+ if (debug)
-+ fprintf(stderr, "PQsendQuery(%s)failed\n", sql);
-+ st->ecnt++;
-+ }
-+ else
-+ {
-+ st->listen++; /* flags that should be
listened */
-+ }
-+}
-+
-+static void
-+doCustom(CState * st, int debug, int ttype )
-+{
-+ PGresult *res;
-+
-+ if (st->listen)
-+ { /* are we
receiver? */
-+ if (commands[st->state]->type == SQL_COMMAND)
-+ {
-+ if (debug)
-+ fprintf(stderr, "client receiving\n");
-+ if (!PQconsumeInput(st->con))
-+ { /*
there's something wrong */
-+ fprintf(stderr, "Client aborted in state %d.
Probably the backend died while processing.\n", st->state);
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ return;
-+ }
-+ if (PQisBusy(st->con))
-+ return; /* don't have
the whole result yet */
-+ }
-+
-+ /*
-+ * transaction finished: record the time it took in the
-+ * log
-+ */
-+ if (use_log && commands[st->state + 1] == NULL)
-+ {
-+ double diff;
-+ struct timeval now;
-+
-+ gettimeofday(&now, NULL);
-+ diff = (int) (now.tv_sec - st->txn_begin.tv_sec) *
1000000.0 +
-+ (int) (now.tv_usec - st->txn_begin.tv_usec);
-+
-+ fprintf(LOGFILE, "%d %d %.0f\n", st->id, st->cnt,
diff);
-+ }
-+
-+ if (commands[st->state]->type == SQL_COMMAND)
-+ {
-+ res = PQgetResult(st->con);
-+ if (strncasecmp(commands[st->state]->argv[0],
"select", 6) != 0)
-+ {
-+ if (check(st, res, PGRES_COMMAND_OK))
-+ return;
-+ }
-+ else
-+ {
-+ if (check(st, res, PGRES_TUPLES_OK))
-+ return;
-+ }
-+ PQclear(res);
-+ discard_response(st);
-+ }
-+
-+ if (commands[st->state + 1] == NULL)
-+ {
-+ if (is_connect)
-+ {
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ }
-+ if (++st->cnt >= st->maxAct)
-+ {
-+ remains--; /* I've done
*/
-+ if (st->con != NULL)
-+ {
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ }
-+ return;
-+ }
-+ }
-+
-+ /* increment state counter */
-+ st->state++;
-+ if (commands[st->state] == NULL)
-+ {
-+ st->state = 0;
-+ remains--; /* I've done */
-+ }
-+ }
-+
-+ if (st->con == NULL)
-+ {
-+ if ((st->con = doConnect()) == NULL)
-+ {
-+ fprintf(stderr, "Client aborted in establishing
connection.\n");
-+ remains--; /* I've aborted */
-+ PQfinish(st->con);
-+ st->con = NULL;
-+ return;
-+ }
-+ }
-+
-+ if (use_log && st->state == 0)
-+ gettimeofday(&(st->txn_begin), NULL);
-+
-+ if (commands[st->state]->type == SQL_COMMAND)
-+ {
-+ char *sql;
-+
-+ if ((sql = strdup(commands[st->state]->argv[0])) == NULL
-+ || (sql = assignVariables(st, sql)) == NULL)
-+ {
-+ fprintf(stderr, "out of memory\n");
-+ st->ecnt++;
-+ return;
-+ }
-+
-+ if (debug)
-+ fprintf(stderr, "client sending %s\n", sql);
-+
-+ if (PQsendQuery(st->con, sql) == 0)
-+ {
-+ if (debug)
-+ fprintf(stderr, "PQsendQuery(%s)failed\n",
sql);
-+ st->ecnt++;
-+ }
-+ else
-+ {
-+ st->listen++; /* flags that should
be listened */
-+ }
-+
-+ free(sql);
-+ }
-+ else if (commands[st->state]->type == META_COMMAND)
-+ {
-+ int argc = commands[st->state]->argc, i;
-+ char **argv = commands[st->state]->argv;
-+
-+ if (debug)
-+ {
-+ fprintf(stderr, "client executing \\%s", argv[0]);
-+ for (i = 1; i < argc; i++)
-+ fprintf(stderr, " %s", argv[i]);
-+ fprintf(stderr, "\n");
-+ }
-+
-+ if (strcasecmp(argv[0], "setrandom") == 0)
-+ {
-+ char *val;
-+
-+ if ((val = malloc(strlen(argv[3]) + 1)) == NULL)
-+ {
-+ fprintf(stderr, "%s: out of memory\n",
argv[0]);
-+ st->ecnt++;
-+ return;
-+ }
-+
-+ sprintf(val, "%d", getrand(atoi(argv[2]),
atoi(argv[3])));
-+
-+ if (putVariable(st, argv[1], val) == false)
-+ {
-+ fprintf(stderr, "%s: out of memory\n",
argv[0]);
-+ free(val);
-+ st->ecnt++;
-+ return;
-+ }
-+
-+ free(val);
-+ st->listen++;
-+ }
-+ }
-+}
-+
-+/* discard connections */
-+static void
-+disconnect_all(CState * state)
-+{
-+ if (state->con)
-+ PQfinish(state->con);
-+}
-+
-+/* create tables and setup data */
-+static void
-+init(void)
-+{
-+ PGconn *con;
-+ PGresult *res;
-+ static char *DDLs[] = {
-+ "drop table branches",
-+ "create table branches(bid int not null,bbalance int,filler
char(88))",
-+ "drop table tellers",
-+ "create table tellers(tid int not null,bid int,tbalance
int,filler char(84))",
-+ "drop table accounts",
-+ "create table accounts(aid int not null,bid int,abalance
int,filler char(84))",
-+ "drop table history",
-+ "create table history(tid int,bid int,aid int,delta int,mtime
timestamp,filler char(22))"};
-+ static char *DDLAFTERs[] = {
-+ "alter table branches add primary key (bid)",
-+ "alter table tellers add primary key (tid)",
-+ "alter table accounts add primary key (aid)"};
-+
-+
-+ char sql[256];
-+
-+ int i;
-+
-+ if ((con = doConnect()) == NULL)
-+ exit(1);
-+
-+ for (i = 0; i < (sizeof(DDLs) / sizeof(char *)); i++)
-+ {
-+ res = PQexec(con, DDLs[i]);
-+ if (strncmp(DDLs[i], "drop", 4) && PQresultStatus(res) !=
PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+ }
-+
-+ res = PQexec(con, "begin");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+
-+ for (i = 0; i < nbranches * tps; i++)
-+ {
-+ snprintf(sql, 256, "insert into branches(bid,bbalance)
values(%d,0)", i + 1);
-+ res = PQexec(con, sql);
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+ }
-+
-+ for (i = 0; i < ntellers * tps; i++)
-+ {
-+ snprintf(sql, 256, "insert into tellers(tid,bid,tbalance)
values (%d,%d,0)"
-+ ,i + 1, i / ntellers + 1);
-+ res = PQexec(con, sql);
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+ }
-+
-+ res = PQexec(con, "end");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+
-+ /*
-+ * occupy accounts table with some data
-+ */
-+ fprintf(stderr, "creating tables...\n");
-+ for (i = 0; i < naccounts * tps; i++)
-+ {
-+ int j = i + 1;
-+
-+ if (j % 10000 == 1)
-+ {
-+ res = PQexec(con, "copy accounts from stdin");
-+ if (PQresultStatus(res) != PGRES_COPY_IN)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+ }
-+
-+ snprintf(sql, 256, "%d\t%d\t%d\t\n", j, i / naccounts + 1, 0);
-+ if (PQputline(con, sql))
-+ {
-+ fprintf(stderr, "PQputline failed\n");
-+ exit(1);
-+ }
-+
-+ if (j % 10000 == 0)
-+ {
-+ /*
-+ * every 10000 tuples, we commit the copy command.
this should
-+ * avoid generating too much WAL logs
-+ */
-+ fprintf(stderr, "%d tuples done.\n", j);
-+ if (PQputline(con, "\\.\n"))
-+ {
-+ fprintf(stderr, "very last PQputline
failed\n");
-+ exit(1);
-+ }
-+
-+ if (PQendcopy(con))
-+ {
-+ fprintf(stderr, "PQendcopy failed\n");
-+ exit(1);
-+ }
-+
-+#ifdef NOT_USED
-+
-+ /*
-+ * do a checkpoint to purge the old WAL logs
-+ */
-+ res = PQexec(con, "checkpoint");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+#endif /* NOT_USED */
-+ }
-+ }
-+ fprintf(stderr, "set primary key...\n");
-+ for (i = 0; i < (sizeof(DDLAFTERs) / sizeof(char *)); i++)
-+ {
-+ res = PQexec(con, DDLAFTERs[i]);
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+ }
-+
-+ /* vacuum */
-+ fprintf(stderr, "vacuum...");
-+ res = PQexec(con, "vacuum analyze");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+ fprintf(stderr, "done.\n");
-+
-+ PQfinish(con);
-+}
-+
-+static int
-+process_file(char *filename)
-+{
-+ const char delim[] = " \f\n\r\t\v";
-+
-+ FILE *fd;
-+ int lineno, i, j;
-+ char buf[BUFSIZ], *p, *tok;
-+ void *tmp;
-+
-+ if (strcmp(filename, "-") == 0)
-+ fd = stdin;
-+ else if ((fd = fopen(filename, "r")) == NULL)
-+ {
-+ fprintf(stderr, "%s: %s\n", strerror(errno), filename);
-+ return false;
-+ }
-+
-+ fprintf(stderr, "processing file...\n");
-+
-+ lineno = 1;
-+ i = 0;
-+ while (fgets(buf, sizeof(buf), fd) != NULL)
-+ {
-+ if ((p = strchr(buf, '\n')) != NULL)
-+ *p = '\0';
-+ p = buf;
-+ while (isspace((unsigned char)*p))
-+ p++;
-+ if (*p == '\0' || strncmp(p, "--", 2) == 0)
-+ {
-+ lineno++;
-+ continue;
-+ }
-+
-+ if ((tmp = realloc(commands, sizeof(Command *) * (i + 1))) ==
NULL)
-+ {
-+ i--;
-+ goto error;
-+ }
-+ commands = tmp;
-+
-+ if ((commands[i] = malloc(sizeof(Command))) == NULL)
-+ goto error;
-+
-+ commands[i]->argv = NULL;
-+ commands[i]->argc = 0;
-+
-+ if (*p == '\\')
-+ {
-+ commands[i]->type = META_COMMAND;
-+
-+ j = 0;
-+ tok = strtok(++p, delim);
-+ while (tok != NULL)
-+ {
-+ tmp = realloc(commands[i]->argv, sizeof(char
*) * (j + 1));
-+ if (tmp == NULL)
-+ goto error;
-+ commands[i]->argv = tmp;
-+
-+ if ((commands[i]->argv[j] = strdup(tok)) ==
NULL)
-+ goto error;
-+
-+ commands[i]->argc++;
-+
-+ j++;
-+ tok = strtok(NULL, delim);
-+ }
-+
-+ if (strcasecmp(commands[i]->argv[0], "setrandom") ==
0)
-+ {
-+ int min, max;
-+
-+ if (commands[i]->argc < 4)
-+ {
-+ fprintf(stderr, "%s: %d: \\%s:
missing argument\n", filename, lineno, commands[i]->argv[0]);
-+ goto error;
-+ }
-+
-+ for (j = 4; j < commands[i]->argc; j++)
-+ fprintf(stderr, "%s: %d: \\%s: extra
argument \"%s\" ignored\n", filename, lineno, commands[i]->argv[0],
commands[i]->argv[j]);
-+
-+ if ((min = atoi(commands[i]->argv[2])) < 0)
-+ {
-+ fprintf(stderr, "%s: %d: \\%s:
invalid minimum number %s\n", filename, lineno, commands[i]->argv[0],
commands[i]->argv[2]);
-+ goto error;
-+ }
-+
-+ if ((max = atoi(commands[i]->argv[3])) < min
|| max > RAND_MAX)
-+ {
-+ fprintf(stderr, "%s: %d: \\%s:
invalid maximum number %s\n", filename, lineno, commands[i]->argv[0],
commands[i]->argv[3]);
-+ goto error;
-+ }
-+ }
-+ else
-+ {
-+ fprintf(stderr, "%s: %d: invalid command
\\%s\n", filename, lineno, commands[i]->argv[0]);
-+ goto error;
-+ }
-+ }
-+ else
-+ {
-+ commands[i]->type = SQL_COMMAND;
-+
-+ if ((commands[i]->argv = malloc(sizeof(char *))) ==
NULL)
-+ goto error;
-+
-+ if ((commands[i]->argv[0] = strdup(p)) == NULL)
-+ goto error;
-+
-+ commands[i]->argc++;
-+ }
-+
-+ i++;
-+ lineno++;
-+ }
-+ fclose(fd);
-+
-+ if ((tmp = realloc(commands, sizeof(Command *) * (i + 1))) == NULL)
-+ goto error;
-+ commands = tmp;
-+
-+ commands[i] = NULL;
-+
-+ return true;
-+
-+error:
-+ if (errno == ENOMEM)
-+ fprintf(stderr, "%s: %d: out of memory\n", filename, lineno);
-+
-+ fclose(fd);
-+
-+ if (commands == NULL)
-+ return false;
-+
-+ while (i >= 0)
-+ {
-+ if (commands[i] != NULL)
-+ {
-+ for (j = 0; j < commands[i]->argc; j++)
-+ free(commands[i]->argv[j]);
-+
-+ free(commands[i]->argv);
-+ free(commands[i]);
-+ }
-+
-+ i--;
-+ }
-+ free(commands);
-+
-+ return false;
-+}
-+
-+/* print out results */
-+static void
-+printResults(
-+ int ttype, int normal_xacts,
-+ struct timeval * tv1, struct timeval * tv2,
-+ struct timeval * tv3)
-+{
-+ double t1,
-+ t2;
-+ char *s;
-+
-+ t1 = (tv3->tv_sec - tv1->tv_sec) * 1000000.0 + (tv3->tv_usec -
tv1->tv_usec);
-+ t1 = t1 / 1000000.0 ;
-+
-+ t2 = (tv3->tv_sec - tv1->tv_sec) * 1000000.0 + (tv3->tv_usec -
tv1->tv_usec);
-+ t2 = normal_xacts * 1000000.0 / t2;
-+
-+#define SELECT_ONLY (1)
-+#define INSERT_ONLY (2)
-+#define UPDATE_ONLY (3)
-+#define WITH_TRANSACTION (4)
-+ switch (ttype)
-+ {
-+ case 0:
-+ s = "TPC-B (sort of)";
-+ break;
-+ case SELECT_ONLY :
-+ s = "SELECT only";
-+ break;
-+ case INSERT_ONLY :
-+ s = "INSERT only";
-+ break;
-+ case UPDATE_ONLY :
-+ s = "UPDATE only";
-+ break;
-+ case CUSTOM_QUERY :
-+ s = "Custom query";
-+ break;
-+ default:
-+ s = "Mix query";
-+ break;
-+ }
-+
-+
-+ printf("transaction type: %s\n", s);
-+ printf("scaling factor: %d\n", tps);
-+ printf("number of clients: %d\n", nclients);
-+ printf("number of transactions actually processed: %d\n",
normal_xacts );
-+ printf("run time (sec) = %f \n", t1);
-+ printf("tps = %f (including connections establishing)\n", t2);
-+}
-+
-+static int
-+doChild(int clientId, int min, int max, int debug, int ttype)
-+{
-+ CState state; /* status of clients */
-+
-+ struct timeval tv1; /* start up time */
-+ fd_set input_mask;
-+ int nsocks = 0; /* return from
select(2) */
-+ int sock = 0;
-+
-+ gettimeofday(&tv1, NULL);
-+ srand((unsigned int) tv1.tv_usec + clientId );
-+
-+ memset((char *)&state,0,sizeof(CState));
-+ /* make connections to the database */
-+ state.id = clientId;
-+ if ((state.con = doConnect()) == NULL)
-+ exit(1);
-+
-+ state.maxAct = max - min + 1;
-+ /* send start up queries in async manner */
-+ switch (ttype)
-+ {
-+ case WITH_TRANSACTION :
-+ case TPC_B_LIKE :
-+ doMix(&state, debug, ttype);
-+ break;
-+ case CUSTOM_QUERY :
-+ doCustom(&state, debug, ttype);
-+ break;
-+ default :
-+ doOne(&state, debug, ttype);
-+ break;
-+ }
-+
-+ remains = max;
-+ for (;;)
-+ {
-+ if (remains < min || !state.con)
-+ {
-+ break;
-+ }
-+
-+ FD_ZERO(&input_mask);
-+
-+ if (ttype != CUSTOM_QUERY || commands[state.state]->type !=
META_COMMAND)
-+ {
-+ if (state.con == NULL)
-+ {
-+ if ((state.con = doConnect()) == NULL)
-+ {
-+ exit(1);
-+ }
-+ }
-+ sock = PQsocket(state.con);
-+
-+ if (sock < 0)
-+ {
-+ fprintf(stderr, "Client %d: PQsocket
failed\n", clientId);
-+ disconnect_all(&state);
-+ exit(1);
-+ }
-+ FD_SET(sock, &input_mask);
-+
-+ if ((nsocks = select(sock + 1, &input_mask, (fd_set
*) NULL,
-+ (fd_set *) NULL,
(struct timeval *) NULL)) < 0)
-+ {
-+ if (errno == EINTR)
-+ continue;
-+ /* must be something wrong */
-+ disconnect_all(&state);
-+ fprintf(stderr, "select failed: %s\n",
strerror(errno));
-+ exit(1);
-+ }
-+ else if (nsocks == 0)
-+ { /*
timeout */
-+ fprintf(stderr, "select timeout\n");
-+ fprintf(stderr, "client %d:state %d cnt %d
ecnt %d listen %d\n",
-+ clientId, state.state,
state.cnt, state.ecnt, state.listen);
-+ exit(0);
-+ }
-+ }
-+
-+ /* ok, backend returns reply */
-+ if (state.con && (FD_ISSET(PQsocket(state.con), &input_mask)
-+ || (ttype == CUSTOM_QUERY
-+ &&
commands[state.state]->type == META_COMMAND)))
-+ {
-+ switch (ttype)
-+ {
-+ case WITH_TRANSACTION :
-+ case TPC_B_LIKE :
-+ doMix(&state, debug, ttype);
-+ break;
-+ case CUSTOM_QUERY :
-+ doCustom(&state, debug, ttype);
-+ break;
-+ default :
-+ doOne(&state, debug, ttype);
-+ break;
-+ }
-+ }
-+ }
-+ disconnect_all(&state);
-+ return 1;
-+}
-+
-+static int
-+doClient(int debug, int ttype)
-+{
-+ pid_t pid;
-+ int i;
-+ int min,max;
-+ int base,mo;
-+
-+ base = nxacts / nclients;
-+ mo = nxacts % nclients;
-+ min = max = 0;
-+ for ( i = 0 ; i < nclients ; i ++)
-+ {
-+ min = max + 1;
-+ max += base;
-+ if (mo > 0)
-+ {
-+ max += 1;
-+ mo --;
-+ }
-+ pid = fork();
-+ if (pid == 0)
-+ {
-+ doChild(i, min, max, debug, ttype);
-+ exit(0);
-+ }
-+ }
-+ while ( wait(NULL) > 0)
-+ ;
-+ return 1;
-+}
-+
-+int
-+main(int argc, char **argv)
-+{
-+ int c;
-+ int is_init_mode = 0; /* initialize
mode? */
-+ int is_no_vacuum = 0; /* no vacuum
at all before
-+
* testing? */
-+ int is_full_vacuum = 0; /* do full
vacuum before testing? */
-+ int debug = 0; /* debug flag */
-+ int ttype = TPC_B_LIKE; /*
transaction type */
-+ char *filename = NULL;
-+
-+ struct timeval tv1; /* start up time */
-+ struct timeval tv2; /* after establishing all
connections to
-+ * the
backend */
-+ struct timeval tv3; /* end time */
-+
-+#if !(defined(__CYGWIN__) || defined(__MINGW32__))
-+ struct rlimit rlim;
-+#endif
-+
-+ PGconn *con;
-+ PGresult *res;
-+ char *env;
-+
-+ if ((env = getenv("PGHOST")) != NULL && *env != '\0')
-+ pghost = env;
-+ if ((env = getenv("PGPORT")) != NULL && *env != '\0')
-+ pgport = env;
-+ else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
-+ login = env;
-+
-+ while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:u:P:CNSlTUIf:")) != -1)
-+ {
-+ switch (c)
-+ {
-+ case 'i':
-+ is_init_mode++;
-+ break;
-+ case 'h':
-+ pghost = optarg;
-+ break;
-+ case 'n':
-+ is_no_vacuum++;
-+ break;
-+ case 'v':
-+ is_full_vacuum++;
-+ break;
-+ case 'p':
-+ pgport = optarg;
-+ break;
-+ case 'd':
-+ debug++;
-+ break;
-+ case 'S':
-+ ttype = SELECT_ONLY;
-+ break;
-+ case 'I':
-+ ttype = INSERT_ONLY;
-+ break;
-+ case 'U':
-+ ttype = UPDATE_ONLY;
-+ break;
-+ case 'T':
-+ ttype = WITH_TRANSACTION;
-+ break;
-+ case 'c':
-+ nclients = atoi(optarg);
-+ if (nclients <= 0 || nclients > MAXCLIENTS)
-+ {
-+ fprintf(stderr, "invalid number of
clients: %d\n", nclients);
-+ exit(1);
-+ }
-+#if !(defined(__CYGWIN__) || defined(__MINGW32__))
-+#ifdef RLIMIT_NOFILE /* most platform uses RLIMIT_NOFILE */
-+ if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
-+ {
-+#else /* but BSD doesn't
... */
-+ if (getrlimit(RLIMIT_OFILE, &rlim) == -1)
-+ {
-+#endif /* HAVE_RLIMIT_NOFILE */
-+ fprintf(stderr, "getrlimit failed.
reason: %s\n", strerror(errno));
-+ exit(1);
-+ }
-+ if (rlim.rlim_cur <= (nclients + 2))
-+ {
-+ fprintf(stderr, "You need at least %d
open files resource but you are only allowed to use %ld.\n", nclients + 2,
(long) rlim.rlim_cur);
-+ fprintf(stderr, "Use limit/ulimt to
increase the limit before using pgbench.\n");
-+ exit(1);
-+ }
-+#endif /* #if !(defined(__CYGWIN__) || defined(__MINGW32__)) */
-+ break;
-+ case 'C':
-+ is_connect = 1;
-+ break;
-+ case 's':
-+ tps = atoi(optarg);
-+ if (tps <= 0)
-+ {
-+ fprintf(stderr, "invalid scaling
factor: %d\n", tps);
-+ exit(1);
-+ }
-+ break;
-+ case 't':
-+ nxacts = atoi(optarg);
-+ if (nxacts <= 0)
-+ {
-+ fprintf(stderr, "invalid number of
transactions: %d\n", nxacts);
-+ exit(1);
-+ }
-+ break;
-+ case 'u':
-+ login = optarg;
-+ break;
-+ case 'P':
-+ pwd = optarg;
-+ break;
-+ case 'l':
-+ use_log = true;
-+ break;
-+ case 'f':
-+ ttype = CUSTOM_QUERY;
-+ filename = optarg;
-+ break;
-+ default:
-+ usage();
-+ exit(1);
-+ break;
-+ }
-+ }
-+
-+ if (argc > optind)
-+ dbName = argv[optind];
-+ else
-+ {
-+ if ((env = getenv("PGDATABASE")) != NULL && *env != '\0')
-+ dbName = env;
-+ else if (login != NULL && *login != '\0')
-+ dbName = login;
-+ else
-+ dbName = "";
-+ }
-+
-+ if (is_init_mode)
-+ {
-+ init();
-+ exit(0);
-+ }
-+
-+ if (use_log)
-+ {
-+ char logpath[64];
-+
-+ snprintf(logpath, 64, "pgbench_log.%d", getpid());
-+ LOGFILE = fopen(logpath, "w");
-+
-+ if (LOGFILE == NULL)
-+ {
-+ fprintf(stderr, "Couldn't open logfile \"%s\": %s",
logpath, strerror(errno));
-+ exit(1);
-+ }
-+ }
-+
-+ if (debug)
-+ {
-+ printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName:
%s\n",
-+ pghost, pgport, nclients, nxacts, dbName);
-+ }
-+
-+ /* opening connection... */
-+ con = doConnect();
-+ if (con == NULL)
-+ exit(1);
-+
-+ if (PQstatus(con) == CONNECTION_BAD)
-+ {
-+ fprintf(stderr, "Connection to database '%s' failed.\n",
dbName);
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+
-+ if (ttype == CUSTOM_QUERY)
-+ {
-+ PQfinish(con);
-+ if (process_file(filename) == false)
-+ exit(1);
-+ }
-+ else
-+ {
-+ /*
-+ * get the scaling factor that should be same as count(*) from
-+ * branches...
-+ */
-+ res = PQexec(con, "select count(*) from branches");
-+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ tps = atoi(PQgetvalue(res, 0, 0));
-+ if (tps < 0)
-+ {
-+ fprintf(stderr, "count(*) from branches invalid
(%d)\n", tps);
-+ exit(1);
-+ }
-+ PQclear(res);
-+
-+ if (!is_no_vacuum)
-+ {
-+ fprintf(stderr, "starting vacuum...");
-+ res = PQexec(con, "vacuum branches");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+
-+ res = PQexec(con, "vacuum tellers");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+
-+ res = PQexec(con, "delete from history");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+ res = PQexec(con, "vacuum history");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s", PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+
-+ fprintf(stderr, "end.\n");
-+
-+ if (is_full_vacuum)
-+ {
-+ fprintf(stderr, "starting full vacuum...");
-+ res = PQexec(con, "vacuum analyze accounts");
-+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
-+ {
-+ fprintf(stderr, "%s",
PQerrorMessage(con));
-+ exit(1);
-+ }
-+ PQclear(res);
-+ fprintf(stderr, "end.\n");
-+ }
-+ }
-+ PQfinish(con);
-+ }
-+
-+ /* set random seed */
-+ gettimeofday(&tv1, NULL);
-+ srand((unsigned int) tv1.tv_usec);
-+ /* get start up time */
-+ gettimeofday(&tv1, NULL);
-+ /* time after connections set up */
-+ gettimeofday(&tv2, NULL);
-+
-+ doClient(debug, ttype);
-+
-+ /* get end time */
-+ gettimeofday(&tv3, NULL);
-+ printResults(ttype, nxacts, &tv1, &tv2, &tv3);
-+ if (LOGFILE)
-+ fclose(LOGFILE);
-+ return 1;
-+}
-diff -aruN postgresql-8.1.2/src/pgcluster/tool/pgcbench.sh
pgcluster-1.5.0rc7/src/pgcluster/tool/pgcbench.sh
---- postgresql-8.1.2/src/pgcluster/tool/pgcbench.sh 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/tool/pgcbench.sh 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,30 @@
-+#! /bin/bash
-+
-+set -e
-+
-+while getopts ih:nvp:dc:t:s:u:P:CNSlTUIf: opt; do
-+ case $opt in
-+ f)
-+ filename=$OPTARG
-+ ;;
-+ *)
-+ opts=(${opts[@]} -$opt $OPTARG)
-+ ;;
-+ esac
-+done
-+shift $(($OPTIND - 1))
-+dbname=$1
-+
-+tps=$(psql -At -c "SELECT count(*) FROM branches" $dbname)
-+
-+vacuumdb -t branches $dbname
-+vacuumdb -t tellers $dbname
-+psql -c "DELETE FROM history" $dbname
-+vacuumdb -t history $dbname
-+
-+if [ -z $filename ]; then
-+ pgcbench ${opts[@]} $@
-+else
-+ perl -pe "BEGIN { \$tps = $tps } s/\`([^\`]+)\`/eval \$1/eg" $filename \
-+ | pgcbench ${opts[@]} -f - $@
-+fi
-diff -aruN postgresql-8.1.2/src/pgcluster/tool/tpc-b_like.sql
pgcluster-1.5.0rc7/src/pgcluster/tool/tpc-b_like.sql
---- postgresql-8.1.2/src/pgcluster/tool/tpc-b_like.sql 1970-01-01
01:00:00.000000000 +0100
-+++ pgcluster-1.5.0rc7/src/pgcluster/tool/tpc-b_like.sql 2006-01-10
17:39:44.000000000 +0100
-@@ -0,0 +1,11 @@
-+\setrandom aid 1 `100000 * $tps`
-+\setrandom bid 1 `1 * $tps`
-+\setrandom tid 1 `10 * $tps`
-+\setrandom delta 1 1000
-+BEGIN
-+UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid
-+SELECT abalance FROM accounts WHERE aid = :aid
-+UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid
-+UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid
-+INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid,
:delta, current_timestamp)
-+END
diff --git a/database/postgresql/pgcluster-1.7.0rc1-patch.tar.gz
b/database/postgresql/pgcluster-1.7.0rc1-patch.tar.gz
new file mode 100644
index 0000000..3e4e89a
Binary files /dev/null and
b/database/postgresql/pgcluster-1.7.0rc1-patch.tar.gz differ



  • [SM-Commit] GIT changes to master grimoire by George Sherwood (69a3b0643fbf2e99a7dafb6fd1783c495e9b1b9e), George Sherwood, 12/12/2006

Archive powered by MHonArc 2.6.24.

Top of Page