[pgpool-hackers: 387] Re: Exception Manager for pgpool

Ahsan Hadi ahsan.hadi at enterprisedb.com
Tue Oct 29 16:51:43 JST 2013


On Mon, Oct 28, 2013 at 6:35 PM, Tatsuo Ishii <ishii at postgresql.org> wrote:

> Probably because I committed something yesterday, I got this:
>
> utils/pool_shmem.c: In function ‘shmem_exit’:
> utils/pool_shmem.c:136: error: ‘on_shmem_exit_index’ undeclared (first use
> in this function)
> utils/pool_shmem.c:136: error: (Each undeclared identifier is reported
> only once
> utils/pool_shmem.c:136: error: for each function it appears in.)
> utils/pool_shmem.c:137: error: ‘on_shmem_exit_list’ undeclared (first use
> in this function)
> utils/pool_shmem.c: In function ‘on_shmem_exit’:
> utils/pool_shmem.c:150: error: ‘on_shmem_exit_index’ undeclared (first use
> in this function)
> utils/pool_shmem.c:150: error: ‘MAX_ON_EXITS’ undeclared (first use in
> this function)
> utils/pool_shmem.c:154: error: ‘on_shmem_exit_list’ undeclared (first use
> in this function)
> utils/pool_shmem.c: In function ‘on_exit_reset’:
> utils/pool_shmem.c:170: error: ‘on_shmem_exit_index’ undeclared (first use
> in this function)
>
> Can you please rebase your patch? Or probably better for you, please

create a branch on git repo to work on exception manager import?
>

+1. We should create a working branch for exception/memory management
import and use that branch for any future check-ins on this project. The
branch can be rebased with master at the end of the project before it is
ready to be merged with the master branch.

Tatsuo,
Is that something you can do?

--
> Tatsuo Ishii
> SRA OSS, Inc. Japan
> English: http://www.sraoss.co.jp/index_en.php
> Japanese: http://www.sraoss.co.jp
>
> > Hi
> >
> > With you patch I get the compilation error,
> > gram.y:13173:12: error: ‘Oid’ undeclared (first use in this function)
> > So I have changed the your patch a little to get rid of this error, can
> you
> > please take a look at the attache patch if it works.
> >
> > I have also looked into this issue a bit more to figure out what causes
> the
> > compilation at your end to throw an error of typedef redefinition, and it
> > appears that reason I am not getting an error is because the version of
> GCC
> > installed on my machine contains c11 extension which allows the typedef
> > redefinition.
> > And by compiling the pgpool using gnu89 standard ./configure CFLAGS='-O0
> > -g3 -std=gnu89 -pedantic' produces the warning of typedef redefinition.
> >
> > In file included from /home/usama/PG/installed/include/libpq-fe.h:29:0,
> >                  from ../src/include/pool.h:34,
> >                  from main/pgpool_main.c:51:
> > /home/usama/PG/installed/include/postgres_ext.h:31:22: warning:
> > redefinition of typedef ‘PoolOid’ [-pedantic]
> > ../src/include/parser/pool_parser.h:43:22: note: previous declaration of
> > ‘PoolOid’ was here
> > /home/usama/PG/installed/include/postgres_ext.h:43:9: warning: ISO C90
> does
> > not support ‘long long’ [-Wlong-long]
> > In file included from main/pgpool_main.c:54:0:
> >
> >
> > Thanks
> > Muhammad Usama
> >
> >
> > On Sat, Oct 26, 2013 at 6:30 AM, Tatsuo Ishii <ishii at postgresql.org>
> wrote:
> >
> >> > Hi Tatsuo
> >> >
> >> >
> >> > On Wed, Oct 23, 2013 at 2:46 PM, Tatsuo Ishii <ishii at postgresql.org>
> >> wrote:
> >> >
> >> >> Usama,
> >> >>
> >> >> I still don't know why my gcc complains but I found a solution.
> >> >> I have made changes to src/include/parser/pool_parser.h.
> >> >>
> >> >> I added #include "postgres_ext.h".
> >> >>
> >> >> Then remove this because PoolOid seems not to be used anywhere in
> >> >> pgpool-II.
> >> >>
> >> >> typedef unsigned int PoolOid;
> >> >>
> >> >> So I removed this too.
> >> >>
> >> >> #define Oid PoolOid
> >> >>
> >> >> Then running the regression test, I found two tests failed.
> >> >>
> >> >> testing 056.bug63...failed.
> >> >> testing 058.bug68...failed.
> >> >>
> >> >> Theses tests are passed in master branch head. I will look into this
> >> >> more.
> >> >>
> >> >> Anyway I think your patch goes to the right direction.
> >> >>
> >> >
> >> > Thanks for looking into this issue and the patch. I am working on the
> >> next
> >> > todo for this task, and will also look into the regression failures
> you
> >> are
> >> > getting. Can you please create a separate branch for this work so that
> >> bugs
> >> > and new todos for this task can become granule and easier to manage
> and
> >> > review, and once we will get this thing stable we will merge it to the
> >> > master branch.
> >>
> >> I have made a patch for this. Please take a look at.
> >> --
> >> Tatsuo Ishii
> >> SRA OSS, Inc. Japan
> >> English: http://www.sraoss.co.jp/index_en.php
> >> Japanese: http://www.sraoss.co.jp
> >>
> >> >> Maybe now is the time to add Usama to one of pgpool-II committers?
> >> >>
> >> >
> >> > Thanks
> >> > Muhammad Usama
> >> >
> >> >
> >> >> --
> >> >> Tatsuo Ishii
> >> >> SRA OSS, Inc. Japan
> >> >> English: http://www.sraoss.co.jp/index_en.php
> >> >> Japanese: http://www.sraoss.co.jp
> >> >>
> >> >> >> Hi Tatsuo
> >> >> >>
> >> >> >> I have been trying to reproduce this compilation issue but unable
> to
> >> do
> >> >> so.
> >> >> >> I have compiled the patched code with GCC 4.6.3 and also with
> >> >> >> LLVM 5.0 and in both case I am able to successfully compile the
> code.
> >> >> >> Can you please guide me to reproduce the issue at my end as the
> Oid
> >> >> >> definition which is conflicting at your end is not changed by the
> >> patch.
> >> >> >
> >> >> > No idea. I just type "make" and got the error.
> >> >> >
> >> >> >> here is the gcc log of files compilation,
> >> >> >>
> >> >> >> gcc -DHAVE_CONFIG_H
> >> >> >>
> >> >>
> >>
> -DDEFAULT_CONFIGDIR=\"/home/usama/EDB/pgpool/elog_work/mypgpool/test/comanddel/installed/etc\"
> >> >> >> -I. -I../src/include  -D_GNU_SOURCE -I
> >> >> /home/usama/EDB/PG/installed/include
> >> >> >>   -O0 -g3 -Wall -Wmissing-prototypes -Wmissing-declarations -MT
> >> >> main/main.o
> >> >> >> -MD -MP -MF $depbase.Tpo -c -o main/main.o main/main.c &&\
> >> >> >> mv -f $depbase.Tpo $depbase.Po
> >> >> >> main/main.c: In function ‘daemonize’:
> >> >> >> main/main.c:384:17: warning: variable ‘rc_chdir’ set but not used
> >> >> >> [-Wunused-but-set-variable]
> >> >> >> depbase=`echo main/pgpool_main.o | sed
> >> 's|[^/]*$|.deps/&|;s|\.o$||'`;\
> >> >> >> gcc -DHAVE_CONFIG_H
> >> >> >>
> >> >>
> >>
> -DDEFAULT_CONFIGDIR=\"/home/usama/EDB/pgpool/elog_work/mypgpool/test/comanddel/installed/etc\"
> >> >> >> -I. -I../src/include  -D_GNU_SOURCE -I
> >> >> /home/usama/EDB/PG/installed/include
> >> >> >>   -O0 -g3 -Wall -Wmissing-prototypes -Wmissing-declarations -MT
> >> >> >> main/pgpool_main.o -MD -MP -MF $depbase.Tpo -c -o
> main/pgpool_main.o
> >> >> >> main/pgpool_main.c &&\
> >> >> >> mv -f $depbase.Tpo $depbase.Po
> >> >> >> main/pgpool_main.c: In function ‘find_primary_node’:
> >> >> >> main/pgpool_main.c:1981:14: warning: variable ‘status’ set but not
> >> used
> >> >> >> [-Wunused-but-set-variable]
> >> >> >> ..
> >> >> >>
> >> >> >> pgpool2$ gcc --version
> >> >> >> gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
> >> >> >> Copyright (C) 2011 Free Software Foundation, Inc.
> >> >> >>
> >> >> >> And on OS/X the compilation is also successfull.
> >> >> >> gcc --version
> >> >> >> Configured with:
> >> --prefix=/Applications/Xcode.app/Contents/Developer/usr
> >> >> >> --with-gxx-include-dir=/usr/include/c++/4.2.1
> >> >> >> Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
> >> >> >> Target: x86_64-apple-darwin12.5.0
> >> >> >>
> >> >> >> Thanks
> >> >> >> Usama
> >> >> >>
> >> >> >>
> >> >> >>
> >> >> >> On Sat, Oct 12, 2013 at 5:41 AM, Tatsuo Ishii <
> ishii at postgresql.org>
> >> >> wrote:
> >> >> >>
> >> >> >>> I have freshly checkout git master and applied your patch.
> >> >> >>> I got this:
> >> >> >>>
> >> >> >>>         gcc -DHAVE_CONFIG_H
> >> -DDEFAULT_CONFIGDIR=\"/home/t-ishii/work/
> >> >> >>>
> >> >>
> >>
> git.postgresql.org/exception/pgpool2/src/test/regression/temp/installed/etc\
> >> >> "
> >> >> >>> -I. -I../src/include  -D_GNU_SOURCE -I /usr/local/pgsql/include
>   -g
> >> >> -O2
> >> >> >>> -Wall -Wmissing-prototypes -Wmissing-declarations -MT
> >> >> main/pgpool_main.o
> >> >> >>> -MD -MP -MF $depbase.Tpo -c -o main/pgpool_main.o
> main/pgpool_main.c
> >> >> &&\
> >> >> >>>         mv -f $depbase.Tpo $depbase.Po
> >> >> >>> In file included from /usr/local/pgsql/include/libpq-fe.h:29,
> >> >> >>>                  from ../src/include/pool.h:34,
> >> >> >>>                  from main/pgpool_main.c:51:
> >> >> >>> /usr/local/pgsql/include/postgres_ext.h:31: error: redefinition
> of
> >> >> typedef
> >> >> >>> ‘PoolOid’
> >> >> >>> ../src/include/parser/pool_parser.h:43: note: previous
> declaration
> >> of
> >> >> >>> ‘PoolOid’ was here
> >> >> >>>
> >> >> >>> This is caused by the conflict in postgres_ext.h:
> >> >> >>> typedef unsigned int Oid;
> >> >> >>>
> >> >> >>> and
> >> >> >>>
> >> >> >>> ./include/parser/pool_parser.h:typedef unsigned int PoolOid;
> >> >> >>> ./include/parser/pool_parser.h:#define Oid PoolOid
> >> >> >>>
> >> >> >>> This is gcc 4.4.5.
> >> >> >>> --
> >> >> >>> Tatsuo Ishii
> >> >> >>> SRA OSS, Inc. Japan
> >> >> >>> English: http://www.sraoss.co.jp/index_en.php
> >> >> >>> Japanese: http://www.sraoss.co.jp
> >> >> >>>
> >> >> >>> > Hi
> >> >> >>> >
> >> >> >>> > Seems like the repository was changed after I had generated the
> >> >> patch.
> >> >> >>> > Please find the updated patch rebased with the current state of
> >> git.
> >> >> >>> >
> >> >> >>> >
> >> >> >>> > Thanks
> >> >> >>> > Usama
> >> >> >>> >
> >> >> >>> >
> >> >> >>> >
> >> >> >>> > On Fri, Oct 11, 2013 at 9:47 AM, Ahsan Hadi <
> >> >> ahsan.hadi at enterprisedb.com
> >> >> >>> >wrote:
> >> >> >>> >
> >> >> >>> >> Usama,
> >> >> >>> >> Please take a look.
> >> >> >>> >>
> >> >> >>> >> Tatsuo,
> >> >> >>> >> I was apply to apply this patch cleanly on pgpool master and
> test
> >> >> before
> >> >> >>> >> Usama sent the patch. It is likely that we have done some
> changes
> >> >> to the
> >> >> >>> >> master branch since then..
> >> >> >>> >>
> >> >> >>> >>
> >> >> >>> >> On Fri, Oct 11, 2013 at 4:03 AM, Tatsuo Ishii <
> >> ishii at postgresql.org
> >> >> >>> >wrote:
> >> >> >>> >>
> >> >> >>> >>> Usama,
> >> >> >>> >>>
> >> >> >>> >>> I have applied your patch and got following error:
> >> >> >>> >>>
> >> >> >>> >>> Hunk #12 FAILED at 499.
> >> >> >>> >>> 1 out of 12 hunks FAILED -- saving rejects to file
> >> >> src/main/main.c.rej
> >> >> >>> >>>
> >> >> >>> >>> I also attached main.c.rej.
> >> >> >>> >>> --
> >> >> >>> >>> Tatsuo Ishii
> >> >> >>> >>> SRA OSS, Inc. Japan
> >> >> >>> >>> English: http://www.sraoss.co.jp/index_en.php
> >> >> >>> >>> Japanese: http://www.sraoss.co.jp
> >> >> >>> >>>
> >> >> >>> >>> > Muhammad,
> >> >> >>> >>> >
> >> >> >>> >>> > Thank you for your great work! I'll look into this.
> >> >> >>> >>> > --
> >> >> >>> >>> > Tatsuo Ishii
> >> >> >>> >>> > SRA OSS, Inc. Japan
> >> >> >>> >>> > English: http://www.sraoss.co.jp/index_en.php
> >> >> >>> >>> > Japanese: http://www.sraoss.co.jp
> >> >> >>> >>> >
> >> >> >>> >>> >> Hi
> >> >> >>> >>> >>
> >> >> >>> >>> >> I am working on adding the exception manager in pgpool
> and my
> >> >> plan
> >> >> >>> of
> >> >> >>> >>> >> action for this is to use the Postgres exception manager
> API
> >> >> (elog
> >> >> >>> and
> >> >> >>> >>> >> friends). Since the exception manager in Postgres uses the
> >> long
> >> >> >>> jump,
> >> >> >>> >>> so
> >> >> >>> >>> >> importing this API in pgpool will effect all existing
> pgpool
> >> >> code
> >> >> >>> flows
> >> >> >>> >>> >> especially in case of an error. and lot of care will be
> >> >> required for
> >> >> >>> >>> this
> >> >> >>> >>> >> integration, and secondly the elog API along with its
> friends
> >> >> will
> >> >> >>> >>> touch
> >> >> >>> >>> >> almost all parts of pgpool source code which will add up
> to a
> >> >> very
> >> >> >>> huge
> >> >> >>> >>> >> patch.
> >> >> >>> >>> >> So instead throwing a very huge patch to the community my
> >> plan
> >> >> is to
> >> >> >>> >>> divide
> >> >> >>> >>> >> this task into multiple smaller sub tasks so that it
> would be
> >> >> easier
> >> >> >>> >>> >> maintain and review the patch.
> >> >> >>> >>> >>
> >> >> >>> >>> >> Cut to the chase, attached is the  first of the series of
> >> >> related
> >> >> >>> >>> patches
> >> >> >>> >>> >> to come.This is the first cut patch for implementing the
> >> >> exception
> >> >> >>> >>> manager
> >> >> >>> >>> >> in pgpool. As described above the exception manager and
> >> related
> >> >> >>> code is
> >> >> >>> >>> >> borrowed from PostgreSQL source code.
> >> >> >>> >>> >> and the exception manager (elog API) is very closely tied
> >> with
> >> >> >>> memory
> >> >> >>> >>> >> manager in PostgreSQL (palloc API) so the patch also
> borrows
> >> the
> >> >> >>> PG's
> >> >> >>> >>> >> memory manager.
> >> >> >>> >>> >>
> >> >> >>> >>> >> Below is the little description of things part of this
> patch.
> >> >> >>> >>> >>
> >> >> >>> >>> >> -- Exception manager API of Postgres is added to pgpool,
> The
> >> API
> >> >> >>> >>> consists
> >> >> >>> >>> >> of elog.c and elog.h files. Since this API is very
> extensive
> >> >> and is
> >> >> >>> >>> >> designed for PostgreSQL so to fit it properly into pgpool
> I
> >> have
> >> >> >>> >>> modified
> >> >> >>> >>> >> it a little bit, and most of the modifications are
> related to
> >> >> >>> removal
> >> >> >>> >>> of
> >> >> >>> >>> >> code which is not required for pgpool.
> >> >> >>> >>> >>
> >> >> >>> >>> >> -- Added on_proc_exit callback mechanism of Postgres. To
> >> >> facilitate
> >> >> >>> the
> >> >> >>> >>> >> cleanup at exit time.
> >> >> >>> >>> >>
> >> >> >>> >>> >> -- Added PostgreSQL's memory manager (palloc API). This
> >> >> includes the
> >> >> >>> >>> client
> >> >> >>> >>> >> side palloc functions placed in 'src/tools' directory
> >> >> (fe_memutils)
> >> >> >>> >>> >>
> >> >> >>> >>> >> -- Removed the existing memory manager which was very
> >> >> minimalistic
> >> >> >>> and
> >> >> >>> >>> was
> >> >> >>> >>> >> not integrated in all parts of the code.
> >> >> >>> >>> >>
> >> >> >>> >>> >> -- I have also tried to reflector some portions of code to
> >> make
> >> >> the
> >> >> >>> >>> code
> >> >> >>> >>> >> more readable at first glance. This includes
> >> >> >>> >>> >>
> >> >> >>> >>> >> - dividing the main.c file into two files main.c and
> >> >> pgpool_main.c,
> >> >> >>> >>> Now the
> >> >> >>> >>> >> main.c file only contains the code related to early
> >> >> initialisations
> >> >> >>> of
> >> >> >>> >>> >> pgpool and parsing the command line options and related
> code.
> >> >> The
> >> >> >>> >>> actual
> >> >> >>> >>> >> logic of the pgpool main process is moved to new
> >> pgpool_main.c
> >> >> file.
> >> >> >>> >>> >> - breaking up some large functions in child.c into smaller
> >> >> >>> functions.
> >> >> >>> >>> >> - rewrite the pgpool's main loop logic to make the code
> more
> >> >> >>> readable.
> >> >> >>> >>> >>
> >> >> >>> >>> >>
> >> >> >>> >>> >> Remaining TODOs on this front.
> >> >> >>> >>> >>
> >> >> >>> >>> >> -- The current patch only integrates the memory and
> exception
> >> >> >>> manager
> >> >> >>> >>> in
> >> >> >>> >>> >> main process and connection creation segment of pgpool
> child
> >> >> >>> process.
> >> >> >>> >>> >> integration of newly added APIs in pcp and worker child
> >> process
> >> >> >>> codes
> >> >> >>> >>> will
> >> >> >>> >>> >> be done be next patch.
> >> >> >>> >>> >>
> >> >> >>> >>> >> -- Integration of newly added API into query processor
> logic
> >> in
> >> >> >>> child
> >> >> >>> >>> >> process. ( this will be the toughest part)
> >> >> >>> >>> >>
> >> >> >>> >>> >> -- elog.c and elog.h files needs some cleanups and
> changes (
> >> to
> >> >> >>> remove
> >> >> >>> >>> >> unwanted functions and data members of ErrorData
> structure)
> >> but
> >> >> this
> >> >> >>> >>> will
> >> >> >>> >>> >> be done at the end when we will have 100% surety if
> >> something in
> >> >> >>> there
> >> >> >>> >>> is
> >> >> >>> >>> >> required or not.
> >> >> >>> >>> >>
> >> >> >>> >>> >>
> >> >> >>> >>> >> Thanks
> >> >> >>> >>> >> Muhammad Usama
> >> >> >>> >>> > _______________________________________________
> >> >> >>> >>> > pgpool-hackers mailing list
> >> >> >>> >>> > pgpool-hackers at pgpool.net
> >> >> >>> >>> > http://www.pgpool.net/mailman/listinfo/pgpool-hackers
> >> >> >>> >>>
> >> >> >>> >>> --- src/main/main.c
> >> >> >>> >>> +++ src/main/main.c
> >> >> >>> >>> @@ -499,1915 +-23,60 @@
> >> >> >>> >>>         fd = open(pool_config->pid_file_name,
> O_CREAT|O_WRONLY,
> >> >> >>> >>> S_IRUSR|S_IWUSR);
> >> >> >>> >>>         if (fd == -1)
> >> >> >>> >>>         {
> >> >> >>> >>> -               pool_error("could not open pid file as %s.
> >> reason:
> >> >> %s",
> >> >> >>> >>> -
>  pool_config->pid_file_name,
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               pool_shmem_exit(1);
> >> >> >>> >>> -               exit(1);
> >> >> >>> >>> +               ereport(FATAL,
> >> >> >>> >>> +                       (errmsg("could not open pid file as
> %s.
> >> >> reason:
> >> >> >>> >>> %s",
> >> >> >>> >>> +
>  pool_config->pid_file_name,
> >> >> >>> >>> strerror(errno))));
> >> >> >>> >>>         }
> >> >> >>> >>>         snprintf(pidbuf, sizeof(pidbuf), "%d",
> (int)getpid());
> >> >> >>> >>>         if (write(fd, pidbuf, strlen(pidbuf)+1) == -1)
> >> >> >>> >>>         {
> >> >> >>> >>> -               pool_error("could not write pid file as %s.
> >> reason:
> >> >> >>> %s",
> >> >> >>> >>> -
>  pool_config->pid_file_name,
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>>                 close(fd);
> >> >> >>> >>> -               pool_shmem_exit(1);
> >> >> >>> >>> -               exit(1);
> >> >> >>> >>> +               ereport(FATAL,
> >> >> >>> >>> +                       (errmsg("could not write pid file as
> %s.
> >> >> >>> reason:
> >> >> >>> >>> %s",
> >> >> >>> >>> +
>  pool_config->pid_file_name,
> >> >> >>> >>> strerror(errno))));
> >> >> >>> >>>         }
> >> >> >>> >>>         if (fsync(fd) == -1)
> >> >> >>> >>>         {
> >> >> >>> >>> -               pool_error("could not fsync pid file as %s.
> >> reason:
> >> >> >>> %s",
> >> >> >>> >>> -
>  pool_config->pid_file_name,
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>>                 close(fd);
> >> >> >>> >>> -               pool_shmem_exit(1);
> >> >> >>> >>> -               exit(1);
> >> >> >>> >>> +               ereport(FATAL,
> >> >> >>> >>> +                       (errmsg("could not fsync pid file as
> %s.
> >> >> >>> reason:
> >> >> >>> >>> %s",
> >> >> >>> >>> +
>  pool_config->pid_file_name,
> >> >> >>> >>> strerror(errno))));
> >> >> >>> >>>         }
> >> >> >>> >>>         if (close(fd) == -1)
> >> >> >>> >>>         {
> >> >> >>> >>> -               pool_error("could not close pid file as %s.
> >> reason:
> >> >> >>> %s",
> >> >> >>> >>> -
>  pool_config->pid_file_name,
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               pool_shmem_exit(1);
> >> >> >>> >>> -               exit(1);
> >> >> >>> >>> +               ereport(FATAL,
> >> >> >>> >>> +                       (errmsg("could not close pid file as
> %s.
> >> >> >>> reason:
> >> >> >>> >>> %s",
> >> >> >>> >>> +
>  pool_config->pid_file_name,
> >> >> >>> >>> strerror(errno))));
> >> >> >>> >>>         }
> >> >> >>> >>> +       /* register the call back to delete the pid file at
> >> system
> >> >> >>> exit */
> >> >> >>> >>> +       on_proc_exit(FileUnlink, (Datum)
> >> >> pool_config->pid_file_name);
> >> >> >>> >>>  }
> >> >> >>> >>>
> >> >> >>> >>>  /*
> >> >> >>> >>> -* Read the status file
> >> >> >>> >>> -*/
> >> >> >>> >>> -static int read_status_file(bool discard_status)
> >> >> >>> >>> + * get_config_file_name: return full path of pgpool.conf.
> >> >> >>> >>> + */
> >> >> >>> >>> +char *get_config_file_name(void)
> >> >> >>> >>>  {
> >> >> >>> >>> -       FILE *fd;
> >> >> >>> >>> -       char fnamebuf[POOLMAXPATHLEN];
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -       bool someone_wakeup = false;
> >> >> >>> >>> -
> >> >> >>> >>> -       snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s",
> >> >> >>> >>> pool_config->logdir, STATUS_FILE_NAME);
> >> >> >>> >>> -       fd = fopen(fnamebuf, "r");
> >> >> >>> >>> -       if (!fd)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("Backend status file %s does not
> >> exist",
> >> >> >>> >>> fnamebuf);
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * If discard_status is true, unlink pgpool_status
> and
> >> >> >>> >>> -        * do not restore previous status.
> >> >> >>> >>> -        */
> >> >> >>> >>> -       if (discard_status)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               fclose(fd);
> >> >> >>> >>> -               if (unlink(fnamebuf) == 0)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("Backend status file %s
> >> >> discarded",
> >> >> >>> >>> fnamebuf);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               else
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_error("Failed to discard backend
> >> >> status
> >> >> >>> file
> >> >> >>> >>> %s reason:%s", fnamebuf, strerror(errno));
> >> >> >>> >>> -               }
> >> >> >>> >>> -               return 0;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (fread(&backend_rec, 1, sizeof(backend_rec), fd)
> !=
> >> >> >>> >>> sizeof(backend_rec))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("Could not read backend status
> file
> >> as
> >> >> %s.
> >> >> >>> >>> reason: %s",
> >> >> >>> >>> -                                  fnamebuf,
> strerror(errno));
> >> >> >>> >>> -               fclose(fd);
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -       fclose(fd);
> >> >> >>> >>> -
> >> >> >>> >>> -       for (i=0;i<
> pool_config->backend_desc->num_backends;i++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (backend_rec.status[i] == CON_DOWN)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       BACKEND_INFO(i).backend_status =
> >> CON_DOWN;
> >> >> >>> >>> -                       pool_log("read_status_file: %d th
> >> backend
> >> >> is
> >> >> >>> set
> >> >> >>> >>> to down status", i);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               else
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       BACKEND_INFO(i).backend_status =
> >> >> >>> CON_CONNECT_WAIT;
> >> >> >>> >>> -                       someone_wakeup = true;
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * If no one woke up, we regard the status file bogus
> >> >> >>> >>> -        */
> >> >> >>> >>> -       if (someone_wakeup == false)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               for (i=0;i<
> >> >> >>> pool_config->backend_desc->num_backends;i++)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       BACKEND_INFO(i).backend_status =
> >> >> >>> CON_CONNECT_WAIT;
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       return 0;
> >> >> >>> >>> +       return conf_file;
> >> >> >>> >>>  }
> >> >> >>> >>>
> >> >> >>> >>>  /*
> >> >> >>> >>> -* Write the pid file
> >> >> >>> >>> -*/
> >> >> >>> >>> -static int write_status_file(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       FILE *fd;
> >> >> >>> >>> -       char fnamebuf[POOLMAXPATHLEN];
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s",
> >> >> >>> >>> pool_config->logdir, STATUS_FILE_NAME);
> >> >> >>> >>> -       fd = fopen(fnamebuf, "w");
> >> >> >>> >>> -       if (!fd)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("Could not open status file %s",
> >> >> fnamebuf);
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       memset(&backend_rec, 0, sizeof(backend_rec));
> >> >> >>> >>> -
> >> >> >>> >>> -       for (i=0;i<
> pool_config->backend_desc->num_backends;i++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               backend_rec.status[i] =
> >> >> BACKEND_INFO(i).backend_status;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (fwrite(&backend_rec, 1, sizeof(backend_rec), fd)
> !=
> >> >> >>> >>> sizeof(backend_rec))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("Could not write backend status
> file
> >> as
> >> >> %s.
> >> >> >>> >>> reason: %s",
> >> >> >>> >>> -                                  fnamebuf,
> strerror(errno));
> >> >> >>> >>> -               fclose(fd);
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -       fclose(fd);
> >> >> >>> >>> -       return 0;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * fork a child for PCP
> >> >> >>> >>> - */
> >> >> >>> >>> -pid_t pcp_fork_a_child(int unix_fd, int inet_fd, char
> >> >> *pcp_conf_file)
> >> >> >>> >>> -{
> >> >> >>> >>> -       pid_t pid;
> >> >> >>> >>> -
> >> >> >>> >>> -       pid = fork();
> >> >> >>> >>> -
> >> >> >>> >>> -       if (pid == 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               close(pipe_fds[0]);
> >> >> >>> >>> -               close(pipe_fds[1]);
> >> >> >>> >>> -
> >> >> >>> >>> -               myargv = save_ps_display_args(myargc,
> myargv);
> >> >> >>> >>> -
> >> >> >>> >>> -               /* call PCP child main */
> >> >> >>> >>> -               POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -               health_check_timer_expired = 0;
> >> >> >>> >>> -               reload_config_request = 0;
> >> >> >>> >>> -               run_as_pcp_child = true;
> >> >> >>> >>> -               pcp_do_child(unix_fd, inet_fd,
> pcp_conf_file);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else if (pid == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("fork() failed. reason: %s",
> >> >> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       return pid;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> -* fork a child
> >> >> >>> >>> -*/
> >> >> >>> >>> -pid_t fork_a_child(int unix_fd, int inet_fd, int id)
> >> >> >>> >>> -{
> >> >> >>> >>> -       pid_t pid;
> >> >> >>> >>> -
> >> >> >>> >>> -       pid = fork();
> >> >> >>> >>> -
> >> >> >>> >>> -       if (pid == 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               /* Before we unconditionally closed
> pipe_fds[0]
> >> and
> >> >> >>> >>> pipe_fds[1]
> >> >> >>> >>> -                * here, which is apparently wrong since in
> the
> >> >> start
> >> >> >>> up
> >> >> >>> >>> of
> >> >> >>> >>> -                * pgpool, pipe(2) is not called yet and it
> >> >> mistakenly
> >> >> >>> >>> closes
> >> >> >>> >>> -                * fd 0. Now we check the fd > 0 before
> close(),
> >> >> >>> expecting
> >> >> >>> >>> -                * pipe returns fds greater than 0.  Note
> that
> >> we
> >> >> >>> cannot
> >> >> >>> >>> -                * unconditionally remove close(2) calls
> since
> >> >> >>> >>> fork_a_child()
> >> >> >>> >>> -                * may be called *after* pgpool starting up.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               if (pipe_fds[0] > 0)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       close(pipe_fds[0]);
> >> >> >>> >>> -                       close(pipe_fds[1]);
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               myargv = save_ps_display_args(myargc,
> myargv);
> >> >> >>> >>> -
> >> >> >>> >>> -               /* call child main */
> >> >> >>> >>> -               POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -               health_check_timer_expired = 0;
> >> >> >>> >>> -               reload_config_request = 0;
> >> >> >>> >>> -               my_proc_id = id;
> >> >> >>> >>> -               run_as_pcp_child = false;
> >> >> >>> >>> -               do_child(unix_fd, inet_fd);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else if (pid == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("fork() failed. reason: %s",
> >> >> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       return pid;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> -* fork worker child process
> >> >> >>> >>> -*/
> >> >> >>> >>> -pid_t worker_fork_a_child()
> >> >> >>> >>> -{
> >> >> >>> >>> -       pid_t pid;
> >> >> >>> >>> -
> >> >> >>> >>> -       pid = fork();
> >> >> >>> >>> -
> >> >> >>> >>> -       if (pid == 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               /* Before we unconditionally closed
> pipe_fds[0]
> >> and
> >> >> >>> >>> pipe_fds[1]
> >> >> >>> >>> -                * here, which is apparently wrong since in
> the
> >> >> start
> >> >> >>> up
> >> >> >>> >>> of
> >> >> >>> >>> -                * pgpool, pipe(2) is not called yet and it
> >> >> mistakenly
> >> >> >>> >>> closes
> >> >> >>> >>> -                * fd 0. Now we check the fd > 0 before
> close(),
> >> >> >>> expecting
> >> >> >>> >>> -                * pipe returns fds greater than 0.  Note
> that
> >> we
> >> >> >>> cannot
> >> >> >>> >>> -                * unconditionally remove close(2) calls
> since
> >> >> >>> >>> fork_a_child()
> >> >> >>> >>> -                * may be called *after* pgpool starting up.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               if (pipe_fds[0] > 0)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       close(pipe_fds[0]);
> >> >> >>> >>> -                       close(pipe_fds[1]);
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               myargv = save_ps_display_args(myargc,
> myargv);
> >> >> >>> >>> -
> >> >> >>> >>> -               /* call child main */
> >> >> >>> >>> -               POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -               health_check_timer_expired = 0;
> >> >> >>> >>> -               reload_config_request = 0;
> >> >> >>> >>> -               do_worker_child();
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else if (pid == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("fork() failed. reason: %s",
> >> >> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       return pid;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> -* create inet domain socket
> >> >> >>> >>> -*/
> >> >> >>> >>> -static int create_inet_domain_socket(const char *hostname,
> >> const
> >> >> int
> >> >> >>> >>> port)
> >> >> >>> >>> -{
> >> >> >>> >>> -       struct sockaddr_in addr;
> >> >> >>> >>> -       int fd;
> >> >> >>> >>> -       int status;
> >> >> >>> >>> -       int one = 1;
> >> >> >>> >>> -       int len;
> >> >> >>> >>> -       int backlog;
> >> >> >>> >>> -
> >> >> >>> >>> -       fd = socket(AF_INET, SOCK_STREAM, 0);
> >> >> >>> >>> -       if (fd == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("Failed to create INET domain
> socket.
> >> >> >>> reason:
> >> >> >>> >>> %s", strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char
> *)
> >> >> &one,
> >> >> >>> >>> -                                       sizeof(one))) == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("setsockopt() failed. reason: %s",
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       memset((char *) &addr, 0, sizeof(addr));
> >> >> >>> >>> -       addr.sin_family = AF_INET;
> >> >> >>> >>> -
> >> >> >>> >>> -       if (strcmp(hostname, "*")==0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               addr.sin_addr.s_addr = htonl(INADDR_ANY);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               struct hostent *hostinfo;
> >> >> >>> >>> -
> >> >> >>> >>> -               hostinfo = gethostbyname(hostname);
> >> >> >>> >>> -               if (!hostinfo)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_error("could not resolve host
> name
> >> >> \"%s\":
> >> >> >>> >>> %s", hostname, hstrerror(h_errno));
> >> >> >>> >>> -                       myexit(1);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               addr.sin_addr = *(struct in_addr *)
> >> >> hostinfo->h_addr;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       addr.sin_port = htons(port);
> >> >> >>> >>> -       len = sizeof(struct sockaddr_in);
> >> >> >>> >>> -       status = bind(fd, (struct sockaddr *)&addr, len);
> >> >> >>> >>> -       if (status == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               char *host = "", *serv = "";
> >> >> >>> >>> -               char hostname[NI_MAXHOST],
> servname[NI_MAXSERV];
> >> >> >>> >>> -               if (getnameinfo((struct sockaddr *) &addr,
> len,
> >> >> >>> hostname,
> >> >> >>> >>> sizeof(hostname), servname, sizeof(servname), 0) == 0) {
> >> >> >>> >>> -                       host = hostname;
> >> >> >>> >>> -                       serv = servname;
> >> >> >>> >>> -               }
> >> >> >>> >>> -               pool_error("bind(%s:%s) failed. reason: %s",
> >> host,
> >> >> >>> serv,
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       backlog = pool_config->num_init_children * 2;
> >> >> >>> >>> -       if (backlog > PGPOOLMAXLITSENQUEUELENGTH)
> >> >> >>> >>> -               backlog = PGPOOLMAXLITSENQUEUELENGTH;
> >> >> >>> >>> -
> >> >> >>> >>> -       status = listen(fd, backlog);
> >> >> >>> >>> -       if (status < 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("listen() failed. reason: %s",
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       return fd;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> -* create UNIX domain socket
> >> >> >>> >>> -*/
> >> >> >>> >>> -static int create_unix_domain_socket(struct sockaddr_un
> >> >> un_addr_tmp)
> >> >> >>> >>> -{
> >> >> >>> >>> -       struct sockaddr_un addr;
> >> >> >>> >>> -       int fd;
> >> >> >>> >>> -       int status;
> >> >> >>> >>> -       int len;
> >> >> >>> >>> -
> >> >> >>> >>> -       fd = socket(AF_UNIX, SOCK_STREAM, 0);
> >> >> >>> >>> -       if (fd == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("Failed to create UNIX domain
> socket.
> >> >> >>> reason:
> >> >> >>> >>> %s", strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       memset((char *) &addr, 0, sizeof(addr));
> >> >> >>> >>> -       addr.sun_family = AF_UNIX;
> >> >> >>> >>> -       snprintf(addr.sun_path, sizeof(addr.sun_path), "%s",
> >> >> >>> >>> un_addr_tmp.sun_path);
> >> >> >>> >>> -       len = sizeof(struct sockaddr_un);
> >> >> >>> >>> -       status = bind(fd, (struct sockaddr *)&addr, len);
> >> >> >>> >>> -       if (status == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("bind(%s) failed. reason: %s",
> >> >> >>> addr.sun_path,
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (chmod(un_addr_tmp.sun_path, 0777) == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("chmod() failed. reason: %s",
> >> >> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       status = listen(fd, PGPOOLMAXLITSENQUEUELENGTH);
> >> >> >>> >>> -       if (status < 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("listen() failed. reason: %s",
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               myexit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       return fd;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -static void myunlink(const char* path)
> >> >> >>> >>> -{
> >> >> >>> >>> -       if (unlink(path) == 0) return;
> >> >> >>> >>> -       pool_error("unlink(%s) failed: %s", path,
> >> strerror(errno));
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -static void myexit(int code)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       if (getpid() != mypid)
> >> >> >>> >>> -               return;
> >> >> >>> >>> -
> >> >> >>> >>> -       if (process_info != NULL) {
> >> >> >>> >>> -               POOL_SETMASK(&AuthBlockSig);
> >> >> >>> >>> -               exiting = 1;
> >> >> >>> >>> -               for (i = 0; i <
> pool_config->num_init_children;
> >> >> i++)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pid_t pid = process_info[i].pid;
> >> >> >>> >>> -                       if (pid)
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               kill(pid, SIGTERM);
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               /* wait for all children to exit */
> >> >> >>> >>> -               while (wait(NULL) > 0)
> >> >> >>> >>> -                       ;
> >> >> >>> >>> -               if (errno != ECHILD)
> >> >> >>> >>> -                       pool_error("wait() failed.
> reason:%s",
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       myunlink(un_addr.sun_path);
> >> >> >>> >>> -       myunlink(pcp_un_addr.sun_path);
> >> >> >>> >>> -       myunlink(pool_config->pid_file_name);
> >> >> >>> >>> -
> >> >> >>> >>> -       write_status_file();
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_shmem_exit(code);
> >> >> >>> >>> -       exit(code);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -void notice_backend_error(int node_id)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int n = node_id;
> >> >> >>> >>> -
> >> >> >>> >>> -       if (getpid() == mypid)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("notice_backend_error: called from
> >> pgpool
> >> >> >>> main.
> >> >> >>> >>> ignored.");
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               degenerate_backend_set(&n, 1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/* notice backend connection error using SIGUSR1 */
> >> >> >>> >>> -void degenerate_backend_set(int *node_id_set, int count)
> >> >> >>> >>> -{
> >> >> >>> >>> -       pid_t parent = getppid();
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -       bool need_signal = false;
> >> >> >>> >>> -#ifdef HAVE_SIGPROCMASK
> >> >> >>> >>> -       sigset_t oldmask;
> >> >> >>> >>> -#else
> >> >> >>> >>> -       int     oldmask;
> >> >> >>> >>> -#endif
> >> >> >>> >>> -
> >> >> >>> >>> -       if (pool_config->parallel_mode)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       POOL_SETMASK2(&BlockSig, &oldmask);
> >> >> >>> >>> -       pool_semaphore_lock(REQUEST_INFO_SEM);
> >> >> >>> >>> -       Req_info->kind = NODE_DOWN_REQUEST;
> >> >> >>> >>> -       for (i = 0; i < count; i++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (node_id_set[i] < 0 || node_id_set[i] >=
> >> >> >>> >>> MAX_NUM_BACKENDS ||
> >> >> >>> >>> -                       !VALID_BACKEND(node_id_set[i]))
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("degenerate_backend_set:
> node
> >> %d
> >> >> is
> >> >> >>> not
> >> >> >>> >>> valid backend.", i);
> >> >> >>> >>> -                       continue;
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               if
> >> >> >>> >>>
> (POOL_DISALLOW_TO_FAILOVER(BACKEND_INFO(node_id_set[i]).flag))
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("degenerate_backend_set: %d
> >> >> failover
> >> >> >>> >>> request from pid %d is canceled because failover is
> disallowed",
> >> >> >>> >>> node_id_set[i], getpid());
> >> >> >>> >>> -                       continue;
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               pool_log("degenerate_backend_set: %d fail
> over
> >> >> request
> >> >> >>> >>> from pid %d", node_id_set[i], getpid());
> >> >> >>> >>> -               Req_info->node_id[i] = node_id_set[i];
> >> >> >>> >>> -               need_signal = true;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (need_signal)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (!pool_config->use_watchdog || WD_OK ==
> >> >> >>> >>> wd_degenerate_backend_set(node_id_set, count))
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       kill(parent, SIGUSR1);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               else
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("degenerate_backend_set:
> >> failover
> >> >> >>> >>> request from pid %d is canceled by other pgpool", getpid());
> >> >> >>> >>> -                       memset(Req_info->node_id, -1,
> >> sizeof(int) *
> >> >> >>> >>> MAX_NUM_BACKENDS);
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_semaphore_unlock(REQUEST_INFO_SEM);
> >> >> >>> >>> -       POOL_SETMASK(&oldmask);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/* send promote node request using SIGUSR1 */
> >> >> >>> >>> -void promote_backend(int node_id)
> >> >> >>> >>> -{
> >> >> >>> >>> -       pid_t parent = getppid();
> >> >> >>> >>> -
> >> >> >>> >>> -       if (!MASTER_SLAVE ||
> >> >> strcmp(pool_config->master_slave_sub_mode,
> >> >> >>> >>> MODE_STREAMREP))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (node_id < 0 || node_id >= MAX_NUM_BACKENDS ||
> >> >> >>> >>> !VALID_BACKEND(node_id))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("promote_backend: node %d is not
> >> valid
> >> >> >>> >>> backend.", node_id);
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_semaphore_lock(REQUEST_INFO_SEM);
> >> >> >>> >>> -       Req_info->kind = PROMOTE_NODE_REQUEST;
> >> >> >>> >>> -       Req_info->node_id[0] = node_id;
> >> >> >>> >>> -       pool_log("promote_backend: %d promote node request
> from
> >> pid
> >> >> >>> %d",
> >> >> >>> >>> node_id, getpid());
> >> >> >>> >>> -
> >> >> >>> >>> -       if (!pool_config->use_watchdog || WD_OK ==
> >> >> >>> >>> wd_promote_backend(node_id))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               kill(parent, SIGUSR1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("promote_backend: promote request
> from
> >> >> pid %d
> >> >> >>> is
> >> >> >>> >>> canceled by other pgpool", getpid());
> >> >> >>> >>> -               Req_info->node_id[0] = -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_semaphore_unlock(REQUEST_INFO_SEM);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/* send failback request using SIGUSR1 */
> >> >> >>> >>> -void send_failback_request(int node_id)
> >> >> >>> >>> -{
> >> >> >>> >>> -       pid_t parent = getppid();
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_log("send_failback_request: fail back %d th node
> >> >> request
> >> >> >>> >>> from pid %d", node_id, getpid());
> >> >> >>> >>> -       Req_info->kind = NODE_UP_REQUEST;
> >> >> >>> >>> -       Req_info->node_id[0] = node_id;
> >> >> >>> >>> -
> >> >> >>> >>> -    if (node_id < 0 || node_id >= MAX_NUM_BACKENDS ||
> >> >> >>> >>> -               (RAW_MODE &&
> >> BACKEND_INFO(node_id).backend_status
> >> >> !=
> >> >> >>> >>> CON_DOWN && VALID_BACKEND(node_id)))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("send_failback_request: node %d is
> >> >> alive.",
> >> >> >>> >>> node_id);
> >> >> >>> >>> -               Req_info->node_id[0] = -1;
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (pool_config->use_watchdog && WD_OK !=
> >> >> >>> >>> wd_send_failback_request(node_id))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("send_failback_request: failback
> >> request
> >> >> from
> >> >> >>> >>> pid %d is canceled by other pgpool", getpid());
> >> >> >>> >>> -               Req_info->node_id[0] = -1;
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -       kill(parent, SIGUSR1);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -static RETSIGTYPE exit_handler(int sig)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       POOL_SETMASK(&AuthBlockSig);
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * this could happen in a child process if a signal
> has
> >> >> been
> >> >> >>> sent
> >> >> >>> >>> -        * before resetting signal handler
> >> >> >>> >>> -        */
> >> >> >>> >>> -       if (getpid() != mypid)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_debug("exit_handler: I am not parent");
> >> >> >>> >>> -               POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -               pool_shmem_exit(0);
> >> >> >>> >>> -               exit(0);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (sig == SIGTERM)
> >> >> >>> >>> -               pool_log("received smart shutdown request");
> >> >> >>> >>> -       else if (sig == SIGINT)
> >> >> >>> >>> -               pool_log("received fast shutdown request");
> >> >> >>> >>> -       else if (sig == SIGQUIT)
> >> >> >>> >>> -               pool_log("received immediate shutdown
> request");
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("exit_handler: unknown signal
> >> received
> >> >> %d",
> >> >> >>> >>> sig);
> >> >> >>> >>> -               POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       exiting = 1;
> >> >> >>> >>> -
> >> >> >>> >>> -       for (i = 0; i < pool_config->num_init_children; i++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pid_t pid = process_info[i].pid;
> >> >> >>> >>> -               if (pid)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       kill(pid, sig);
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       kill(pcp_pid, sig);
> >> >> >>> >>> -       kill(worker_pid, sig);
> >> >> >>> >>> -
> >> >> >>> >>> -       if (pool_config->use_watchdog)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               wd_kill_watchdog(sig);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -
> >> >> >>> >>> -       while (wait(NULL) > 0)
> >> >> >>> >>> -               ;
> >> >> >>> >>> -
> >> >> >>> >>> -       if (errno != ECHILD)
> >> >> >>> >>> -               pool_error("wait() failed. reason:%s",
> >> >> >>> strerror(errno));
> >> >> >>> >>> -
> >> >> >>> >>> -       process_info = NULL;
> >> >> >>> >>> -       myexit(0);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * Calculate next valid master node id.
> >> >> >>> >>> - * If no valid node found, returns -1.
> >> >> >>> >>> - */
> >> >> >>> >>> -static int get_next_master_node(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       for
> (i=0;i<pool_config->backend_desc->num_backends;i++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               /*
> >> >> >>> >>> -                * Do not use VALID_BACKEND macro in raw
> mode.
> >> >> >>> >>> -                * VALID_BACKEND return true only if the
> >> argument
> >> >> is
> >> >> >>> >>> master
> >> >> >>> >>> -                * node id. In other words, standby nodes are
> >> >> false. So
> >> >> >>> >>> need
> >> >> >>> >>> -                * to check backend status with
> >> VALID_BACKEND_RAW.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               if (RAW_MODE)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (VALID_BACKEND_RAW(i))
> >> >> >>> >>> -                               break;
> >> >> >>> >>> -               }
> >> >> >>> >>> -               else
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (VALID_BACKEND(i))
> >> >> >>> >>> -                               break;
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (i == pool_config->backend_desc->num_backends)
> >> >> >>> >>> -               i = -1;
> >> >> >>> >>> -
> >> >> >>> >>> -       return i;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * handle SIGUSR1
> >> >> >>> >>> - *
> >> >> >>> >>> - */
> >> >> >>> >>> -static RETSIGTYPE failover_handler(int sig)
> >> >> >>> >>> -{
> >> >> >>> >>> -       POOL_SETMASK(&BlockSig);
> >> >> >>> >>> -       failover_request = 1;
> >> >> >>> >>> -       write(pipe_fds[1], "\0", 1);
> >> >> >>> >>> -       POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * backend connection error, failover/failback request, if
> >> >> possible
> >> >> >>> >>> - * failover() must be called under protecting signals.
> >> >> >>> >>> - */
> >> >> >>> >>> -static void failover(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -       int node_id;
> >> >> >>> >>> -       bool by_health_check;
> >> >> >>> >>> -       int new_master;
> >> >> >>> >>> -       int new_primary;
> >> >> >>> >>> -       int nodes[MAX_NUM_BACKENDS];
> >> >> >>> >>> -       bool need_to_restart_children;
> >> >> >>> >>> -       int status;
> >> >> >>> >>> -       int sts;
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_debug("failover_handler called");
> >> >> >>> >>> -
> >> >> >>> >>> -       memset(nodes, 0, sizeof(int) * MAX_NUM_BACKENDS);
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * this could happen in a child process if a signal
> has
> >> >> been
> >> >> >>> sent
> >> >> >>> >>> -        * before resetting signal handler
> >> >> >>> >>> -        */
> >> >> >>> >>> -       if (getpid() != mypid)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_debug("failover_handler: I am not
> parent");
> >> >> >>> >>> -               kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * processing SIGTERM, SIGINT or SIGQUIT
> >> >> >>> >>> -        */
> >> >> >>> >>> -       if (exiting)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_debug("failover_handler called while
> >> >> exiting");
> >> >> >>> >>> -               kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * processing fail over or switch over
> >> >> >>> >>> -        */
> >> >> >>> >>> -       if (switching)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_debug("failover_handler called while
> >> >> switching");
> >> >> >>> >>> -               kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_semaphore_lock(REQUEST_INFO_SEM);
> >> >> >>> >>> -
> >> >> >>> >>> -       if (Req_info->kind == CLOSE_IDLE_REQUEST)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_semaphore_unlock(REQUEST_INFO_SEM);
> >> >> >>> >>> -               kill_all_children(SIGUSR1);
> >> >> >>> >>> -               kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * if not in replication mode/master slave mode, we
> >> treat
> >> >> this
> >> >> >>> a
> >> >> >>> >>> restart request.
> >> >> >>> >>> -        * otherwise we need to check if we have already
> >> >> failovered.
> >> >> >>> >>> -        */
> >> >> >>> >>> -       pool_debug("failover_handler: starting to select new
> >> master
> >> >> >>> >>> node");
> >> >> >>> >>> -       switching = 1;
> >> >> >>> >>> -       Req_info->switching = true;
> >> >> >>> >>> -       node_id = Req_info->node_id[0];
> >> >> >>> >>> -
> >> >> >>> >>> -       /* start of command inter-lock with watchdog */
> >> >> >>> >>> -       if (pool_config->use_watchdog)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               by_health_check = (!failover_request &&
> >> >> >>> >>> Req_info->kind==NODE_DOWN_REQUEST);
> >> >> >>> >>> -               wd_start_interlock(by_health_check);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /* failback request? */
> >> >> >>> >>> -       if (Req_info->kind == NODE_UP_REQUEST)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (node_id >= MAX_NUM_BACKENDS ||
> >> >> >>> >>> -                       (Req_info->kind == NODE_UP_REQUEST &&
> >> >> >>> !(RAW_MODE
> >> >> >>> >>> &&
> >> >> >>> >>> -            BACKEND_INFO(node_id).backend_status ==
> CON_DOWN)
> >> &&
> >> >> >>> >>> VALID_BACKEND(node_id)) ||
> >> >> >>> >>> -                       (Req_info->kind == NODE_DOWN_REQUEST
> &&
> >> >> >>> >>> !VALID_BACKEND(node_id)))
> >> >> >>> >>> -               {
> >> >> >>> >>> -
> pool_semaphore_unlock(REQUEST_INFO_SEM);
> >> >> >>> >>> -                       pool_error("failover_handler: invalid
> >> >> node_id
> >> >> >>> %d
> >> >> >>> >>> status:%d MAX_NUM_BACKENDS: %d", node_id,
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(node_id).backend_status, MAX_NUM_BACKENDS);
> >> >> >>> >>> -                       kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -                       switching = 0;
> >> >> >>> >>> -                       Req_info->switching = false;
> >> >> >>> >>> -
> >> >> >>> >>> -                       /* end of command inter-lock */
> >> >> >>> >>> -                       if (pool_config->use_watchdog)
> >> >> >>> >>> -                               wd_leave_interlock();
> >> >> >>> >>> -
> >> >> >>> >>> -                       return;
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               pool_log("starting fail back. reconnect host
> >> >> %s(%d)",
> >> >> >>> >>> -
> >> >> >>>  BACKEND_INFO(node_id).backend_hostname,
> >> >> >>> >>> -
> >> >>  BACKEND_INFO(node_id).backend_port);
> >> >> >>> >>> -               BACKEND_INFO(node_id).backend_status =
> >> >> >>> CON_CONNECT_WAIT;
> >> >> >>> >>>        /* unset down status */
> >> >> >>> >>> -
> >> >> >>> >>> -               /* wait for failback command lock or to be
> lock
> >> >> holder
> >> >> >>> */
> >> >> >>> >>> -               if (pool_config->use_watchdog &&
> >> >> >>> !wd_am_I_lock_holder())
> >> >> >>> >>> -               {
> >> >> >>> >>> -
> >> wd_wait_for_lock(WD_FAILBACK_COMMAND_LOCK);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               /* execute failback command if lock holder */
> >> >> >>> >>> -               if (!pool_config->use_watchdog ||
> >> >> >>> wd_am_I_lock_holder())
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       trigger_failover_command(node_id,
> >> >> >>> >>> pool_config->failback_command,
> >> >> >>> >>> -
> >> >> >>> >>> MASTER_NODE_ID, get_next_master_node(), PRIMARY_NODE_ID);
> >> >> >>> >>> -
> >> >> >>> >>> -                       /* unlock failback command */
> >> >> >>> >>> -                       if (pool_config->use_watchdog)
> >> >> >>> >>> -
> >> >> wd_unlock(WD_FAILBACK_COMMAND_LOCK);
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else if (Req_info->kind == PROMOTE_NODE_REQUEST)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (node_id != -1 && VALID_BACKEND(node_id))
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("starting promotion. promote
> >> host
> >> >> >>> >>> %s(%d)",
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(node_id).backend_hostname,
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(node_id).backend_port);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               else
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("failover: no backends are
> >> >> promoted");
> >> >> >>> >>> -
> pool_semaphore_unlock(REQUEST_INFO_SEM);
> >> >> >>> >>> -                       kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -                       switching = 0;
> >> >> >>> >>> -                       Req_info->switching = false;
> >> >> >>> >>> -
> >> >> >>> >>> -                       /* end of command inter-lock */
> >> >> >>> >>> -                       if (pool_config->use_watchdog)
> >> >> >>> >>> -                               wd_leave_interlock();
> >> >> >>> >>> -
> >> >> >>> >>> -                       return;
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               int cnt = 0;
> >> >> >>> >>> -
> >> >> >>> >>> -               for (i = 0; i < MAX_NUM_BACKENDS; i++)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (Req_info->node_id[i] != -1 &&
> >> >> >>> >>> -                               ((RAW_MODE &&
> >> >> >>> >>> VALID_BACKEND_RAW(Req_info->node_id[i])) ||
> >> >> >>> >>> -
> >> >>  VALID_BACKEND(Req_info->node_id[i])))
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               pool_log("starting
> degeneration.
> >> >> >>> shutdown
> >> >> >>> >>> host %s(%d)",
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(Req_info->node_id[i]).backend_hostname,
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(Req_info->node_id[i]).backend_port);
> >> >> >>> >>> -
> >> >> >>> >>> -
> >> >> >>> >>> BACKEND_INFO(Req_info->node_id[i]).backend_status = CON_DOWN;
> >> /*
> >> >> set
> >> >> >>> down
> >> >> >>> >>> status */
> >> >> >>> >>> -                               /* save down node */
> >> >> >>> >>> -                               nodes[Req_info->node_id[i]]
> = 1;
> >> >> >>> >>> -                               cnt++;
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               if (cnt == 0)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("failover: no backends are
> >> >> >>> degenerated");
> >> >> >>> >>> -
> pool_semaphore_unlock(REQUEST_INFO_SEM);
> >> >> >>> >>> -                       kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -                       switching = 0;
> >> >> >>> >>> -                       Req_info->switching = false;
> >> >> >>> >>> -
> >> >> >>> >>> -                       /* end of command inter-lock */
> >> >> >>> >>> -                       if (pool_config->use_watchdog)
> >> >> >>> >>> -                               wd_leave_interlock();
> >> >> >>> >>> -
> >> >> >>> >>> -                       return;
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       new_master = get_next_master_node();
> >> >> >>> >>> -
> >> >> >>> >>> -       if (new_master < 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("failover_handler: no valid DB
> node
> >> >> found");
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * Before we tried to minimize restarting pgpool to protect
> >> >> existing
> >> >> >>> >>> - * connections from clients to pgpool children. What we did
> >> here
> >> >> was,
> >> >> >>> >>> - * if children other than master went down, we did not fail
> >> over.
> >> >> >>> >>> - * This is wrong. Think about following scenario. If someone
> >> >> >>> >>> - * accidentally plugs out the network cable, the TCP/IP
> stack
> >> >> keeps
> >> >> >>> >>> - * retrying for long time (typically 2 hours). The only way
> to
> >> >> stop
> >> >> >>> >>> - * the retry is restarting the process.  Bottom line is, we
> >> need
> >> >> to
> >> >> >>> >>> - * restart all children in any case.  See pgpool-general
> list
> >> >> posting
> >> >> >>> >>> - * "TCP connections are *not* closed when a backend
> timeout" on
> >> >> Jul 13
> >> >> >>> >>> - * 2008 for more details.
> >> >> >>> >>> - */
> >> >> >>> >>> -#ifdef NOT_USED
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (Req_info->master_node_id == new_master &&
> >> >> >>> *InRecovery
> >> >> >>> >>> == RECOVERY_INIT)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("failover_handler: do not
> >> restart
> >> >> >>> >>> pgpool. same master node %d was selected", new_master);
> >> >> >>> >>> -                       if (Req_info->kind ==
> NODE_UP_REQUEST)
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               pool_log("failback done.
> >> reconnect
> >> >> host
> >> >> >>> >>> %s(%d)",
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(node_id).backend_hostname,
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(node_id).backend_port);
> >> >> >>> >>> -                       }
> >> >> >>> >>> -                       else
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               pool_log("failover done.
> >> shutdown
> >> >> host
> >> >> >>> >>> %s(%d)",
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(node_id).backend_hostname,
> >> >> >>> >>> -
> >> >> >>> >>>  BACKEND_INFO(node_id).backend_port);
> >> >> >>> >>> -                       }
> >> >> >>> >>> -
> >> >> >>> >>> -                       /* exec failover_command */
> >> >> >>> >>> -                       for (i = 0; i <
> >> >> >>> >>> pool_config->backend_desc->num_backends; i++)
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               if (nodes[i])
> >> >> >>> >>> -
> >> trigger_failover_command(i,
> >> >> >>> >>> pool_config->failover_command);
> >> >> >>> >>> -                       }
> >> >> >>> >>> -
> >> >> >>> >>> -
> pool_semaphore_unlock(REQUEST_INFO_SEM);
> >> >> >>> >>> -                       switching = 0;
> >> >> >>> >>> -                       Req_info->switching = false;
> >> >> >>> >>> -                       kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -                       switching = 0;
> >> >> >>> >>> -                       Req_info->switching = false;
> >> >> >>> >>> -                       return;
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -#endif
> >> >> >>> >>> -
> >> >> >>> >>> -
> >> >> >>> >>> -   /* On 2011/5/2 Tatsuo Ishii says: if mode is streaming
> >> >> replication
> >> >> >>> >>> -       * and request is NODE_UP_REQUEST(failback case) we
> don't
> >> >> need
> >> >> >>> to
> >> >> >>> >>> -       * restart all children. Existing session will not use
> >> newly
> >> >> >>> >>> -       * attached node, but load balanced node is not
> changed
> >> >> until
> >> >> >>> this
> >> >> >>> >>> -       * session ends, so it's harmless anyway.
> >> >> >>> >>> -       */
> >> >> >>> >>> -       if (MASTER_SLAVE &&
> >> >> !strcmp(pool_config->master_slave_sub_mode,
> >> >> >>> >>> MODE_STREAMREP) &&
> >> >> >>> >>> -               Req_info->kind == NODE_UP_REQUEST)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("Do not restart children because we
> are
> >> >> >>> >>> failbacking node id %d host%s port:%d and we are in streaming
> >> >> >>> replication
> >> >> >>> >>> mode", node_id,
> >> >> >>> >>> -
> >> >> >>>  BACKEND_INFO(node_id).backend_hostname,
> >> >> >>> >>> -
> >> >>  BACKEND_INFO(node_id).backend_port);
> >> >> >>> >>> -
> >> >> >>> >>> -               need_to_restart_children = false;
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("Restart all children");
> >> >> >>> >>> -
> >> >> >>> >>> -               /* kill all children */
> >> >> >>> >>> -               for (i = 0; i <
> pool_config->num_init_children;
> >> >> i++)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pid_t pid = process_info[i].pid;
> >> >> >>> >>> -                       if (pid)
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               kill(pid, SIGQUIT);
> >> >> >>> >>> -                               pool_debug("failover_handler:
> >> kill
> >> >> %d",
> >> >> >>> >>> pid);
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               need_to_restart_children = true;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /* wait for failover command lock or to be lock
> holder*/
> >> >> >>> >>> -       if (pool_config->use_watchdog &&
> !wd_am_I_lock_holder())
> >> >> >>> >>> -       {
> >> >> >>> >>> -               wd_wait_for_lock(WD_FAILOVER_COMMAND_LOCK);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /* execute failover command if lock holder */
> >> >> >>> >>> -       if (!pool_config->use_watchdog ||
> wd_am_I_lock_holder())
> >> >> >>> >>> -       {
> >> >> >>> >>> -               /* Exec failover_command if needed */
> >> >> >>> >>> -               for (i = 0; i <
> >> >> >>> pool_config->backend_desc->num_backends;
> >> >> >>> >>> i++)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (nodes[i])
> >> >> >>> >>> -                               trigger_failover_command(i,
> >> >> >>> >>> pool_config->failover_command,
> >> >> >>> >>> -
> >> >> >>> >>>               MASTER_NODE_ID, new_master, PRIMARY_NODE_ID);
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               /* unlock failover command */
> >> >> >>> >>> -               if (pool_config->use_watchdog)
> >> >> >>> >>> -                       wd_unlock(WD_FAILOVER_COMMAND_LOCK);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -
> >> >> >>> >>> -/* no need to wait since it will be done in reap_handler */
> >> >> >>> >>> -#ifdef NOT_USED
> >> >> >>> >>> -       while (wait(NULL) > 0)
> >> >> >>> >>> -               ;
> >> >> >>> >>> -
> >> >> >>> >>> -       if (errno != ECHILD)
> >> >> >>> >>> -               pool_error("failover_handler: wait() failed.
> >> >> >>> reason:%s",
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -#endif
> >> >> >>> >>> -
> >> >> >>> >>> -       if (Req_info->kind == PROMOTE_NODE_REQUEST &&
> >> >> >>> >>> VALID_BACKEND(node_id))
> >> >> >>> >>> -               new_primary = node_id;
> >> >> >>> >>> -       else
> >> >> >>> >>> -               new_primary =
>  find_primary_node_repeatedly();
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * If follow_master_command is provided and in
> >> master/slave
> >> >> >>> >>> -        * streaming replication mode, we start degenerating
> all
> >> >> >>> backends
> >> >> >>> >>> -        * as they are not replicated anymore.
> >> >> >>> >>> -        */
> >> >> >>> >>> -       int follow_cnt = 0;
> >> >> >>> >>> -       if (MASTER_SLAVE &&
> >> >> !strcmp(pool_config->master_slave_sub_mode,
> >> >> >>> >>> MODE_STREAMREP))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (*pool_config->follow_master_command !=
> '\0'
> >> ||
> >> >> >>> >>> -                       Req_info->kind ==
> PROMOTE_NODE_REQUEST)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       /* only if the failover is against
> the
> >> >> current
> >> >> >>> >>> primary */
> >> >> >>> >>> -                       if (((Req_info->kind ==
> >> NODE_DOWN_REQUEST)
> >> >> &&
> >> >> >>> >>> -
> >> >>  (nodes[Req_info->primary_node_id])) ||
> >> >> >>> >>> -                               ((Req_info->kind ==
> >> >> >>> PROMOTE_NODE_REQUEST)
> >> >> >>> >>> &&
> >> >> >>> >>> -                                (VALID_BACKEND(node_id)))) {
> >> >> >>> >>> -
> >> >> >>> >>> -                               for (i = 0; i <
> >> >> >>> >>> pool_config->backend_desc->num_backends; i++)
> >> >> >>> >>> -                               {
> >> >> >>> >>> -                                       /* do not degenerate
> the
> >> >> new
> >> >> >>> >>> primary */
> >> >> >>> >>> -                                       if ((new_primary >=
> 0)
> >> &&
> >> >> (i !=
> >> >> >>> >>> new_primary)) {
> >> >> >>> >>> -                                               BackendInfo
> >> >> *bkinfo;
> >> >> >>> >>> -                                               bkinfo =
> >> >> >>> >>> pool_get_node_info(i);
> >> >> >>> >>> -
> >> pool_log("starting
> >> >> >>> follow
> >> >> >>> >>> degeneration. shutdown host %s(%d)",
> >> >> >>> >>> -
> >> >> >>> >>>  bkinfo->backend_hostname,
> >> >> >>> >>> -
> >> >> >>> >>>  bkinfo->backend_port);
> >> >> >>> >>> -
> >> >> bkinfo->backend_status
> >> >> >>> =
> >> >> >>> >>> CON_DOWN;      /* set down status */
> >> >> >>> >>> -                                               follow_cnt++;
> >> >> >>> >>> -                                       }
> >> >> >>> >>> -                               }
> >> >> >>> >>> -
> >> >> >>> >>> -                               if (follow_cnt == 0)
> >> >> >>> >>> -                               {
> >> >> >>> >>> -                                       pool_log("failover:
> no
> >> >> follow
> >> >> >>> >>> backends are degenerated");
> >> >> >>> >>> -                               }
> >> >> >>> >>> -                               else
> >> >> >>> >>> -                               {
> >> >> >>> >>> -                                       /* update new master
> >> node
> >> >> */
> >> >> >>> >>> -                                       new_master =
> >> >> >>> >>> get_next_master_node();
> >> >> >>> >>> -                                       pool_log("failover:
> %d
> >> >> follow
> >> >> >>> >>> backends have been degenerated", follow_cnt);
> >> >> >>> >>> -                               }
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       memset(Req_info->node_id, -1, sizeof(int) *
> >> >> MAX_NUM_BACKENDS);
> >> >> >>> >>> -       pool_semaphore_unlock(REQUEST_INFO_SEM);
> >> >> >>> >>> -
> >> >> >>> >>> -       /* wait for follow_master_command lock or to be lock
> >> >> holder */
> >> >> >>> >>> -       if (pool_config->use_watchdog &&
> !wd_am_I_lock_holder())
> >> >> >>> >>> -       {
> >> >> >>> >>> -
> wd_wait_for_lock(WD_FOLLOW_MASTER_COMMAND_LOCK);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /* execute follow_master_command */
> >> >> >>> >>> -       if (!pool_config->use_watchdog ||
> wd_am_I_lock_holder())
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if ((follow_cnt > 0) &&
> >> >> >>> >>> (*pool_config->follow_master_command != '\0'))
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       follow_pid =
> >> >> >>> >>> fork_follow_child(Req_info->master_node_id, new_primary,
> >> >> >>> >>> -
> >> >> >>> >>>       Req_info->primary_node_id);
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               /* unlock follow_master_command  */
> >> >> >>> >>> -               if (pool_config->use_watchdog)
> >> >> >>> >>> -
> >> wd_unlock(WD_FOLLOW_MASTER_COMMAND_LOCK);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /* end of command inter-lock */
> >> >> >>> >>> -       if (pool_config->use_watchdog)
> >> >> >>> >>> -               wd_end_interlock();
> >> >> >>> >>> -
> >> >> >>> >>> -       /* Save primary node id */
> >> >> >>> >>> -       Req_info->primary_node_id = new_primary;
> >> >> >>> >>> -       pool_log("failover: set new primary node: %d",
> >> >> >>> >>> Req_info->primary_node_id);
> >> >> >>> >>> -
> >> >> >>> >>> -       if (new_master >= 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               Req_info->master_node_id = new_master;
> >> >> >>> >>> -               pool_log("failover: set new master node: %d",
> >> >> >>> >>> Req_info->master_node_id);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -
> >> >> >>> >>> -       /* Fork the children if needed */
> >> >> >>> >>> -       if (need_to_restart_children)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               for
> (i=0;i<pool_config->num_init_children;i++)
> >> >> >>> >>> -               {
> >> >> >>> >>> -
> >> >> >>> >>> -                       /*
> >> >> >>> >>> -                        * Try to kill pgpool child because
> >> >> previous
> >> >> >>> kill
> >> >> >>> >>> signal
> >> >> >>> >>> -                        * may not be received by pgpool
> child.
> >> >> This
> >> >> >>> >>> could happen
> >> >> >>> >>> -                        * if multiple PostgreSQL are going
> down
> >> >> (or
> >> >> >>> even
> >> >> >>> >>> starting
> >> >> >>> >>> -                        * pgpool, without starting
> PostgreSQL
> >> can
> >> >> >>> >>> trigger this).
> >> >> >>> >>> -                        * Child calls degenerate_backend()
> and
> >> it
> >> >> >>> tries
> >> >> >>> >>> to aquire
> >> >> >>> >>> -                        * semaphore to write a failover
> >> request.
> >> >> In
> >> >> >>> this
> >> >> >>> >>> case the
> >> >> >>> >>> -                        * signal mask is set as well, thus
> >> >> signals are
> >> >> >>> >>> never
> >> >> >>> >>> -                        * received.
> >> >> >>> >>> -                        */
> >> >> >>> >>> -                       kill(process_info[i].pid, SIGQUIT);
> >> >> >>> >>> -
> >> >> >>> >>> -                       process_info[i].pid =
> >> fork_a_child(unix_fd,
> >> >> >>> >>> inet_fd, i);
> >> >> >>> >>> -                       process_info[i].start_time =
> time(NULL);
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               /* Set restart request to each child.
> Children
> >> will
> >> >> >>> >>> exit(1)
> >> >> >>> >>> -                * whenever they are idle to restart.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               for
> (i=0;i<pool_config->num_init_children;i++)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       process_info[i].need_to_restart = 1;
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * Send restart request to worker child.
> >> >> >>> >>> -        */
> >> >> >>> >>> -       kill(worker_pid, SIGUSR1);
> >> >> >>> >>> -
> >> >> >>> >>> -       if (Req_info->kind == NODE_UP_REQUEST)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("failback done. reconnect host
> %s(%d)",
> >> >> >>> >>> -
> >> >> >>>  BACKEND_INFO(node_id).backend_hostname,
> >> >> >>> >>> -
> >> >>  BACKEND_INFO(node_id).backend_port);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else if (Req_info->kind == PROMOTE_NODE_REQUEST)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("promotion done. promoted host
> %s(%d)",
> >> >> >>> >>> -
> >> >> >>>  BACKEND_INFO(node_id).backend_hostname,
> >> >> >>> >>> -
> >> >>  BACKEND_INFO(node_id).backend_port);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("failover done. shutdown host
> %s(%d)",
> >> >> >>> >>> -
> >> >> >>>  BACKEND_INFO(node_id).backend_hostname,
> >> >> >>> >>> -
> >> >>  BACKEND_INFO(node_id).backend_port);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       switching = 0;
> >> >> >>> >>> -       Req_info->switching = false;
> >> >> >>> >>> -
> >> >> >>> >>> -       /* kick wakeup_handler in pcp_child to notice that
> >> >> >>> >>> -        * failover/failback done
> >> >> >>> >>> -        */
> >> >> >>> >>> -       kill(pcp_pid, SIGUSR2);
> >> >> >>> >>> -
> >> >> >>> >>> -       sleep(1);
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * Send restart request to pcp child.
> >> >> >>> >>> -        */
> >> >> >>> >>> -       kill(pcp_pid, SIGUSR1);
> >> >> >>> >>> -       for (;;)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               sts = waitpid(pcp_pid, &status, 0);
> >> >> >>> >>> -               if (sts != -1)
> >> >> >>> >>> -                       break;
> >> >> >>> >>> -               if (sts == -1)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (errno == EINTR)
> >> >> >>> >>> -                               continue;
> >> >> >>> >>> -                       else
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               pool_error("failover: waitpid
> >> >> failed.
> >> >> >>> >>> reason: %s", strerror(errno));
> >> >> >>> >>> -                               return;
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -       if (WIFSIGNALED(status))
> >> >> >>> >>> -               pool_log("PCP child %d exits with status %d
> by
> >> >> signal
> >> >> >>> %d
> >> >> >>> >>> in failover()", pcp_pid, status, WTERMSIG(status));
> >> >> >>> >>> -       else
> >> >> >>> >>> -               pool_log("PCP child %d exits with status %d
> in
> >> >> >>> >>> failover()", pcp_pid, status);
> >> >> >>> >>> -
> >> >> >>> >>> -       pcp_pid = pcp_fork_a_child(pcp_unix_fd, pcp_inet_fd,
> >> >> >>> >>> pcp_conf_file);
> >> >> >>> >>> -       pool_log("fork a new PCP child pid %d in failover()",
> >> >> pcp_pid);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * health check timer handler
> >> >> >>> >>> - */
> >> >> >>> >>> -static RETSIGTYPE health_check_timer_handler(int sig)
> >> >> >>> >>> -{
> >> >> >>> >>> -       POOL_SETMASK(&BlockSig);
> >> >> >>> >>> -       health_check_timer_expired = 1;
> >> >> >>> >>> -       POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * Check if we can connect to the backend
> >> >> >>> >>> - * returns 0 for OK. otherwise returns backend id + 1
> >> >> >>> >>> - */
> >> >> >>> >>> -static int health_check(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       POOL_CONNECTION_POOL_SLOT *slot;
> >> >> >>> >>> -       BackendInfo *bkinfo;
> >> >> >>> >>> -       static bool is_first = true;
> >> >> >>> >>> -       static char *dbname;
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       /* Do not execute health check during recovery */
> >> >> >>> >>> -       if (*InRecovery)
> >> >> >>> >>> -               return 0;
> >> >> >>> >>> -
> >> >> >>> >>> - Retry:
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * First we try with "postgres" database.
> >> >> >>> >>> -        */
> >> >> >>> >>> -       if (is_first)
> >> >> >>> >>> -               dbname = "postgres";
> >> >> >>> >>> -
> >> >> >>> >>> -       for
> (i=0;i<pool_config->backend_desc->num_backends;i++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               /*
> >> >> >>> >>> -                * Make sure that health check timer has not
> >> been
> >> >> >>> expired.
> >> >> >>> >>> -                * Before called health_check(),
> >> >> >>> >>> health_check_timer_expired is
> >> >> >>> >>> -                * set to 0.  However it is possible that
> while
> >> >> >>> >>> processing DB
> >> >> >>> >>> -                * nodes health check timer expired.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               if (health_check_timer_expired)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("health_check: health check
> >> timer
> >> >> has
> >> >> >>> >>> been already expired before attempting to connect to %d th
> >> >> backend",
> >> >> >>> i);
> >> >> >>> >>> -                       return i+1;
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               bkinfo = pool_get_node_info(i);
> >> >> >>> >>> -
> >> >> >>> >>> -               pool_debug("health_check: %d th DB node
> status:
> >> >> %d", i,
> >> >> >>> >>> bkinfo->backend_status);
> >> >> >>> >>> -
> >> >> >>> >>> -               if (bkinfo->backend_status == CON_UNUSED ||
> >> >> >>> >>> -                       bkinfo->backend_status == CON_DOWN)
> >> >> >>> >>> -                       continue;
> >> >> >>> >>> -
> >> >> >>> >>> -               slot =
> >> >> >>> >>> make_persistent_db_connection(bkinfo->backend_hostname,
> >> >> >>> >>> -
> >> >> >>> >>>                bkinfo->backend_port,
> >> >> >>> >>> -
> >> >> >>> >>>                dbname,
> >> >> >>> >>> -
> >> >> >>> >>>                pool_config->health_check_user,
> >> >> >>> >>> -
> >> >> >>> >>>                pool_config->health_check_password, false);
> >> >> >>> >>> -
> >> >> >>> >>> -               if (is_first)
> >> >> >>> >>> -                       is_first = false;
> >> >> >>> >>> -
> >> >> >>> >>> -               if (!slot)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       /*
> >> >> >>> >>> -                        * Retry with template1 unless health
> >> check
> >> >> >>> timer
> >> >> >>> >>> is expired.
> >> >> >>> >>> -                        */
> >> >> >>> >>> -                       if (!strcmp(dbname, "postgres") &&
> >> >> >>> >>> health_check_timer_expired == 0)
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               dbname = "template1";
> >> >> >>> >>> -                               goto Retry;
> >> >> >>> >>> -                       }
> >> >> >>> >>> -                       else
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               pool_error("health check
> failed.
> >> >> %d th
> >> >> >>> >>> host %s at port %d is down",
> >> >> >>> >>> -                                                  i,
> >> >> >>> >>> -
> >> >> >>> >>>  bkinfo->backend_hostname,
> >> >> >>> >>> -
> >> >> >>>  bkinfo->backend_port);
> >> >> >>> >>> -                               return i+1;
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               }
> >> >> >>> >>> -               else
> >> >> >>> >>> -               {
> >> >> >>> >>> -
> discard_persistent_db_connection(slot);
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       return 0;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * check if we can connect to the SystemDB
> >> >> >>> >>> - * returns 0 for OK. otherwise returns -1
> >> >> >>> >>> - */
> >> >> >>> >>> -static int
> >> >> >>> >>> -system_db_health_check(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int fd;
> >> >> >>> >>> -
> >> >> >>> >>> -       /* V2 startup packet */
> >> >> >>> >>> -       typedef struct {
> >> >> >>> >>> -               int len;                /* startup packet
> >> length */
> >> >> >>> >>> -               StartupPacket_v2 sp;
> >> >> >>> >>> -       } MySp;
> >> >> >>> >>> -       MySp mysp;
> >> >> >>> >>> -       char kind;
> >> >> >>> >>> -
> >> >> >>> >>> -       memset(&mysp, 0, sizeof(mysp));
> >> >> >>> >>> -       mysp.len = htonl(296);
> >> >> >>> >>> -       mysp.sp.protoVersion = htonl(PROTO_MAJOR_V2 << 16);
> >> >> >>> >>> -       strcpy(mysp.sp.database, "template1");
> >> >> >>> >>> -       strncpy(mysp.sp.user, SYSDB_INFO->user,
> >> >> sizeof(mysp.sp.user) -
> >> >> >>> 1);
> >> >> >>> >>> -       *mysp.sp.options = '\0';
> >> >> >>> >>> -       *mysp.sp.unused = '\0';
> >> >> >>> >>> -       *mysp.sp.tty = '\0';
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_debug("health_check: SystemDB status: %d",
> >> >> SYSDB_STATUS);
> >> >> >>> >>> -
> >> >> >>> >>> -       /* if SystemDB is already down, ignore */
> >> >> >>> >>> -       if (SYSDB_STATUS == CON_UNUSED || SYSDB_STATUS ==
> >> CON_DOWN)
> >> >> >>> >>> -               return 0;
> >> >> >>> >>> -
> >> >> >>> >>> -       if (*SYSDB_INFO->hostname == '/')
> >> >> >>> >>> -               fd =
> >> >> >>> connect_unix_domain_socket_by_port(SYSDB_INFO->port,
> >> >> >>> >>> SYSDB_INFO->hostname, FALSE);
> >> >> >>> >>> -       else
> >> >> >>> >>> -               fd =
> >> >> >>> >>> connect_inet_domain_socket_by_port(SYSDB_INFO->hostname,
> >> >> >>> SYSDB_INFO->port,
> >> >> >>> >>> FALSE);
> >> >> >>> >>> -
> >> >> >>> >>> -       if (fd < 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("health check failed. SystemDB
> host
> >> %s
> >> >> at
> >> >> >>> port
> >> >> >>> >>> %d is down",
> >> >> >>> >>> -                                  SYSDB_INFO->hostname,
> >> >> >>> >>> -                                  SYSDB_INFO->port);
> >> >> >>> >>> -
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (write(fd, &mysp, sizeof(mysp)) < 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("health check failed during write.
> >> >> SystemDB
> >> >> >>> >>> host %s at port %d is down",
> >> >> >>> >>> -                                  SYSDB_INFO->hostname,
> >> >> >>> >>> -                                  SYSDB_INFO->port);
> >> >> >>> >>> -               close(fd);
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       read(fd, &kind, 1);
> >> >> >>> >>> -
> >> >> >>> >>> -       if (write(fd, "X", 1) < 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("health check failed during write.
> >> >> SystemDB
> >> >> >>> >>> host %s at port %d is down",
> >> >> >>> >>> -                                  SYSDB_INFO->hostname,
> >> >> >>> >>> -                                  SYSDB_INFO->port);
> >> >> >>> >>> -               close(fd);
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       close(fd);
> >> >> >>> >>> -       return 0;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * handle SIGCHLD
> >> >> >>> >>> - */
> >> >> >>> >>> -static RETSIGTYPE reap_handler(int sig)
> >> >> >>> >>> -{
> >> >> >>> >>> -       POOL_SETMASK(&BlockSig);
> >> >> >>> >>> -       sigchld_request = 1;
> >> >> >>> >>> -       write(pipe_fds[1], "\0", 1);
> >> >> >>> >>> -       POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * Attach zombie processes and restart child processes.
> >> >> >>> >>> - * reaper() must be called protected from signals.
> >> >> >>> >>> - */
> >> >> >>> >>> -static void reaper(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       pid_t pid;
> >> >> >>> >>> -       int status;
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_debug("reap_handler called");
> >> >> >>> >>> -
> >> >> >>> >>> -       if (exiting)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_debug("reap_handler: exited due to
> >> exiting");
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (switching)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_debug("reap_handler: exited due to
> >> >> switching");
> >> >> >>> >>> -               return;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /* clear SIGCHLD request */
> >> >> >>> >>> -       sigchld_request = 0;
> >> >> >>> >>> -
> >> >> >>> >>> -#ifdef HAVE_WAITPID
> >> >> >>> >>> -       pool_debug("reap_handler: call waitpid");
> >> >> >>> >>> -       while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
> >> >> >>> >>> -#else
> >> >> >>> >>> -       pool_debug("reap_handler: call wait3");
> >> >> >>> >>> -       while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
> >> >> >>> >>> -#endif
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (WIFSIGNALED(status) && WTERMSIG(status)
> ==
> >> >> SIGSEGV)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       /* Child terminated by segmentation
> >> fault.
> >> >> >>> Report
> >> >> >>> >>> it */
> >> >> >>> >>> -                       pool_error("Child process %d was
> >> >> terminated by
> >> >> >>> >>> segmentation fault", pid);
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               /* if exiting child process was PCP handler
> */
> >> >> >>> >>> -               if (pid == pcp_pid)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (WIFSIGNALED(status))
> >> >> >>> >>> -                               pool_log("PCP child %d exits
> >> with
> >> >> >>> status
> >> >> >>> >>> %d by signal %d", pid, status, WTERMSIG(status));
> >> >> >>> >>> -                       else
> >> >> >>> >>> -                               pool_log("PCP child %d exits
> >> with
> >> >> >>> status
> >> >> >>> >>> %d", pid, status);
> >> >> >>> >>> -
> >> >> >>> >>> -                       pcp_pid =
> pcp_fork_a_child(pcp_unix_fd,
> >> >> >>> >>> pcp_inet_fd, pcp_conf_file);
> >> >> >>> >>> -                       pool_log("fork a new PCP child pid
> %d",
> >> >> >>> pcp_pid);
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               /* exiting process was worker process */
> >> >> >>> >>> -               else if (pid == worker_pid)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (WIFSIGNALED(status))
> >> >> >>> >>> -                               pool_log("worker child %d
> exits
> >> >> with
> >> >> >>> >>> status %d by signal %d", pid, status, WTERMSIG(status));
> >> >> >>> >>> -                       else
> >> >> >>> >>> -                               pool_log("worker child %d
> exits
> >> >> with
> >> >> >>> >>> status %d", pid, status);
> >> >> >>> >>> -
> >> >> >>> >>> -                       if (status)
> >> >> >>> >>> -                               worker_pid =
> >> worker_fork_a_child();
> >> >> >>> >>> -
> >> >> >>> >>> -                       pool_log("fork a new worker child pid
> >> %d",
> >> >> >>> >>> worker_pid);
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               /* exiting process was watchdog process */
> >> >> >>> >>> -               else if (pool_config->use_watchdog &&
> >> >> >>> >>> wd_is_watchdog_pid(pid))
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (!wd_reaper_watchdog(pid, status))
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               pool_error("wd_reaper
> failed");
> >> >> >>> >>> -                               myexit(1);
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               else
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (WIFSIGNALED(status))
> >> >> >>> >>> -                               pool_debug("child %d exits
> with
> >> >> status
> >> >> >>> %d
> >> >> >>> >>> by signal %d", pid, status, WTERMSIG(status));
> >> >> >>> >>> -                       else
> >> >> >>> >>> -                               pool_debug("child %d exits
> with
> >> >> status
> >> >> >>> >>> %d", pid, status);
> >> >> >>> >>> -
> >> >> >>> >>> -                       /* look for exiting child's pid */
> >> >> >>> >>> -                       for
> >> >> (i=0;i<pool_config->num_init_children;i++)
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               if (pid ==
> process_info[i].pid)
> >> >> >>> >>> -                               {
> >> >> >>> >>> -                                       /* if found, fork a
> new
> >> >> child
> >> >> >>> */
> >> >> >>> >>> -                                       if (!switching &&
> >> !exiting
> >> >> &&
> >> >> >>> >>> status)
> >> >> >>> >>> -                                       {
> >> >> >>> >>> -
> >> >> process_info[i].pid =
> >> >> >>> >>> fork_a_child(unix_fd, inet_fd, i);
> >> >> >>> >>> -
> >> >> >>> >>> process_info[i].start_time = time(NULL);
> >> >> >>> >>> -
> >> pool_debug("fork a
> >> >> new
> >> >> >>> >>> child pid %d", process_info[i].pid);
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -                                       }
> >> >> >>> >>> -                               }
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -       pool_debug("reap_handler: normally exited");
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * get node information specified by node_number
> >> >> >>> >>> - */
> >> >> >>> >>> -BackendInfo *
> >> >> >>> >>> -pool_get_node_info(int node_number)
> >> >> >>> >>> -{
> >> >> >>> >>> -       if (node_number < 0 || node_number >= NUM_BACKENDS)
> >> >> >>> >>> -               return NULL;
> >> >> >>> >>> -
> >> >> >>> >>> -       return &BACKEND_INFO(node_number);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * get number of nodes
> >> >> >>> >>> - */
> >> >> >>> >>> -int
> >> >> >>> >>> -pool_get_node_count(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       return NUM_BACKENDS;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * get process ids
> >> >> >>> >>> - */
> >> >> >>> >>> -int *
> >> >> >>> >>> -pool_get_process_list(int *array_size)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int        *array;
> >> >> >>> >>> -       int             i;
> >> >> >>> >>> -
> >> >> >>> >>> -       *array_size = pool_config->num_init_children;
> >> >> >>> >>> -       array = calloc(*array_size, sizeof(int));
> >> >> >>> >>> -       for (i = 0; i < *array_size; i++)
> >> >> >>> >>> -               array[i] = process_info[i].pid;
> >> >> >>> >>> -
> >> >> >>> >>> -       return array;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * get process information specified by pid
> >> >> >>> >>> - */
> >> >> >>> >>> -ProcessInfo *
> >> >> >>> >>> -pool_get_process_info(pid_t pid)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int             i;
> >> >> >>> >>> -
> >> >> >>> >>> -       for (i = 0; i < pool_config->num_init_children; i++)
> >> >> >>> >>> -               if (process_info[i].pid == pid)
> >> >> >>> >>> -                       return &process_info[i];
> >> >> >>> >>> -
> >> >> >>> >>> -       return NULL;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * get System DB information
> >> >> >>> >>> - */
> >> >> >>> >>> -SystemDBInfo *
> >> >> >>> >>> -pool_get_system_db_info(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       if (system_db_info == NULL)
> >> >> >>> >>> -               return NULL;
> >> >> >>> >>> -
> >> >> >>> >>> -       return system_db_info->info;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * handle SIGUSR2
> >> >> >>> >>> - * Wakeup all processes
> >> >> >>> >>> - */
> >> >> >>> >>> -static void wakeup_children(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       kill_all_children(SIGUSR2);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -
> >> >> >>> >>> -static RETSIGTYPE wakeup_handler(int sig)
> >> >> >>> >>> -{
> >> >> >>> >>> -       POOL_SETMASK(&BlockSig);
> >> >> >>> >>> -       wakeup_request = 1;
> >> >> >>> >>> -       write(pipe_fds[1], "\0", 1);
> >> >> >>> >>> -       POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * handle SIGHUP
> >> >> >>> >>> - *
> >> >> >>> >>> - */
> >> >> >>> >>> -static RETSIGTYPE reload_config_handler(int sig)
> >> >> >>> >>> -{
> >> >> >>> >>> -       POOL_SETMASK(&BlockSig);
> >> >> >>> >>> -       reload_config_request = 1;
> >> >> >>> >>> -       write(pipe_fds[1], "\0", 1);
> >> >> >>> >>> -       POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -static void reload_config(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       pool_log("reload config files.");
> >> >> >>> >>> -       pool_get_config(conf_file, RELOAD_CONFIG);
> >> >> >>> >>> -       if (pool_config->enable_pool_hba)
> >> >> >>> >>> -               load_hba(hba_file);
> >> >> >>> >>> -       if (pool_config->parallel_mode)
> >> >> >>> >>> -
> >> pool_memset_system_db_info(system_db_info->info);
> >> >> >>> >>> -       kill_all_children(SIGHUP);
> >> >> >>> >>> -
> >> >> >>> >>> -       if (worker_pid)
> >> >> >>> >>> -               kill(worker_pid, SIGHUP);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -static void kill_all_children(int sig)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       /* kill all children */
> >> >> >>> >>> -       for (i = 0; i < pool_config->num_init_children; i++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pid_t pid = process_info[i].pid;
> >> >> >>> >>> -               if (pid)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       kill(pid, sig);
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /* make PCP process reload as well */
> >> >> >>> >>> -       if (sig == SIGHUP)
> >> >> >>> >>> -               kill(pcp_pid, sig);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * pause in a period specified by timeout. If any data is
> >> coming
> >> >> >>> >>> - * through pipe_fds[0], that means one of: failover
> >> >> request(SIGUSR1),
> >> >> >>> >>> - * SIGCHLD received, children wake up request(SIGUSR2 used
> in
> >> on
> >> >> line
> >> >> >>> >>> - * recovery processing) or config file reload
> request(SIGHUP)
> >> has
> >> >> been
> >> >> >>> >>> - * occurred.  In this case this function returns 1.
> >> >> >>> >>> - * otherwise 0: (no signal event occurred), -1: (error)
> >> >> >>> >>> - * XXX: is it OK that select(2) error is ignored here?
> >> >> >>> >>> - */
> >> >> >>> >>> -static int pool_pause(struct timeval *timeout)
> >> >> >>> >>> -{
> >> >> >>> >>> -       fd_set rfds;
> >> >> >>> >>> -       int n;
> >> >> >>> >>> -       char dummy;
> >> >> >>> >>> -
> >> >> >>> >>> -       FD_ZERO(&rfds);
> >> >> >>> >>> -       FD_SET(pipe_fds[0], &rfds);
> >> >> >>> >>> -       n = select(pipe_fds[0]+1, &rfds, NULL, NULL,
> timeout);
> >> >> >>> >>> -       if (n == 1)
> >> >> >>> >>> -               read(pipe_fds[0], &dummy, 1);
> >> >> >>> >>> -       return n;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * sleep for seconds specified by "second".  Unlike
> >> pool_pause(),
> >> >> this
> >> >> >>> >>> - * function guarantees that it will sleep for specified
> >> seconds.
> >> >>  This
> >> >> >>> >>> - * function uses pool_pause() internally. If it informs that
> >> >> there is
> >> >> >>> >>> - * a pending signal event, they are processed using
> >> CHECK_REQUEST
> >> >> >>> >>> - * macro. Note that most of these processes are done while
> all
> >> >> signals
> >> >> >>> >>> - * are blocked.
> >> >> >>> >>> - */
> >> >> >>> >>> -void pool_sleep(unsigned int second)
> >> >> >>> >>> -{
> >> >> >>> >>> -       struct timeval current_time, sleep_time;
> >> >> >>> >>> -
> >> >> >>> >>> -       gettimeofday(&current_time, NULL);
> >> >> >>> >>> -       sleep_time.tv_sec = second + current_time.tv_sec;
> >> >> >>> >>> -       sleep_time.tv_usec = current_time.tv_usec;
> >> >> >>> >>> -
> >> >> >>> >>> -       POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -       while (sleep_time.tv_sec > current_time.tv_sec)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               struct timeval timeout;
> >> >> >>> >>> -               int r;
> >> >> >>> >>> -
> >> >> >>> >>> -               timeout.tv_sec = sleep_time.tv_sec -
> >> >> >>> current_time.tv_sec;
> >> >> >>> >>> -               timeout.tv_usec = sleep_time.tv_usec -
> >> >> >>> >>> current_time.tv_usec;
> >> >> >>> >>> -               if (timeout.tv_usec < 0)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       timeout.tv_sec--;
> >> >> >>> >>> -                       timeout.tv_usec += 1000000;
> >> >> >>> >>> -               }
> >> >> >>> >>> -
> >> >> >>> >>> -               r = pool_pause(&timeout);
> >> >> >>> >>> -               POOL_SETMASK(&BlockSig);
> >> >> >>> >>> -               if (r > 0)
> >> >> >>> >>> -                       CHECK_REQUEST;
> >> >> >>> >>> -               POOL_SETMASK(&UnBlockSig);
> >> >> >>> >>> -               gettimeofday(&current_time, NULL);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       POOL_SETMASK(&BlockSig);
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * get_config_file_name: return full path of pgpool.conf.
> >> >> >>> >>> - */
> >> >> >>> >>> -char *get_config_file_name(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       return conf_file;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * get_config_file_name: return full path of pool_hba.conf.
> >> >> >>> >>> - */
> >> >> >>> >>> -char *get_hba_file_name(void)
> >> >> >>> >>> + * get_config_file_name: return full path of pool_hba.conf.
> >> >> >>> >>> + */
> >> >> >>> >>> +char *get_hba_file_name(void)
> >> >> >>> >>>  {
> >> >> >>> >>>         return hba_file;
> >> >> >>> >>>  }
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * trigger_failover_command: execute specified command at
> >> >> failover.
> >> >> >>> >>> - *                           command_line is null-terminated
> >> >> string.
> >> >> >>> >>> - */
> >> >> >>> >>> -static int trigger_failover_command(int node, const char
> >> >> >>> *command_line,
> >> >> >>> >>> -
> >> >> >>> >>> int old_master, int new_master, int old_primary)
> >> >> >>> >>> -{
> >> >> >>> >>> -       int r = 0;
> >> >> >>> >>> -       String *exec_cmd;
> >> >> >>> >>> -       char port_buf[6];
> >> >> >>> >>> -       char buf[2];
> >> >> >>> >>> -       BackendInfo *info;
> >> >> >>> >>> -       BackendInfo *newmaster;
> >> >> >>> >>> -
> >> >> >>> >>> -       if (command_line == NULL || (strlen(command_line) ==
> 0))
> >> >> >>> >>> -               return 0;
> >> >> >>> >>> -
> >> >> >>> >>> -       /* check failed nodeID */
> >> >> >>> >>> -       if (node < 0 || node > NUM_BACKENDS)
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -
> >> >> >>> >>> -       info = pool_get_node_info(node);
> >> >> >>> >>> -       if (!info)
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -
> >> >> >>> >>> -       buf[1] = '\0';
> >> >> >>> >>> -       pool_memory = pool_memory_create(PREPARE_BLOCK_SIZE);
> >> >> >>> >>> -       if (!pool_memory)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("trigger_failover_command:
> >> >> >>> >>> pool_memory_create() failed");
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -       exec_cmd = init_string("");
> >> >> >>> >>> -
> >> >> >>> >>> -       while (*command_line)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (*command_line == '%')
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       if (*(command_line + 1))
> >> >> >>> >>> -                       {
> >> >> >>> >>> -                               char val = *(command_line +
> 1);
> >> >> >>> >>> -                               switch (val)
> >> >> >>> >>> -                               {
> >> >> >>> >>> -                                       case 'p': /* failed
> node
> >> >> port
> >> >> >>> */
> >> >> >>> >>> -
> >> snprintf(port_buf,
> >> >> >>> >>> sizeof(port_buf), "%d", info->backend_port);
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, port_buf);
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'D': /* failed
> node
> >> >> >>> database
> >> >> >>> >>> directory */
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, info->backend_data_directory);
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'd': /* failed
> node
> >> >> id */
> >> >> >>> >>> -
> >> snprintf(port_buf,
> >> >> >>> >>> sizeof(port_buf), "%d", node);
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, port_buf);
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'h': /* failed
> host
> >> >> name
> >> >> >>> */
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, info->backend_hostname);
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'H': /* new
> master
> >> >> host
> >> >> >>> name
> >> >> >>> >>> */
> >> >> >>> >>> -                                               newmaster =
> >> >> >>> >>> pool_get_node_info(new_master);
> >> >> >>> >>> -                                               if
> (newmaster)
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, newmaster->backend_hostname);
> >> >> >>> >>> -                                               else
> >> >> >>> >>> -                                                       /* no
> >> >> valid new
> >> >> >>> >>> master */
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, "");
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'm': /* new
> master
> >> >> node
> >> >> >>> id */
> >> >> >>> >>> -
> >> snprintf(port_buf,
> >> >> >>> >>> sizeof(port_buf), "%d", new_master);
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, port_buf);
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'r': /* new
> master
> >> >> port */
> >> >> >>> >>> -                                               newmaster =
> >> >> >>> >>> pool_get_node_info(get_next_master_node());
> >> >> >>> >>> -                                               if
> (newmaster)
> >> >> >>> >>> -                                               {
> >> >> >>> >>> -
> >> >> >>> >>> snprintf(port_buf, sizeof(port_buf), "%d",
> >> >> newmaster->backend_port);
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, port_buf);
> >> >> >>> >>> -                                               }
> >> >> >>> >>> -                                               else
> >> >> >>> >>> -                                                       /* no
> >> >> valid new
> >> >> >>> >>> master */
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, "");
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'R': /* new
> master
> >> >> >>> database
> >> >> >>> >>> directory */
> >> >> >>> >>> -                                               newmaster =
> >> >> >>> >>> pool_get_node_info(get_next_master_node());
> >> >> >>> >>> -                                               if
> (newmaster)
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd,
> newmaster->backend_data_directory);
> >> >> >>> >>> -                                               else
> >> >> >>> >>> -                                                       /* no
> >> >> valid new
> >> >> >>> >>> master */
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, "");
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'M': /* old
> master
> >> >> node
> >> >> >>> id */
> >> >> >>> >>> -
> >> snprintf(port_buf,
> >> >> >>> >>> sizeof(port_buf), "%d", old_master);
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, port_buf);
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case 'P': /* old
> primary
> >> >> node
> >> >> >>> id
> >> >> >>> >>> */
> >> >> >>> >>> -
> >> snprintf(port_buf,
> >> >> >>> >>> sizeof(port_buf), "%d", old_primary);
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, port_buf);
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       case '%': /* escape
> */
> >> >> >>> >>> -
> >> >> >>> >>> string_append_char(exec_cmd, "%");
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -
> >> >> >>> >>> -                                       default: /* ignore */
> >> >> >>> >>> -                                               break;
> >> >> >>> >>> -                               }
> >> >> >>> >>> -                               command_line++;
> >> >> >>> >>> -                       }
> >> >> >>> >>> -               } else {
> >> >> >>> >>> -                       buf[0] = *command_line;
> >> >> >>> >>> -                       string_append_char(exec_cmd, buf);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               command_line++;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (strlen(exec_cmd->data) != 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("execute command: %s",
> exec_cmd->data);
> >> >> >>> >>> -               r = system(exec_cmd->data);
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_memory_delete(pool_memory, 0);
> >> >> >>> >>> -       pool_memory = NULL;
> >> >> >>> >>> -
> >> >> >>> >>> -       return r;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> - * Find the primary node (i.e. not standby node) and returns
> >> its
> >> >> node
> >> >> >>> >>> - * id. If no primary node is found, returns -1.
> >> >> >>> >>> - */
> >> >> >>> >>> -static int find_primary_node(void)
> >> >> >>> >>> -{
> >> >> >>> >>> -       BackendInfo *bkinfo;
> >> >> >>> >>> -       POOL_CONNECTION_POOL_SLOT *s;
> >> >> >>> >>> -       POOL_CONNECTION *con;
> >> >> >>> >>> -       POOL_STATUS status;
> >> >> >>> >>> -       POOL_SELECT_RESULT *res;
> >> >> >>> >>> -       bool is_standby;
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       /* Streaming replication mode? */
> >> >> >>> >>> -       if (pool_config->master_slave_mode == 0 ||
> >> >> >>> >>> -               strcmp(pool_config->master_slave_sub_mode,
> >> >> >>> >>> MODE_STREAMREP))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               /* No point to look for primary node if not
> in
> >> >> >>> streaming
> >> >> >>> >>> -                * replication mode.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               pool_debug("find_primary_node: not in
> streaming
> >> >> >>> >>> replication mode");
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       for(i=0;i<NUM_BACKENDS;i++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               if (!VALID_BACKEND(i))
> >> >> >>> >>> -                       continue;
> >> >> >>> >>> -
> >> >> >>> >>> -               /*
> >> >> >>> >>> -                * Check to see if this is a standby node or
> >> not.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               is_standby = false;
> >> >> >>> >>> -
> >> >> >>> >>> -               bkinfo = pool_get_node_info(i);
> >> >> >>> >>> -               s =
> >> >> >>> >>> make_persistent_db_connection(bkinfo->backend_hostname,
> >> >> >>> >>> -
> >> >> >>> >>>         bkinfo->backend_port,
> >> >> >>> >>> -
> >> >> >>> >>>         "postgres",
> >> >> >>> >>> -
> >> >> >>> >>>         pool_config->sr_check_user,
> >> >> >>> >>> -
> >> >> >>> >>>         pool_config->sr_check_password, true);
> >> >> >>> >>> -               if (!s)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_error("find_primary_node:
> >> >> >>> >>> make_persistent_connection failed");
> >> >> >>> >>> -                       return -1;
> >> >> >>> >>> -               }
> >> >> >>> >>> -               con = s->con;
> >> >> >>> >>> -               status = do_query(con, "SELECT
> >> >> pg_is_in_recovery()",
> >> >> >>> >>> -                                                 &res,
> >> >> >>> PROTO_MAJOR_V3);
> >> >> >>> >>> -               if (res->numrows <= 0)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("find_primary_node: do_query
> >> >> returns
> >> >> >>> no
> >> >> >>> >>> rows");
> >> >> >>> >>> -               }
> >> >> >>> >>> -               if (res->data[0] == NULL)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("find_primary_node: do_query
> >> >> returns
> >> >> >>> no
> >> >> >>> >>> data");
> >> >> >>> >>> -               }
> >> >> >>> >>> -               if (res->nullflags[0] == -1)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_log("find_primary_node: do_query
> >> >> returns
> >> >> >>> >>> NULL");
> >> >> >>> >>> -               }
> >> >> >>> >>> -               if (res->data[0] && !strcmp(res->data[0],
> "t"))
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       is_standby = true;
> >> >> >>> >>> -               }
> >> >> >>> >>> -               free_select_result(res);
> >> >> >>> >>> -               discard_persistent_db_connection(s);
> >> >> >>> >>> -
> >> >> >>> >>> -               /*
> >> >> >>> >>> -                * If this is a standby, we continue to look
> for
> >> >> >>> primary
> >> >> >>> >>> node.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               if (is_standby)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       pool_debug("find_primary_node: %d
> node
> >> is
> >> >> >>> >>> standby", i);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               else
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       break;
> >> >> >>> >>> -               }
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       if (i == NUM_BACKENDS)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_debug("find_primary_node: no primary
> node
> >> >> found");
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       pool_log("find_primary_node: primary node id is %d",
> i);
> >> >> >>> >>> -       return i;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -static int find_primary_node_repeatedly(void)
> >> >> >>> >>> +/* Call back function to unlink the file */
> >> >> >>> >>> +/* Call back function to unlink the file */
> >> >> >>> >>> +static void FileUnlink(int code, Datum path)
> >> >> >>> >>>  {
> >> >> >>> >>> -       int sec;
> >> >> >>> >>> -       int node_id = -1;
> >> >> >>> >>> -
> >> >> >>> >>> -       /* Streaming replication mode? */
> >> >> >>> >>> -       if (pool_config->master_slave_mode == 0 ||
> >> >> >>> >>> -               strcmp(pool_config->master_slave_sub_mode,
> >> >> >>> >>> MODE_STREAMREP))
> >> >> >>> >>> -       {
> >> >> >>> >>> -               /* No point to look for primary node if not
> in
> >> >> >>> streaming
> >> >> >>> >>> -                * replication mode.
> >> >> >>> >>> -                */
> >> >> >>> >>> -               pool_debug("find_primary_node: not in
> streaming
> >> >> >>> >>> replication mode");
> >> >> >>> >>> -               return -1;
> >> >> >>> >>> -       }
> >> >> >>> >>> -
> >> >> >>> >>> -       /*
> >> >> >>> >>> -        * Try to find the new primary node and keep trying
> for
> >> >> >>> >>> -        * search_primary_node_timeout seconds.
> >> >> >>> >>> -        * search_primary_node_timeout = 0 means never
> timeout
> >> and
> >> >> keep
> >> >> >>> >>> searching
> >> >> >>> >>> -        * indefinitely
> >> >> >>> >>> +       char* filePath = (char*)path;
> >> >> >>> >>> +       if (unlink(filePath) == 0) return;
> >> >> >>> >>> +       /*
> >> >> >>> >>> +        * We are already exiting the system just produce a
> log
> >> >> entry
> >> >> >>> to
> >> >> >>> >>> report an error
> >> >> >>> >>>          */
> >> >> >>> >>> -       pool_log("find_primary_node_repeatedly: waiting for
> >> >> finding a
> >> >> >>> >>> primary node");
> >> >> >>> >>> -       for (sec = 0;
> (pool_config->search_primary_node_timeout
> >> ==
> >> >> 0 ||
> >> >> >>> >>> -                               sec <
> >> >> >>> >>> pool_config->search_primary_node_timeout); sec++)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               node_id = find_primary_node();
> >> >> >>> >>> -               if (node_id != -1)
> >> >> >>> >>> -                       break;
> >> >> >>> >>> -               pool_sleep(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       return node_id;
> >> >> >>> >>> -}
> >> >> >>> >>> -
> >> >> >>> >>> -/*
> >> >> >>> >>> -* fork a follow child
> >> >> >>> >>> -*/
> >> >> >>> >>> -pid_t fork_follow_child(int old_master, int new_primary, int
> >> >> >>> old_primary)
> >> >> >>> >>> -{
> >> >> >>> >>> -       pid_t pid;
> >> >> >>> >>> -       int i;
> >> >> >>> >>> -
> >> >> >>> >>> -       pid = fork();
> >> >> >>> >>> -
> >> >> >>> >>> -       if (pid == 0)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_log("start triggering follow command.");
> >> >> >>> >>> -               for (i = 0; i <
> >> >> >>> pool_config->backend_desc->num_backends;
> >> >> >>> >>> i++)
> >> >> >>> >>> -               {
> >> >> >>> >>> -                       BackendInfo *bkinfo;
> >> >> >>> >>> -                       bkinfo = pool_get_node_info(i);
> >> >> >>> >>> -                       if (bkinfo->backend_status ==
> CON_DOWN)
> >> >> >>> >>> -                               trigger_failover_command(i,
> >> >> >>> >>> pool_config->follow_master_command,
> >> >> >>> >>> -
> >> >> >>> >>>        old_master, new_primary, old_primary);
> >> >> >>> >>> -               }
> >> >> >>> >>> -               exit(0);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       else if (pid == -1)
> >> >> >>> >>> -       {
> >> >> >>> >>> -               pool_error("follow fork() failed. reason:
> %s",
> >> >> >>> >>> strerror(errno));
> >> >> >>> >>> -               exit(1);
> >> >> >>> >>> -       }
> >> >> >>> >>> -       return pid;
> >> >> >>> >>> +       ereport(LOG,
> >> >> >>> >>> +               (errmsg("unlink failed for file at path
> \"%s\"",
> >> >> >>> >>> filePath),
> >> >> >>> >>> +                       errdetail("\"%s\"",
> strerror(errno))));
> >> >> >>> >>>  }
> >> >> >>> >>>
> >> >> >>> >>> ...
> >> >> >>> >>>
> >> >> >>> >>> [Message clipped]
> >> >> >>> >>
> >> >> >>> >>
> >> >> >>> >>
> >> >> >>> >>
> >> >> >>> >> --
> >> >> >>> >> Ahsan Hadi
> >> >> >>> >> Snr Director Product Development
> >> >> >>> >> EnterpriseDB Corporation
> >> >> >>> >> The Enterprise Postgres Company
> >> >> >>> >>
> >> >> >>> >> Phone: +92-51-8358874
> >> >> >>> >> Mobile: +92-333-5162114
> >> >> >>> >>
> >> >> >>> >> Website: www.enterprisedb.com
> >> >> >>> >> EnterpriseDB Blog: http://blogs.enterprisedb.com/
> >> >> >>> >> Follow us on Twitter: http://www.twitter.com/enterprisedb
> >> >> >>> >>
> >> >> >>> >> This e-mail message (and any attachment) is intended for the
> use
> >> of
> >> >> the
> >> >> >>> >> individual or entity to whom it is addressed. This message
> >> contains
> >> >> >>> >> information from EnterpriseDB Corporation that may be
> privileged,
> >> >> >>> >> confidential, or exempt from disclosure under applicable law.
> If
> >> >> you are
> >> >> >>> >> not the intended recipient or authorized to receive this for
> the
> >> >> >>> intended
> >> >> >>> >> recipient, any use, dissemination, distribution, retention,
> >> >> archiving,
> >> >> >>> or
> >> >> >>> >> copying of this communication is strictly prohibited. If you
> have
> >> >> >>> received
> >> >> >>> >> this e-mail in error, please notify the sender immediately by
> >> reply
> >> >> >>> e-mail
> >> >> >>> >> and delete this message.
> >> >> >>> >>
> >> >> >>>
> >> >> > _______________________________________________
> >> >> > pgpool-hackers mailing list
> >> >> > pgpool-hackers at pgpool.net
> >> >> > http://www.pgpool.net/mailman/listinfo/pgpool-hackers
> >> >>
> >>
> _______________________________________________
> pgpool-hackers mailing list
> pgpool-hackers at pgpool.net
> http://www.pgpool.net/mailman/listinfo/pgpool-hackers
>



-- 
Ahsan Hadi
Snr Director Product Development
EnterpriseDB Corporation
The Enterprise Postgres Company

Phone: +92-51-8358874
Mobile: +92-333-5162114

Website: www.enterprisedb.com
EnterpriseDB Blog: http://blogs.enterprisedb.com/
Follow us on Twitter: http://www.twitter.com/enterprisedb

This e-mail message (and any attachment) is intended for the use of the
individual or entity to whom it is addressed. This message contains
information from EnterpriseDB Corporation that may be privileged,
confidential, or exempt from disclosure under applicable law. If you are
not the intended recipient or authorized to receive this for the intended
recipient, any use, dissemination, distribution, retention, archiving, or
copying of this communication is strictly prohibited. If you have received
this e-mail in error, please notify the sender immediately by reply e-mail
and delete this message.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.sraoss.jp/pipermail/pgpool-hackers/attachments/20131029/e49124c3/attachment-0001.html>


More information about the pgpool-hackers mailing list