> Other points after reviewing your code.
> 
> First of all I want to make sure that what are not included in the
> patches:
> 
> 1) Shared memory cache
> 2) Cache data when extended protocol is used
> 3) Cache invalidation when receives DDL/DML related to query cache
> 4) Cache should not be registered if transaction aborts
> 5) Cache should not be registered if the table is temporary table
> 6) configure does not recognize "--with-memcached" option. This part,
>    I will write a patch.

I have written patches for this. Attached is the patches *including*
Masanori's patches against CVS HEAD (memqcache.[ch] are not included).

Usage:

./configure --with-memcached=/usr/local

Masanori, you need to do this:

> 7) All memory cache codes using memcached should be surrounded by
>    #ifdef USE_MEMCACHED ... #endif
>
> 8) directive "memqcache_dir" is missing
> 
> Second, questionable codes in the patches:
> 
> 1) No memory allocation error check in add_buf.
> 
> 2) Excess memory allocation in add_buf. If it needs n byte, it allways
>    allocate memqcache_total_size + n bytes. Why do we need extra
>    memqcache_total_size?
> 
> 3) What is this code doing? "con" is never
>    used. memqcache_total_size's 3rd arg is "oid", while you are
>    passing a file descriptor.
> 
>       /* save the received result to buf for each kind */
>       if (pool_config->memory_cache_enabled)
>       {
>               char* con;
>               memqcache_register(kind, frontend, frontend->fd, p1, len1);
>       }
> 
> 4) write_tableoid()
> 
>    - directory should be obtained from memqcache_dir directive
> 
>    - file extention ."txt" is not appropreate becauase the file does
>      not need to be a text file.
> 
>    - writing md5 hash key as a string is wate of space. Just use fwrite().
> 
>    - The function should store md5 hash key + cache ids. Without cache
>      ids, how can you invalidate cache entries?
> 
> 5) About cache key
> 
>    Cache key should be md5(username+query_string+database_name), not
>    just query_string. Also we need to store username at the same time
>    to make sure that the cache data is not accessed by someone
>    else. Otherwise we will have a security concern. See discussions in
>    pgpool-hackers.
> 
>    http://lists.pgfoundry.org/pipermail/pgpool-hackers/2011-June/000817.html
> --
> Tatsuo Ishii
> SRA OSS, Inc. Japan
> English: http://www.sraoss.co.jp/index_en.php
> Japanese: http://www.sraoss.co.jp
Index: Makefile.am
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/Makefile.am,v
retrieving revision 1.53
diff -c -r1.53 Makefile.am
*** Makefile.am	16 Mar 2011 09:11:25 -0000	1.53
--- Makefile.am	28 Jun 2011 10:26:40 -0000
***************
*** 16,21 ****
--- 16,22 ----
  	pool_proto2.c pool_proto_modules.c pool_proto_modules.h \
  	pool_lobj.c pool_lobj.h \
  	pool_process_context.c pool_process_context.h \
+     pool_memqcache.c pool_memqcache.h \
  	pool_session_context.c pool_session_context.h \
  	pool_query_context.c pool_query_context.h \
  	pool_worker_child.c \
***************
*** 40,53 ****
  				pgpool.conf.sample-stream
  pkgdata_DATA = sql/system_db.sql sample/pgpool.pam
  
! AM_CPPFLAGS = -D_GNU_SOURCE -I @PGSQL_INCLUDE_DIR@
  
  # suggested by libtoolize
  ACLOCAL_AMFLAGS = -I m4
  
! pgpool_LDADD = -L@PGSQL_LIB_DIR@ -lpq parser/libsql-parser.a pcp/libpcp.la parser/nodes.o
  if enable_rpath
!   pgpool_LDFLAGS = -rpath @PGSQL_LIB_DIR@ -rpath $(libdir)
  else
    pgpool_LDFLAGS = 
  endif
--- 41,54 ----
  				pgpool.conf.sample-stream
  pkgdata_DATA = sql/system_db.sql sample/pgpool.pam
  
! AM_CPPFLAGS = -D_GNU_SOURCE -I @PGSQL_INCLUDE_DIR@ -I @MEMCACHED_INCLUDE_DIR@
  
  # suggested by libtoolize
  ACLOCAL_AMFLAGS = -I m4
  
! pgpool_LDADD = -L@PGSQL_LIB_DIR@ -lpq parser/libsql-parser.a pcp/libpcp.la parser/nodes.o @MEMCACHED_LINK_OPT@
  if enable_rpath
!   pgpool_LDFLAGS = -rpath @PGSQL_LIB_DIR@ @MEMCACHED_RPATH_OPT@ -rpath $(libdir)
  else
    pgpool_LDFLAGS = 
  endif
Index: Makefile.in
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/Makefile.in,v
retrieving revision 1.56
diff -c -r1.56 Makefile.in
*** Makefile.in	16 Mar 2011 09:11:25 -0000	1.56
--- Makefile.in	28 Jun 2011 10:26:41 -0000
***************
*** 75,84 ****
  	pool_process_reporting.$(OBJEXT) pool_ssl.$(OBJEXT) \
  	pool_timestamp.$(OBJEXT) pool_proto2.$(OBJEXT) \
  	pool_proto_modules.$(OBJEXT) pool_lobj.$(OBJEXT) \
! 	pool_process_context.$(OBJEXT) pool_session_context.$(OBJEXT) \
! 	pool_query_context.$(OBJEXT) pool_worker_child.$(OBJEXT) \
! 	pool_passwd.$(OBJEXT) pool_globals.$(OBJEXT) \
! 	pool_select_walker.$(OBJEXT) getopt_long.$(OBJEXT)
  pgpool_OBJECTS = $(am_pgpool_OBJECTS)
  pgpool_DEPENDENCIES = parser/libsql-parser.a pcp/libpcp.la \
  	parser/nodes.o
--- 75,85 ----
  	pool_process_reporting.$(OBJEXT) pool_ssl.$(OBJEXT) \
  	pool_timestamp.$(OBJEXT) pool_proto2.$(OBJEXT) \
  	pool_proto_modules.$(OBJEXT) pool_lobj.$(OBJEXT) \
! 	pool_process_context.$(OBJEXT) pool_memqcache.$(OBJEXT) \
! 	pool_session_context.$(OBJEXT) pool_query_context.$(OBJEXT) \
! 	pool_worker_child.$(OBJEXT) pool_passwd.$(OBJEXT) \
! 	pool_globals.$(OBJEXT) pool_select_walker.$(OBJEXT) \
! 	getopt_long.$(OBJEXT)
  pgpool_OBJECTS = $(am_pgpool_OBJECTS)
  pgpool_DEPENDENCIES = parser/libsql-parser.a pcp/libpcp.la \
  	parser/nodes.o
***************
*** 181,186 ****
--- 182,190 ----
  LN_S = @LN_S@
  LTLIBOBJS = @LTLIBOBJS@
  MAKEINFO = @MAKEINFO@
+ MEMCACHED_INCLUDE_OPT = @MEMCACHED_INCLUDE_OPT@
+ MEMCACHED_LINK_OPT = @MEMCACHED_LINK_OPT@
+ MEMCACHED_RPATH_OPT = @MEMCACHED_RPATH_OPT@
  MKDIR_P = @MKDIR_P@
  NM = @NM@
  NMEDIT = @NMEDIT@
***************
*** 274,279 ****
--- 278,284 ----
  	pool_proto2.c pool_proto_modules.c pool_proto_modules.h \
  	pool_lobj.c pool_lobj.h \
  	pool_process_context.c pool_process_context.h \
+     pool_memqcache.c pool_memqcache.h \
  	pool_session_context.c pool_session_context.h \
  	pool_query_context.c pool_query_context.h \
  	pool_worker_child.c \
***************
*** 295,307 ****
  				pgpool.conf.sample-stream
  
  pkgdata_DATA = sql/system_db.sql sample/pgpool.pam
! AM_CPPFLAGS = -D_GNU_SOURCE -I @PGSQL_INCLUDE_DIR@
  
  # suggested by libtoolize
  ACLOCAL_AMFLAGS = -I m4
! pgpool_LDADD = -L@PGSQL_LIB_DIR@ -lpq parser/libsql-parser.a pcp/libpcp.la parser/nodes.o
  @enable_rpath_FALSE@pgpool_LDFLAGS = 
! @enable_rpath_TRUE@pgpool_LDFLAGS = -rpath @PGSQL_LIB_DIR@ -rpath $(libdir)
  AM_YFLAGS = -d
  man_MANS = pgpool.8
  CLEANFILES = pgpool.8
--- 300,312 ----
  				pgpool.conf.sample-stream
  
  pkgdata_DATA = sql/system_db.sql sample/pgpool.pam
! AM_CPPFLAGS = -D_GNU_SOURCE -I @PGSQL_INCLUDE_DIR@ -I @MEMCACHED_INCLUDE_DIR@
  
  # suggested by libtoolize
  ACLOCAL_AMFLAGS = -I m4
! pgpool_LDADD = -L@PGSQL_LIB_DIR@ -lpq parser/libsql-parser.a pcp/libpcp.la parser/nodes.o @MEMCACHED_LINK_OPT@
  @enable_rpath_FALSE@pgpool_LDFLAGS = 
! @enable_rpath_TRUE@pgpool_LDFLAGS = -rpath @PGSQL_LIB_DIR@ @MEMCACHED_RPATH_OPT@ -rpath $(libdir)
  AM_YFLAGS = -d
  man_MANS = pgpool.8
  CLEANFILES = pgpool.8
***************
*** 360,366 ****
  SUBDIRS = parser pcp
  all: config.h
  	$(MAKE) $(AM_MAKEFLAGS) all-recursive
- 	+@echo "All of pgPool-II successfully made. Ready to install."
  
  .SUFFIXES:
  .SUFFIXES: .c .l .lo .o .obj
--- 365,370 ----
***************
*** 470,475 ****
--- 474,480 ----
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_hba.Po@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_ip.Po@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_lobj.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_memqcache.Po@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_params.Po@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_passwd.Po@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_path.Po@am__quote@
***************
*** 896,902 ****
  	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
  	done
  install: install-recursive
- 	+@echo "pgPool-II installation complete."
  install-exec: install-exec-recursive
  install-data: install-data-recursive
  uninstall: uninstall-recursive
--- 901,906 ----
Index: config.h.in
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/config.h.in,v
retrieving revision 1.12
diff -c -r1.12 config.h.in
*** config.h.in	10 Nov 2010 01:53:50 -0000	1.12
--- config.h.in	28 Jun 2011 10:26:47 -0000
***************
*** 70,75 ****
--- 70,81 ----
  /* Define to 1 if you have the `m' library (-lm). */
  #undef HAVE_LIBM
  
+ /* Define to 1 if you have the `memcached' library (-lmemcached). */
+ #undef HAVE_LIBMEMCACHED
+ 
+ /* Define to 1 if you have the <libmemcached/memcached.h> header file. */
+ #undef HAVE_LIBMEMCACHED_MEMCACHED_H
+ 
  /* Define to 1 if you have the `nsl' library (-lnsl). */
  #undef HAVE_LIBNSL
  
***************
*** 286,291 ****
--- 292,300 ----
     (--enable-float8-byval) */
  #undef USE_FLOAT8_BYVAL
  
+ /* Define to 1 to build with memcached support */
+ #undef USE_MEMCACHED
+ 
  /* Define to 1 to build with PAM support. (--with-pam) */
  #undef USE_PAM
  
Index: configure
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/configure,v
retrieving revision 1.48
diff -c -r1.48 configure
*** configure	22 Apr 2011 02:50:27 -0000	1.48
--- configure	28 Jun 2011 10:26:58 -0000
***************
*** 788,793 ****
--- 788,796 ----
  enable_rpath_TRUE
  PGSQL_LIB_DIR
  PGSQL_INCLUDE_DIR
+ MEMCACHED_RPATH_OPT
+ MEMCACHED_LINK_OPT
+ MEMCACHED_INCLUDE_OPT
  PGCONFIG
  LIBOBJS
  YFLAGS
***************
*** 916,921 ****
--- 919,925 ----
  with_pgsql_libdir
  with_openssl
  with_pam
+ with_memcached
  enable_rpath
  '
        ac_precious_vars='build_alias
***************
*** 1579,1584 ****
--- 1583,1589 ----
    --with-pgsql-libdir=DIR     site library files for PostgreSQL in DIR
    --with-openssl     build with OpenSSL support
    --with-pam     build with PAM support
+   --with-memcached=DIR     site header files for libmemcached in DIR
  
  Some influential environment variables:
    CC          C compiler command
***************
*** 4423,4435 ****
  else
    lt_cv_nm_interface="BSD nm"
    echo "int some_variable = 0;" > conftest.$ac_ext
!   (eval echo "\"\$as_me:4426: $ac_compile\"" >&5)
    (eval "$ac_compile" 2>conftest.err)
    cat conftest.err >&5
!   (eval echo "\"\$as_me:4429: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
    (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
    cat conftest.err >&5
!   (eval echo "\"\$as_me:4432: output\"" >&5)
    cat conftest.out >&5
    if $GREP 'External.*some_variable' conftest.out > /dev/null; then
      lt_cv_nm_interface="MS dumpbin"
--- 4428,4440 ----
  else
    lt_cv_nm_interface="BSD nm"
    echo "int some_variable = 0;" > conftest.$ac_ext
!   (eval echo "\"\$as_me:4431: $ac_compile\"" >&5)
    (eval "$ac_compile" 2>conftest.err)
    cat conftest.err >&5
!   (eval echo "\"\$as_me:4434: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
    (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
    cat conftest.err >&5
!   (eval echo "\"\$as_me:4437: output\"" >&5)
    cat conftest.out >&5
    if $GREP 'External.*some_variable' conftest.out > /dev/null; then
      lt_cv_nm_interface="MS dumpbin"
***************
*** 5635,5641 ****
    ;;
  *-*-irix6*)
    # Find out which ABI we are using.
!   echo '#line 5638 "configure"' > conftest.$ac_ext
    if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
    (eval $ac_compile) 2>&5
    ac_status=$?
--- 5640,5646 ----
    ;;
  *-*-irix6*)
    # Find out which ABI we are using.
!   echo '#line 5643 "configure"' > conftest.$ac_ext
    if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
    (eval $ac_compile) 2>&5
    ac_status=$?
***************
*** 7488,7498 ****
     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
     -e 's:$: $lt_compiler_flag:'`
!    (eval echo "\"\$as_me:7491: $lt_compile\"" >&5)
     (eval "$lt_compile" 2>conftest.err)
     ac_status=$?
     cat conftest.err >&5
!    echo "$as_me:7495: \$? = $ac_status" >&5
     if (exit $ac_status) && test -s "$ac_outfile"; then
       # The compiler can only warn and ignore the option if not recognized
       # So say no if there are warnings other than the usual output.
--- 7493,7503 ----
     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
     -e 's:$: $lt_compiler_flag:'`
!    (eval echo "\"\$as_me:7496: $lt_compile\"" >&5)
     (eval "$lt_compile" 2>conftest.err)
     ac_status=$?
     cat conftest.err >&5
!    echo "$as_me:7500: \$? = $ac_status" >&5
     if (exit $ac_status) && test -s "$ac_outfile"; then
       # The compiler can only warn and ignore the option if not recognized
       # So say no if there are warnings other than the usual output.
***************
*** 7827,7837 ****
     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
     -e 's:$: $lt_compiler_flag:'`
!    (eval echo "\"\$as_me:7830: $lt_compile\"" >&5)
     (eval "$lt_compile" 2>conftest.err)
     ac_status=$?
     cat conftest.err >&5
!    echo "$as_me:7834: \$? = $ac_status" >&5
     if (exit $ac_status) && test -s "$ac_outfile"; then
       # The compiler can only warn and ignore the option if not recognized
       # So say no if there are warnings other than the usual output.
--- 7832,7842 ----
     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
     -e 's:$: $lt_compiler_flag:'`
!    (eval echo "\"\$as_me:7835: $lt_compile\"" >&5)
     (eval "$lt_compile" 2>conftest.err)
     ac_status=$?
     cat conftest.err >&5
!    echo "$as_me:7839: \$? = $ac_status" >&5
     if (exit $ac_status) && test -s "$ac_outfile"; then
       # The compiler can only warn and ignore the option if not recognized
       # So say no if there are warnings other than the usual output.
***************
*** 7932,7942 ****
     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
     -e 's:$: $lt_compiler_flag:'`
!    (eval echo "\"\$as_me:7935: $lt_compile\"" >&5)
     (eval "$lt_compile" 2>out/conftest.err)
     ac_status=$?
     cat out/conftest.err >&5
!    echo "$as_me:7939: \$? = $ac_status" >&5
     if (exit $ac_status) && test -s out/conftest2.$ac_objext
     then
       # The compiler can only warn and ignore the option if not recognized
--- 7937,7947 ----
     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
     -e 's:$: $lt_compiler_flag:'`
!    (eval echo "\"\$as_me:7940: $lt_compile\"" >&5)
     (eval "$lt_compile" 2>out/conftest.err)
     ac_status=$?
     cat out/conftest.err >&5
!    echo "$as_me:7944: \$? = $ac_status" >&5
     if (exit $ac_status) && test -s out/conftest2.$ac_objext
     then
       # The compiler can only warn and ignore the option if not recognized
***************
*** 7987,7997 ****
     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
     -e 's:$: $lt_compiler_flag:'`
!    (eval echo "\"\$as_me:7990: $lt_compile\"" >&5)
     (eval "$lt_compile" 2>out/conftest.err)
     ac_status=$?
     cat out/conftest.err >&5
!    echo "$as_me:7994: \$? = $ac_status" >&5
     if (exit $ac_status) && test -s out/conftest2.$ac_objext
     then
       # The compiler can only warn and ignore the option if not recognized
--- 7992,8002 ----
     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
     -e 's:$: $lt_compiler_flag:'`
!    (eval echo "\"\$as_me:7995: $lt_compile\"" >&5)
     (eval "$lt_compile" 2>out/conftest.err)
     ac_status=$?
     cat out/conftest.err >&5
!    echo "$as_me:7999: \$? = $ac_status" >&5
     if (exit $ac_status) && test -s out/conftest2.$ac_objext
     then
       # The compiler can only warn and ignore the option if not recognized
***************
*** 10790,10796 ****
    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
    lt_status=$lt_dlunknown
    cat > conftest.$ac_ext <<_LT_EOF
! #line 10793 "configure"
  #include "confdefs.h"
  
  #if HAVE_DLFCN_H
--- 10795,10801 ----
    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
    lt_status=$lt_dlunknown
    cat > conftest.$ac_ext <<_LT_EOF
! #line 10798 "configure"
  #include "confdefs.h"
  
  #if HAVE_DLFCN_H
***************
*** 10886,10892 ****
    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
    lt_status=$lt_dlunknown
    cat > conftest.$ac_ext <<_LT_EOF
! #line 10889 "configure"
  #include "confdefs.h"
  
  #if HAVE_DLFCN_H
--- 10891,10897 ----
    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
    lt_status=$lt_dlunknown
    cat > conftest.$ac_ext <<_LT_EOF
! #line 10894 "configure"
  #include "confdefs.h"
  
  #if HAVE_DLFCN_H
***************
*** 17199,17204 ****
--- 17204,17472 ----
  
  fi
  
+ 
+ # Check whether --with-memcached was given.
+ if test "${with_memcached+set}" = set; then
+   withval=$with_memcached;
+ 	case "$withval" in
+ 	"" | y | ye | yes | n | no)
+ 	    { { $as_echo "$as_me:$LINENO: error: *** You must supply an argument to the --with-memcached option." >&5
+ $as_echo "$as_me: error: *** You must supply an argument to the --with-memcached option." >&2;}
+    { (exit 1); exit 1; }; }
+ 	  ;;
+     *)
+ 
+ 	MEMCACHED_INCLUDE_DIR="$withval"/include
+ 	MEMCACHED_LIB_DIR="$withval"/lib
+ 	OLD_CFLAGS="$CFLAGS"
+ 	CFLAGS="$CFLAGS -I$MEMCACHED_INCLUDE_DIR"
+ 
+ for ac_header in libmemcached/memcached.h
+ do
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+   { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+ $as_echo_n "checking for $ac_header... " >&6; }
+ if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+   $as_echo_n "(cached) " >&6
+ fi
+ ac_res=`eval 'as_val=${'$as_ac_Header'}
+ 		 $as_echo "$as_val"'`
+ 	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+ $as_echo "$ac_res" >&6; }
+ else
+   # Is the header compilable?
+ { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5
+ $as_echo_n "checking $ac_header usability... " >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h.  */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+ cat >>conftest.$ac_ext <<_ACEOF
+ /* end confdefs.h.  */
+ $ac_includes_default
+ #include <$ac_header>
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (ac_try="$ac_compile"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+ $as_echo "$ac_try_echo") >&5
+   (eval "$ac_compile") 2>conftest.er1
+   ac_status=$?
+   grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } && {
+ 	 test -z "$ac_c_werror_flag" ||
+ 	 test ! -s conftest.err
+        } && test -s conftest.$ac_objext; then
+   ac_header_compiler=yes
+ else
+   $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+ 	ac_header_compiler=no
+ fi
+ 
+ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+ $as_echo "$ac_header_compiler" >&6; }
+ 
+ # Is the header present?
+ { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5
+ $as_echo_n "checking $ac_header presence... " >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h.  */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+ cat >>conftest.$ac_ext <<_ACEOF
+ /* end confdefs.h.  */
+ #include <$ac_header>
+ _ACEOF
+ if { (ac_try="$ac_cpp conftest.$ac_ext"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+ $as_echo "$ac_try_echo") >&5
+   (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+   ac_status=$?
+   grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } >/dev/null && {
+ 	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ 	 test ! -s conftest.err
+        }; then
+   ac_header_preproc=yes
+ else
+   $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+   ac_header_preproc=no
+ fi
+ 
+ rm -f conftest.err conftest.$ac_ext
+ { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+ $as_echo "$ac_header_preproc" >&6; }
+ 
+ # So?  What about this header?
+ case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+   yes:no: )
+     { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+ $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+     { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+ $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+     ac_header_preproc=yes
+     ;;
+   no:yes:* )
+     { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+ $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+     { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+ $as_echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+     { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+ $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+     { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+ $as_echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+     { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+ $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+     { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+ $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ 
+     ;;
+ esac
+ { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+ $as_echo_n "checking for $ac_header... " >&6; }
+ if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+   $as_echo_n "(cached) " >&6
+ else
+   eval "$as_ac_Header=\$ac_header_preproc"
+ fi
+ ac_res=`eval 'as_val=${'$as_ac_Header'}
+ 		 $as_echo "$as_val"'`
+ 	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+ $as_echo "$ac_res" >&6; }
+ 
+ fi
+ as_val=`eval 'as_val=${'$as_ac_Header'}
+ 		 $as_echo "$as_val"'`
+    if test "x$as_val" = x""yes; then
+   cat >>confdefs.h <<_ACEOF
+ #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+ _ACEOF
+ 
+ cat >>confdefs.h <<\_ACEOF
+ #define USE_MEMCACHED 1
+ _ACEOF
+ 
+ else
+   { { $as_echo "$as_me:$LINENO: error: header file <libmemcached/memcached.h> is required for memcached support" >&5
+ $as_echo "$as_me: error: header file <libmemcached/memcached.h> is required for memcached support" >&2;}
+    { (exit 1); exit 1; }; }
+ fi
+ 
+ done
+ 
+ 	CFLAGS=$OLD_CFLAGS
+ 
+ { $as_echo "$as_me:$LINENO: checking for memcached_create in -lmemcached" >&5
+ $as_echo_n "checking for memcached_create in -lmemcached... " >&6; }
+ if test "${ac_cv_lib_memcached_memcached_create+set}" = set; then
+   $as_echo_n "(cached) " >&6
+ else
+   ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lmemcached  $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h.  */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+ cat >>conftest.$ac_ext <<_ACEOF
+ /* end confdefs.h.  */
+ 
+ /* Override any GCC internal prototype to avoid an error.
+    Use char because int might match the return type of a GCC
+    builtin and then its argument prototype would still apply.  */
+ #ifdef __cplusplus
+ extern "C"
+ #endif
+ char memcached_create ();
+ int
+ main ()
+ {
+ return memcached_create ();
+   ;
+   return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (ac_try="$ac_link"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+ $as_echo "$ac_try_echo") >&5
+   (eval "$ac_link") 2>conftest.er1
+   ac_status=$?
+   grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } && {
+ 	 test -z "$ac_c_werror_flag" ||
+ 	 test ! -s conftest.err
+        } && test -s conftest$ac_exeext && {
+ 	 test "$cross_compiling" = yes ||
+ 	 $as_test_x conftest$ac_exeext
+        }; then
+   ac_cv_lib_memcached_memcached_create=yes
+ else
+   $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+ 	ac_cv_lib_memcached_memcached_create=no
+ fi
+ 
+ rm -rf conftest.dSYM
+ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+       conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+ { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_memcached_memcached_create" >&5
+ $as_echo "$ac_cv_lib_memcached_memcached_create" >&6; }
+ if test "x$ac_cv_lib_memcached_memcached_create" = x""yes; then
+   cat >>confdefs.h <<_ACEOF
+ #define HAVE_LIBMEMCACHED 1
+ _ACEOF
+ 
+   LIBS="-lmemcached $LIBS"
+ 
+ else
+   { { $as_echo "$as_me:$LINENO: error: libmemcached is not installed" >&5
+ $as_echo "$as_me: error: libmemcached is not installed" >&2;}
+    { (exit 1); exit 1; }; }
+ fi
+ 
+ 	MEMCACHED_INCLUDE_OPT="-I $MEMCACHED_INCLUDE_DIR"
+ 	MEMCACHED_LINK_OPT="-L$MEMCACHED_LIB_DIR"
+ 	MEMCACHED_RPATH_OPT="-rpath $MEMCACHED_LIB_DIR"
+ 	;;
+ 	esac
+ 
+ fi
+ 
+ 
+ 
+ 
+ 
+ 
  OLD_LDFLAGS="$LDFLAGS"
  LDFLAGS="-L$PGSQL_LIB_DIR"
  OLD_LIBS="$LIBS"
Index: configure.in
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/configure.in,v
retrieving revision 1.45
diff -c -r1.45 configure.in
*** configure.in	22 Apr 2011 02:50:27 -0000	1.45
--- configure.in	28 Jun 2011 10:26:58 -0000
***************
*** 310,315 ****
--- 310,345 ----
                                        [AC_MSG_ERROR([header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.])])])
  fi
  
+ AC_ARG_WITH(memcached,
+     [  --with-memcached=DIR     site header files for libmemcached in DIR],
+     [
+ 	case "$withval" in
+ 	"" | y | ye | yes | n | no)
+ 	    AC_MSG_ERROR([*** You must supply an argument to the --with-memcached option.])
+ 	  ;;
+     *)
+ 
+ 	MEMCACHED_INCLUDE_DIR="$withval"/include
+ 	MEMCACHED_LIB_DIR="$withval"/lib
+ 	OLD_CFLAGS="$CFLAGS"
+ 	CFLAGS="$CFLAGS -I$MEMCACHED_INCLUDE_DIR"
+     AC_CHECK_HEADERS(
+ 		[libmemcached/memcached.h],
+         [AC_DEFINE([USE_MEMCACHED], 1, [Define to 1 to build with memcached support])],
+         [AC_MSG_ERROR([header file <libmemcached/memcached.h> is required for memcached support])])
+ 	CFLAGS=$OLD_CFLAGS
+ 	AC_CHECK_LIB(memcached, memcached_create, [], [AC_MSG_ERROR(libmemcached is not installed)])
+ 	MEMCACHED_INCLUDE_OPT="-I $MEMCACHED_INCLUDE_DIR"
+ 	MEMCACHED_LINK_OPT="-L$MEMCACHED_LIB_DIR"
+ 	MEMCACHED_RPATH_OPT="-rpath $MEMCACHED_LIB_DIR"
+ 	;;
+ 	esac
+ 	])
+ 
+ AC_SUBST(MEMCACHED_INCLUDE_OPT)
+ AC_SUBST(MEMCACHED_LINK_OPT)
+ AC_SUBST(MEMCACHED_RPATH_OPT)
+ 
  OLD_LDFLAGS="$LDFLAGS"
  LDFLAGS="-L$PGSQL_LIB_DIR"
  OLD_LIBS="$LIBS"
Index: pgpool.conf.sample
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pgpool.conf.sample,v
retrieving revision 1.45
diff -c -r1.45 pgpool.conf.sample
*** pgpool.conf.sample	21 Apr 2011 05:00:52 -0000	1.45
--- pgpool.conf.sample	28 Jun 2011 10:26:58 -0000
***************
*** 329,331 ****
--- 329,355 ----
  # is not consistent anymore.
  # For this purpose, cache_expiration controls the life time of the cache.
  relcache_expire = 0
+ 
+ # If true, use the memory cache functionality, false by default
+ memory_cache_enabled = true
+ 
+ # Cache store method. either shmem(shared memory) or Memcached. shmem by default
+ memqcache_method = 'memcached'
+ 
+ # Memcached host name. Mandatory if memqcache_method=memcached.
+ memqcache_memcached_host = 'localhost'
+ 
+ # Memcached port number. Mondatory if memqcache_method=memcached.
+ memqcache_memcached_port=11211
+ 
+ # Total memory size in bytes for storing memory cache. Mandatory if memqcache_method=shmem.
+ memqcache_total_size=10240
+ 
+ # Memory cache entry life time specified in seconds. 60 by default.
+ memqcache_expire=60
+ 
+ # Maximum SELECT result size in bytes.
+ memqcache_maxcache=512
+ 
+ # Cache block size in bytes. 8192 by default
+ memqcache_cache_block_size=8192
Index: pool_config.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.c,v
retrieving revision 1.60
diff -c -r1.60 pool_config.c
*** pool_config.c	6 May 2011 23:43:26 -0000	1.60
--- pool_config.c	28 Jun 2011 10:27:00 -0000
***************
*** 1936,1941 ****
--- 1936,1950 ----
  	pool_config->pattc = 0;
  	pool_config->current_pattern_size = 0;
  
+ 	pool_config->memory_cache_enabled = 0;
+ 	pool_config->memqcache_method = "memcached";
+ 	pool_config->memqcache_memcached_host = "";
+ 	pool_config->memqcache_memcached_port = 11211;
+     pool_config->memqcache_total_size = 10240;
+     pool_config->memqcache_expire = 60;
+     pool_config->memqcache_maxcache = 512;
+     pool_config->memqcache_cache_block_size = 8192;
+ 
  	res = gethostname(localhostname,sizeof(localhostname));
  	if(res !=0 )
  	{
***************
*** 3441,3446 ****
--- 3450,3564 ----
  			}
  			pool_config->relcache_expire = v;
  		}
+         else if (!strcmp(key, "memory_cache_enabled") &&
+                  CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+         {
+             int v = eval_logical(yytext);
+ 
+             if (v < 0)
+             {
+                 pool_error("pool_config: invalid value %s for %s", yytext, key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memory_cache_enabled = v;
+         }
+         else if (!strcmp(key, "memqcache_method") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             char *str;
+ 
+             if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+             {
+                 PARSE_ERROR();
+                 fclose(fd);
+                 return(-1);
+             }
+             str = extract_string(yytext, token);
+             if (str == NULL)
+             {
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_method = str;
+         }
+         else if (!strcmp(key, "memqcache_memcached_host") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             char *str;
+ 
+             if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+             {
+                 PARSE_ERROR();
+                 fclose(fd);
+                 return(-1);
+             }
+             str = extract_string(yytext, token);
+             if (str == NULL)
+             {
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_memcached_host = str;
+         }
+         else if (!strcmp(key, "memqcache_memcached_port") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_memcached_port = v;
+         }
+         else if (!strcmp(key, "memqcache_total_size") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_total_size = v;
+         }
+         else if (!strcmp(key, "memqcache_expire") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_expire = v;
+         }
+         else if (!strcmp(key, "memqcache_maxcache") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_maxcache = v;
+         }
+         else if (!strcmp(key, "memqcache_cache_block_size") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_cache_block_size = v;
+         }
  
  	}
  
Index: pool_config.h
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.h,v
retrieving revision 1.13
diff -c -r1.13 pool_config.h
*** pool_config.h	30 Mar 2011 02:13:07 -0000	1.13
--- pool_config.h	28 Jun 2011 10:27:00 -0000
***************
*** 174,179 ****
--- 174,188 ----
  	RegPattern *lists_patterns; /* Precompiled regex patterns for black/white lists */
  	int pattc; /* number of regexp pattern */
  	int current_pattern_size; /* size of the regex pattern array */
+ 
+ 	int memory_cache_enabled;   /* if true, use the memory cache functionality, false by default */
+ 	char *memqcache_method;   /* Cache store method. Either 'shmem'(shared memory) or 'memcached'. 'shmem' by default */
+ 	char *memqcache_memcached_host;   /* Memcached host name. Mandatory if memqcache_method=memcached. */
+ 	int memqcache_memcached_port;   /* Memcached port number. Mondatory if memqcache_method=memcached. */
+ 	int memqcache_total_size;   /* Total memory size in bytes for storing memory cache. Mandatory if memqcache_method=shmem. */
+ 	int memqcache_expire;   /* Memory cache entry life time specified in seconds. 60 by default. */
+ 	int memqcache_maxcache;   /* Maximum SELECT result size in bytes. */
+ 	int memqcache_cache_block_size;   /* Cache block size in bytes. 8192 by default */
  } POOL_CONFIG;
  
  typedef enum {
Index: pool_config.l
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_config.l,v
retrieving revision 1.56
diff -c -r1.56 pool_config.l
*** pool_config.l	6 May 2011 23:43:26 -0000	1.56
--- pool_config.l	28 Jun 2011 10:27:01 -0000
***************
*** 211,216 ****
--- 211,225 ----
  	pool_config->pattc = 0;
  	pool_config->current_pattern_size = 0;
  
+     pool_config->memory_cache_enabled = 0;
+     pool_config->memqcache_method = "memcached";
+     pool_config->memqcache_memcached_host = "";
+     pool_config->memqcache_memcached_port = 11211;
+     pool_config->memqcache_total_size = 10240;
+     pool_config->memqcache_expire = 60;
+     pool_config->memqcache_maxcache = 512;
+     pool_config->memqcache_cache_block_size = 8192;
+ 
  	res = gethostname(localhostname,sizeof(localhostname));
  	if(res !=0 )
  	{
***************
*** 1716,1721 ****
--- 1725,1839 ----
  			}
  			pool_config->relcache_expire = v;
  		}
+         else if (!strcmp(key, "memory_cache_enabled") &&
+                  CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context))
+         {
+             int v = eval_logical(yytext);
+ 
+             if (v < 0)
+             {
+                 pool_error("pool_config: invalid value %s for %s", yytext, key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memory_cache_enabled = v;
+         }
+         else if (!strcmp(key, "memqcache_method") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             char *str;
+ 
+             if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+             {
+                 PARSE_ERROR();
+                 fclose(fd);
+                 return(-1);
+             }
+             str = extract_string(yytext, token);
+             if (str == NULL)
+             {
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_method = str;
+         }
+         else if (!strcmp(key, "memqcache_memcached_host") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             char *str;
+ 
+             if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+             {
+                 PARSE_ERROR();
+                 fclose(fd);
+                 return(-1);
+             }
+             str = extract_string(yytext, token);
+             if (str == NULL)
+             {
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_memcached_host = str;
+         }
+         else if (!strcmp(key, "memqcache_memcached_port") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_memcached_port = v;
+         }
+         else if (!strcmp(key, "memqcache_total_size") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_total_size = v;
+         }
+         else if (!strcmp(key, "memqcache_expire") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_expire = v;
+         }
+         else if (!strcmp(key, "memqcache_maxcache") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_maxcache = v;
+         }
+         else if (!strcmp(key, "memqcache_cache_block_size") && CHECK_CONTEXT(INIT_CONFIG, context))
+         {
+             int v = atoi(yytext);
+ 
+             if (token != POOL_INTEGER || v < 0)
+             {
+                 pool_error("pool_config: %s must be equal or higher than 0 numeric value", key);
+                 fclose(fd);
+                 return(-1);
+             }
+             pool_config->memqcache_cache_block_size = v;
+         }
  
  	}
  
Index: pool_process_query.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_process_query.c,v
retrieving revision 1.259
diff -c -r1.259 pool_process_query.c
*** pool_process_query.c	13 May 2011 06:53:05 -0000	1.259
--- pool_process_query.c	28 Jun 2011 10:27:03 -0000
***************
*** 52,57 ****
--- 52,58 ----
  #include "pool_session_context.h"
  #include "pool_query_context.h"
  #include "pool_select_walker.h"
+ #include "pool_memqcache.h"
  
  #ifndef FD_SETSIZE
  #define FD_SETSIZE 512
***************
*** 107,112 ****
--- 108,124 ----
  	qcnt = 0;
  	state = 0;
  
+ 	/* Try to connect memcached */
+ 	if (pool_config->memory_cache_enabled)
+ 	{
+ 		int res;
+ 		res = memcached_connect();
+ 		if (res < 0)
+ 		{
+ 			pool_debug("Could not connect the Memcached");
+ 		}
+ 	}
+ 
  	for (;;)
  	{
  		/* Are we requested to send reset queries? */
***************
*** 1163,1168 ****
--- 1175,1187 ----
  		query_cache_register(kind, frontend, backend->info->database, p1, len1);
  	}
  
+ 	/* save the received result to buf for each kind */
+ 	if (pool_config->memory_cache_enabled)
+ 	{
+ 		char* con;
+ 		memqcache_register(kind, frontend, frontend->fd, p1, len1);
+ 	}
+ 
  	/* error response? */
  	if (kind == 'E')
  	{
Index: pool_proto_modules.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_proto_modules.c,v
retrieving revision 1.98
diff -c -r1.98 pool_proto_modules.c
*** pool_proto_modules.c	5 Jun 2011 23:03:06 -0000	1.98
--- pool_proto_modules.c	28 Jun 2011 10:27:04 -0000
***************
*** 55,60 ****
--- 55,61 ----
  #include "pool_session_context.h"
  #include "pool_query_context.h"
  #include "pool_lobj.h"
+ #include "pool_memqcache.h"
  
  char *copy_table = NULL;  /* copy table name */
  char *copy_schema = NULL;  /* copy table name */
***************
*** 191,196 ****
--- 192,214 ----
  			}
  		}
  
+ 		if (pool_config->memory_cache_enabled)
+ 		{
+ 			if (IsA(node, SelectStmt) && !(is_select_pgcatalog = IsSelectpgcatalog(node, backend)))
+ 			{
+ 				if (memqcache_lookup(frontend, backend, node) == POOL_CONTINUE)
+ 				{
+ 					return POOL_CONTINUE;
+ 				}
+ 			}
+ 			else if ((strncasecmp("DELETE", node, 6) == 0) || (strncasecmp("UPDATE", node, 6) == 0)
+ 			 || (strncasecmp("INSERT", node, 6) == 0) || (strncasecmp("DELETE", node, 6) == 0)
+ 			 || (strncasecmp("ALTER", node, 5) == 0) || (strncasecmp("DROP", node, 4) == 0))
+ 			{
+ 				set_update_sql_flag(1);
+ 			}
+ 		}
+ 
  		/*
  		 * Start query context
  		 */
***************
*** 1720,1725 ****
--- 1738,1749 ----
  		query_cache_register('C', frontend, backend->info->database, p1, len1);
  	}
  
+ 	/* save the received result to buf for each kind */
+ 	if (pool_config->memory_cache_enabled)
+ 	{
+ 		memqcache_register('C', frontend, 0, p1, len1);
+ 	}
+ 
  	free(p1);
  
  	return POOL_CONTINUE;
***************
*** 2117,2123 ****
--- 2141,2152 ----
  				break;
  
  			case 'Z':	/* ReadyForQuery */
+ 				if (pool_config->memory_cache_enabled)
+ 				{
+ 					set_cache_on_memcached(frontend, get_key(), get_buf());
+ 				}
  				status = ReadyForQuery(frontend, backend, 1);
+ 				init_buf();
  				break;
  
  			case '1':	/* ParseComplete */
Index: pool_select_walker.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_select_walker.c,v
retrieving revision 1.10
diff -c -r1.10 pool_select_walker.c
*** pool_select_walker.c	19 Jun 2011 08:56:38 -0000	1.10
--- pool_select_walker.c	28 Jun 2011 10:27:04 -0000
***************
*** 33,38 ****
--- 33,39 ----
  	bool	has_system_catalog;		/* True if system catalog table is used */
  	bool	has_temp_table;		/* True if temporary table is used */
  	bool	has_function_call;	/* True if write function call is used */	
+ 	bool	has_non_immutable_function_call;	/* True if non stable functions are used */
  } SelectContext;
  
  static bool function_call_walker(Node *node, void *context);
***************
*** 40,45 ****
--- 41,48 ----
  static bool is_system_catalog(char *table_name);
  static bool temp_table_walker(Node *node, void *context);
  static bool is_temp_table(char *table_name);
+ static bool non_immutable_function_call_walker(Node *node, void *context);
+ static bool is_immutable_function(char *fname);
  
  /*
   * Return true if this SELECT has function calls *and* supposed to
***************
*** 453,455 ****
--- 456,550 ----
  	result = pool_search_relcache(relcache, backend, "pgpool_regclass")==0?0:1;
  	return result;
  }
+ 
+ /*
+  * Return true if this SELECT has non immutable function calls.
+  */
+ bool pool_has_non_immutable_function_call(Node *node)
+ {
+ 	SelectContext	ctx;
+ 
+ 	if (!IsA(node, SelectStmt))
+ 		return false;
+ 
+  	ctx.has_non_immutable_function_call = false;
+ 
+ 	raw_expression_tree_walker(node, non_immutable_function_call_walker, &ctx);
+ 
+ 	pool_debug("pool_has_non_immutable_function_call: %d", ctx.has_non_immutable_function_call);
+ 	return ctx.has_non_immutable_function_call;
+ }
+ 
+ /*
+  * Walker function to find non immutable function call.
+  */
+ static bool non_immutable_function_call_walker(Node *node, void *context)
+ {
+ 	SelectContext	*ctx = (SelectContext *) context;
+ 
+ 	if (node == NULL)
+ 		return false;
+ 
+ 	if (IsA(node, FuncCall))
+ 	{
+ 		FuncCall *fcall = (FuncCall *)node;
+ 		char *fname;
+ 		int length = list_length(fcall->funcname);
+ 
+ 		if (length > 0)
+ 		{
+ 			if (length == 1)	/* no schema qualification? */
+ 			{
+ 				fname = strVal(linitial(fcall->funcname));
+ 			}
+ 			else
+ 			{
+ 				fname = strVal(lsecond(fcall->funcname));		/* with schema qualification */
+ 			}
+ 
+ 			pool_debug("non_immutable_function_call_walker: function name: %s", fname);
+ 
+ 			/* Check system catalog if the function is immutable */
+ 			if (is_immutable_function(fname) == false)
+ 			{
+ 				/* Non immutable function call found */
+ 				ctx->has_non_immutable_function_call = true;
+ 				return false;
+ 			}
+ 		}
+ 	}
+ 	return raw_expression_tree_walker(node, non_immutable_function_call_walker, context);
+ }
+ 
+ /*
+  * Check if the function is stable.
+  */
+ static bool is_immutable_function(char *fname)
+ {
+ /*
+  * Query to know if the function is IMMUTABLE
+  */
+ #define IS_STABLE_FUNCTION_QUERY "SELECT count(*) FROM pg_catalog.pg_proc AS p WHERE p.proname = '%s' AND p.provolatile = 'i'"
+ 	bool result;
+ 	static POOL_RELCACHE *relcache;
+ 	POOL_CONNECTION_POOL *backend;
+ 
+ 	backend = pool_get_session_context()->backend;
+ 
+ 	if (!relcache)
+ 	{
+ 		relcache = pool_create_relcache(32, IS_STABLE_FUNCTION_QUERY,
+ 										int_register_func, int_unregister_func,
+ 										false);
+ 		if (relcache == NULL)
+ 		{
+ 			pool_error("is_immutable_function: pool_create_relcache error");
+ 			return false;
+ 		}
+ 		pool_debug("is_immutable_function: relcache created");
+ 	}
+ 
+ 	result = pool_search_relcache(relcache, backend, fname)==0?0:1;
+ 	pool_debug("is_immutable_function: search result:%d", result);
+ 	return result;
+ }
Index: pool_select_walker.h
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_select_walker.h,v
retrieving revision 1.4
diff -c -r1.4 pool_select_walker.h
*** pool_select_walker.h	6 Sep 2010 05:03:21 -0000	1.4
--- pool_select_walker.h	28 Jun 2011 10:27:04 -0000
***************
*** 30,35 ****
--- 30,36 ----
  #include "parser/nodes.h"
  
  extern bool pool_has_function_call(Node *node);
+ extern bool pool_has_non_immutable_function_call(Node *node);
  extern bool pool_has_system_catalog(Node *node);
  extern bool pool_has_temp_table(Node *node);
  extern bool pool_has_pgpool_regclass(void);
Index: parser/Makefile.in
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/parser/Makefile.in,v
retrieving revision 1.20
diff -c -r1.20 Makefile.in
*** parser/Makefile.in	14 Dec 2010 09:21:08 -0000	1.20
--- parser/Makefile.in	28 Jun 2011 10:27:05 -0000
***************
*** 117,122 ****
--- 117,125 ----
  LN_S = @LN_S@
  LTLIBOBJS = @LTLIBOBJS@
  MAKEINFO = @MAKEINFO@
+ MEMCACHED_INCLUDE_OPT = @MEMCACHED_INCLUDE_OPT@
+ MEMCACHED_LINK_OPT = @MEMCACHED_LINK_OPT@
+ MEMCACHED_RPATH_OPT = @MEMCACHED_RPATH_OPT@
  MKDIR_P = @MKDIR_P@
  NM = @NM@
  NMEDIT = @NMEDIT@
Index: pcp/Makefile.in
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pcp/Makefile.in,v
retrieving revision 1.21
diff -c -r1.21 Makefile.in
*** pcp/Makefile.in	26 Apr 2011 00:44:36 -0000	1.21
--- pcp/Makefile.in	28 Jun 2011 10:27:05 -0000
***************
*** 174,179 ****
--- 174,182 ----
  LN_S = @LN_S@
  LTLIBOBJS = @LTLIBOBJS@
  MAKEINFO = @MAKEINFO@
+ MEMCACHED_INCLUDE_OPT = @MEMCACHED_INCLUDE_OPT@
+ MEMCACHED_LINK_OPT = @MEMCACHED_LINK_OPT@
+ MEMCACHED_RPATH_OPT = @MEMCACHED_RPATH_OPT@
  MKDIR_P = @MKDIR_P@
  NM = @NM@
  NMEDIT = @NMEDIT@
_______________________________________________
Pgpool-hackers mailing list
[email protected]
http://pgfoundry.org/mailman/listinfo/pgpool-hackers

Reply via email to