> 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