summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/components
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2012-05-28 04:39:28 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2012-05-28 04:39:28 +0000
commit4a28afdf7a6b193942f180862d443a7d818c5789 (patch)
treedd1afbf7757a075f768af1b4e588e5dabc2a5f71 /sca-cpp/trunk/components
parentf278315081b24b59bf73e9613e552e3519200a71 (diff)
Database support optimizations. Use PgBouncer to pool connections. Track and manage WAL archives to optimize space and speed up database replication setup.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1343139 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/components')
-rw-r--r--sca-cpp/trunk/components/sqldb/Makefile.am6
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql2
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-archive59
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-backup38
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-clean-archive58
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-conf60
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-restore30
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-standby-conf66
-rw-r--r--sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp8
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-start5
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-stop7
-rw-r--r--sca-cpp/trunk/components/sqldb/pgsql-test.cpp4
-rw-r--r--sca-cpp/trunk/components/sqldb/pgsql.hpp103
-rw-r--r--sca-cpp/trunk/components/sqldb/sqldb.componentType2
-rw-r--r--sca-cpp/trunk/components/sqldb/sqldb.composite2
15 files changed, 348 insertions, 102 deletions
diff --git a/sca-cpp/trunk/components/sqldb/Makefile.am b/sca-cpp/trunk/components/sqldb/Makefile.am
index 0443de07d9..9ce5f26713 100644
--- a/sca-cpp/trunk/components/sqldb/Makefile.am
+++ b/sca-cpp/trunk/components/sqldb/Makefile.am
@@ -22,12 +22,14 @@ INCLUDES = -I${PGSQL_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/components/sqldb
-dist_comp_SCRIPTS = pgsql-conf pgsql-log-conf pgsql-start pgsql-stop pgsql pgsql-standby-conf pgsql-backup
+dist_comp_SCRIPTS = pgsql-conf pgsql-log-conf pgsql-start pgsql-stop pgsql pgsql-standby-conf pgsql-archive pgsql-backup pgsql-restore pgsql-clean-archive
compdir=$(prefix)/components/sqldb
-comp_DATA = pgsql.prefix
+comp_DATA = pgsql.prefix pgbouncer.prefix
pgsql.prefix: $(top_builddir)/config.status
echo ${PGSQL_PREFIX} >pgsql.prefix
+pgbouncer.prefix: $(top_builddir)/config.status
+ echo ${PGBOUNCER_PREFIX} >pgbouncer.prefix
EXTRA_DIST = sqldb.composite sqldb.componentType
diff --git a/sca-cpp/trunk/components/sqldb/pgsql b/sca-cpp/trunk/components/sqldb/pgsql
index 8079fde7b1..8a60068ab7 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql
+++ b/sca-cpp/trunk/components/sqldb/pgsql
@@ -23,7 +23,7 @@ pgsql_prefix=`cat $here/pgsql.prefix`
if [ "$2" = "" ]; then
host="localhost"
- port="5432"
+ port="6432"
cmd="$1"
else
host="$1"
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-archive b/sca-cpp/trunk/components/sqldb/pgsql-archive
new file mode 100755
index 0000000000..128e6eb539
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/pgsql-archive
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# PostgreSQL archive command
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+host=$2
+port=$3
+walp=$4
+walf=$5
+
+# Copy WAL to archive directory
+if [ ! -f $root/sqldb/archive/$walf ]; then
+ cp $walp $root/sqldb/archive/$walf
+ rc=$?
+ if [ "$rc" != "0" ]; then
+ exit $rc
+ fi
+fi
+
+# Trigger a backup if we have 10 WAL files archived since the last backup
+lastbak=`ls $root/sqldb/archive | sort -r | grep "\.backup$" | head -1`
+if [ "$lastbak" = "" ]; then
+ exit 0
+fi
+wals=`ls $root/sqldb/archive | sort -r | grep -v "\.backup\.tar\.gz$"`
+
+w=0
+for f in $wals; do
+ if [ "$f" = "$lastbak" ]; then
+ break
+ fi
+ w=$((w+1))
+
+ if [ "$w" = "10" ]; then
+ nohup /bin/sh -c "$here/pgsql-backup $root $host $port" 1>/dev/null 2>/dev/null &
+ break
+ fi
+done
+
+exit 0
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-backup b/sca-cpp/trunk/components/sqldb/pgsql-backup
index c0b1c4b2aa..ff660ad20d 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql-backup
+++ b/sca-cpp/trunk/components/sqldb/pgsql-backup
@@ -23,7 +23,7 @@ root=`echo "import os; print os.path.realpath('$1')" | python`
if [ "$2" = "" ]; then
host="localhost"
- port="5432"
+ port="6432"
else
host="$2"
port="$3"
@@ -40,12 +40,40 @@ fi
mkdir -p $root/sqldb
echo $pgsql_log >$root/sqldb/logger
-$pgsql_prefix/bin/psql -h $host -p $port -c "SELECT pg_start_backup('backup', true)" db 2>&1 | sh $root/sqldb/logger
+mkdir -p $root/sqldb/backup
+mkdir -p $root/sqldb/archive
-echo "Content-type: application/x-compressed"
-echo
+# Make sure that only one backup is in progress at a time
+if [ -f $root/sqldb/backup/inprogress ]; then
+ exit 0
+fi
+touch $root/sqldb/backup/inprogress
+
+# Backup
+stamp=`date +%Y%m%d%H%M%S`
+$pgsql_prefix/bin/psql -h $host -p $port -c "SELECT pg_start_backup('$stamp', true)" db 2>&1 | sh $root/sqldb/logger
-tar -C $root/sqldb -cz data
+uname=`uname -s`
+if [ $uname = "Darwin" ]; then
+ tar=gnutar
+else
+ tar=tar
+fi
+$tar -C $root/sqldb --exclude data/postmaster.pid --exclude data/postmaster.opts --exclude data/pg_xlog --ignore-failed-read -czf $root/sqldb/backup/$stamp.backup.tar.gz data
+rc=$?
+if [ "$rc" = "0" ]; then
+ mv $root/sqldb/backup/$stamp.backup.tar.gz $root/sqldb/archive/$stamp.backup.tar.gz
+fi
$pgsql_prefix/bin/psql -h $host -p $port -c "SELECT pg_stop_backup()" db 2>&1 | sh $root/sqldb/logger
+if [ "$rc" != "0" ]; then
+ rm -f $root/sqldb/backup/inprogress
+ exit $rc
+fi
+
+# Clean obsolete backup and WAL files
+$here/pgsql-clean-archive $root
+
+rm -f $root/sqldb/backup/inprogress
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-clean-archive b/sca-cpp/trunk/components/sqldb/pgsql-clean-archive
new file mode 100755
index 0000000000..0e52fade89
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/pgsql-clean-archive
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Cleanup database archive.
+# Keep the last two backups and corresponding WAL files.
+
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+baks=`ls $root/sqldb/archive | sort -r | grep "\.backup$" | head -2`
+wals=`ls $root/sqldb/archive | sort -r | grep -v "\.backup\.tar\.gz$"`
+tars=`ls $root/sqldb/archive | sort -r | grep "\.backup\.tar\.gz$"`
+
+for f in $baks; do
+ if [ "$lastbak" = "" ]; then
+ lastbak=$f
+ else
+ prevbak=$f
+ fi
+done
+
+w=0
+for f in $wals; do
+ if [ "$w" = "2" ]; then
+ rm $root/sqldb/archive/$f
+ fi
+ if [ "$w" = "1" ]; then
+ w=2
+ fi
+ if [ "$f" = "$prevbak" ]; then
+ w=1
+ fi
+done
+
+t=0
+for f in $tars; do
+ if [ "$t" = "2" ]; then
+ rm $root/sqldb/archive/$f
+ fi
+ t=$((t+1))
+done
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-conf b/sca-cpp/trunk/components/sqldb/pgsql-conf
index 58d38412ca..482048a295 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql-conf
+++ b/sca-cpp/trunk/components/sqldb/pgsql-conf
@@ -33,11 +33,15 @@ else
fi
port=`$here/../../modules/http/httpd-addr port $addr`
fi
+bport=`expr $port + 1000`
pgsql_prefix=`cat $here/pgsql.prefix`
+pgbouncer_prefix=`cat $here/pgbouncer.prefix`
+
mkdir -p $root/sqldb/data
chmod 700 $root/sqldb/data
mkdir -p $root/sqldb/archive
+mkdir -p $root/sqldb/backup
if [ -f "$root/sqldb/log.conf" ]; then
pgsql_log=`cat $root/sqldb/log.conf`
@@ -48,6 +52,7 @@ fi
mkdir -p $root/sqldb
echo $pgsql_log >$root/sqldb/logger
+# Initialize PostgreSQL
if [ ! -f $root/sqldb/data/postgresql.conf ]; then
$pgsql_prefix/bin/pg_ctl init -D $root/sqldb/data 2>&1 | sh $root/sqldb/logger
cp $root/sqldb/data/postgresql.conf $root/sqldb/data/postgresql-init.conf
@@ -77,7 +82,7 @@ port = $port
# Setup archival
archive_mode = on
-archive_command = 'cp %p $root/sqldb/archive/%f'
+archive_command = '$here/pgsql-archive $root localhost $bport %p %f'
# Setup hot standby with streaming replication
wal_level = hot_standby
@@ -97,7 +102,7 @@ host replication all samenet trust
EOF
-# Create the db
+# Create the db if it's not created yet
nohup /bin/sh -c "($pgsql_prefix/bin/pg_ctl start -W -D $root/sqldb/data 2>&1 | sh $root/sqldb/logger)" 1>/dev/null 2>/dev/null &
sti=0
while [ $sti -ne 30 ]; do
@@ -110,15 +115,22 @@ while [ $sti -ne 30 ]; do
done
$pgsql_prefix/bin/createdb -h localhost -p $port db 2>&1 | sh $root/sqldb/logger
+
+# Backup the db if there's no backup for it yet
+baks=`ls $root/sqldb/archive | sort -r | grep "\.backup\.tar\.gz$"`
+if [ "$baks" = "" ]; then
+ $here/pgsql-backup $root localhost $port
+fi
+
$pgsql_prefix/bin/pg_ctl stop -w -D $root/sqldb/data 2>&1 | sh $root/sqldb/logger
-# Generate database backup script
+# Generate database restore script
mkdir -p $root/sqldb/scripts
-cat >$root/sqldb/scripts/backup <<EOF
+cat >$root/sqldb/scripts/restore <<EOF
#!/bin/sh
-$here/pgsql-backup $root localhost $port
+$here/pgsql-restore $root
EOF
-chmod 700 $root/sqldb/scripts/backup
+chmod 700 $root/sqldb/scripts/restore
# Configure HTTPD to serve backup and archive files
if [ -f "$root/conf/httpd.conf" ]; then
@@ -126,10 +138,44 @@ if [ -f "$root/conf/httpd.conf" ]; then
# Generated by: pgsql-conf $*
# Serve PostgreSQL backup and WAL archive files
-ScriptAlias /pgsql-backup "$root/sqldb/scripts/backup"
+ScriptAlias /pgsql-restore "$root/sqldb/scripts/restore"
Alias /pgsql-archive "$root/sqldb/archive"
EOF
fi
+# Configure PgBouncer
+mkdir -p $root/logs
+id=`id -un`
+cat >$root/sqldb/data/pgbouncer.conf <<EOF
+
+[databases]
+db = host=localhost dbname=db
+
+[pgbouncer]
+pool_mode = session
+listen_port = $bport
+listen_addr = $ip
+auth_type = trust
+auth_file=$root/sqldb/data/pgbouncer-auth.conf
+logfile = $root/logs/pgbouncer
+pidfile = $root/logs/pgbouncer.pid
+max_client_conn = 1000
+pool_mode = transaction
+server_reset_query =
+default_pool_size = 500
+min_pool_size = 5
+reserve_pool_size = 50
+log_connections = 0
+log_disconnections = 0
+stats_period = 3600
+admin_users = $id
+
+EOF
+
+cat >$root/sqldb/data/pgbouncer-auth.conf <<EOF
+"$id" "password"
+
+EOF
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-restore b/sca-cpp/trunk/components/sqldb/pgsql-restore
new file mode 100755
index 0000000000..e91eba2a6b
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/pgsql-restore
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Backup postgresql data directory
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+tar=`ls $root/sqldb/archive | sort -r | grep "\.backup\.tar\.gz$" | head -1`
+
+echo "Content-type: application/x-compressed"
+echo ""
+
+cat $root/sqldb/archive/$tar
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-standby-conf b/sca-cpp/trunk/components/sqldb/pgsql-standby-conf
index bc0d4e9981..77d1dfa8e2 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql-standby-conf
+++ b/sca-cpp/trunk/components/sqldb/pgsql-standby-conf
@@ -34,6 +34,7 @@ else
fi
port=`$here/../../modules/http/httpd-addr port $addr`
fi
+bport=`expr $port + 1000`
# Master server address
if [ "$3" = "" ]; then
@@ -47,6 +48,12 @@ else
fi
pgsql_prefix=`cat $here/pgsql.prefix`
+pgbouncer_prefix=`cat $here/pgbouncer.prefix`
+
+mkdir -p $root/sqldb/data
+chmod 700 $root/sqldb/data
+mkdir -p $root/sqldb/archive
+mkdir -p $root/sqldb/backup
if [ -f "$root/sqldb/log.conf" ]; then
pgsql_log=`cat $root/sqldb/log.conf`
@@ -57,14 +64,15 @@ fi
mkdir -p $root/sqldb
echo $pgsql_log >$root/sqldb/logger
-mkdir -p $root/sqldb/data
-chmod 700 $root/sqldb/data
-mkdir -p $root/sqldb/archive
-
# Initialize from a backup of the master
if [ ! -f $root/sqldb/data/postgresql.conf ]; then
- (curl -L -# http://$mhost:$mhttpport/pgsql-backup | tar -C $root/sqldb -xz) 2>&1 | grep -v "100.0%" | sh $root/sqldb/logger
- rm -rf $root/sqldb/data/postmaster.pid $root/sqldb/data/pg_xlog
+ uname=`uname -s`
+ if [ $uname = "Darwin" ]; then
+ tar=gnutar
+ else
+ tar=tar
+ fi
+ (curl -L -# http://$mhost:$mhttpport/pgsql-restore | $tar -C $root/sqldb -xz) 2>&1 | grep -v "100.0%" | sh $root/sqldb/logger
mkdir -p $root/sqldb/data/pg_xlog/archive_status
chmod 700 $root/sqldb/data/pg_xlog/archive_status
fi
@@ -92,7 +100,7 @@ port = $port
# Setup archival
archive_mode = on
-archive_command = 'cp %p $root/sqldb/archive/%f'
+archive_command = '$here/pgsql-archive $root localhost $bport %p %f'
# Setup hot standby with streaming replication
wal_level = hot_standby
@@ -119,13 +127,13 @@ restore_command = 'curl -L -# http://$mhost:$mhttpport/pgsql-archive/%f -o "%p"
EOF
-# Generate database backup script
+# Generate database restore script
mkdir -p $root/sqldb/scripts
-cat >$root/sqldb/scripts/backup <<EOF
+cat >$root/sqldb/scripts/restore <<EOF
#!/bin/sh
-$here/pgsql-backup $root localhost $port
+$here/pgsql-restore $root
EOF
-chmod 700 $root/sqldb/scripts/backup
+chmod 700 $root/sqldb/scripts/restore
# Configure HTTPD to serve backup and archive files
if [ -f "$root/conf/httpd.conf" ]; then
@@ -133,10 +141,44 @@ if [ -f "$root/conf/httpd.conf" ]; then
# Generated by: pgsql-standby-conf $*
# Serve PostgreSQL backup and WAL archive files
-ScriptAlias /pgsql-backup "$root/sqldb/scripts/backup"
+ScriptAlias /pgsql-restore "$root/sqldb/scripts/restore"
Alias /pgsql-archive "$root/sqldb/archive"
EOF
fi
+# Configure PgBouncer
+mkdir -p $root/logs
+id=`id -un`
+cat >$root/sqldb/data/pgbouncer.conf <<EOF
+
+[databases]
+db = host=localhost dbname=db
+
+[pgbouncer]
+pool_mode = session
+listen_port = $bport
+listen_addr = $ip
+auth_type = trust
+auth_file=$root/sqldb/data/pgbouncer-auth.conf
+logfile = $root/logs/pgbouncer
+pidfile = $root/logs/pgbouncer.pid
+max_client_conn = 1000
+pool_mode = transaction
+server_reset_query =
+default_pool_size = 500
+min_pool_size = 5
+reserve_pool_size = 50
+log_connections = 0
+log_disconnections = 0
+stats_period = 3600
+admin_users = $id
+
+EOF
+
+cat >$root/sqldb/data/pgbouncer-auth.conf <<EOF
+"$id" "password"
+
+EOF
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp b/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp
index 44f0a4a9e6..2cd25f874a 100644
--- a/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp
+++ b/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp
@@ -33,8 +33,8 @@ namespace tuscany {
namespace pgsql {
bool testPGSql() {
- PGSql wpg("host=localhost port=5432 dbname=db", "test");
- PGSql rpg("host=localhost port=5433 dbname=db", "test");
+ PGSql wpg("host=localhost port=6432 dbname=db", "test");
+ PGSql rpg("host=localhost port=6433 dbname=db", "test");
const value k = mklist<value>("a");
assert(hasContent(post(k, string("AAA"), wpg)));
@@ -63,8 +63,8 @@ struct getLoop {
bool testGetPerf() {
const value k = mklist<value>("c");
- PGSql wpg("host=localhost port=5432 dbname=db", "test");
- PGSql rpg("host=localhost port=5433 dbname=db", "test");
+ PGSql wpg("host=localhost port=6432 dbname=db", "test");
+ PGSql rpg("host=localhost port=6433 dbname=db", "test");
assert(hasContent(post(k, string("CCC"), wpg)));
sleep(1);
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-start b/sca-cpp/trunk/components/sqldb/pgsql-start
index 2955bec991..6b388d29f0 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql-start
+++ b/sca-cpp/trunk/components/sqldb/pgsql-start
@@ -22,6 +22,7 @@ here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $h
root=`echo "import os; print os.path.realpath('$1')" | python`
pgsql_prefix=`cat $here/pgsql.prefix`
+pgbouncer_prefix=`cat $here/pgbouncer.prefix`
if [ -f "$root/sqldb/log.conf" ]; then
pgsql_log=`cat $root/sqldb/log.conf`
@@ -43,3 +44,7 @@ while [ $sti -ne 30 ]; do
sti=$((sti+1))
done
+# Start PgBouncer
+mkdir -p $root/logs
+$pgbouncer_prefix/bin/pgbouncer -q -d $root/sqldb/data/pgbouncer.conf
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-stop b/sca-cpp/trunk/components/sqldb/pgsql-stop
index fbb9997961..16b6506838 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql-stop
+++ b/sca-cpp/trunk/components/sqldb/pgsql-stop
@@ -22,6 +22,7 @@ here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $h
root=`echo "import os; print os.path.realpath('$1')" | python`
pgsql_prefix=`cat $here/pgsql.prefix`
+pgbouncer_prefix=`cat $here/pgbouncer.prefix`
if [ -f "$root/sqldb/log.conf" ]; then
pgsql_log=`cat $root/sqldb/log.conf`
@@ -32,5 +33,11 @@ fi
mkdir -p $root/sqldb
echo $pgsql_log >$root/sqldb/logger
+pgb="$pgbouncer_prefix/bin/pgbouncer -q -d $root/sqldb/data/pgbouncer.conf"
+k=`ps -ef | grep -v grep | grep "${pgb}" | awk '{ print $2 }'`
+if [ "$k" != "" ]; then
+ kill $k
+fi
+
$pgsql_prefix/bin/pg_ctl stop -w -D $root/sqldb/data 2>&1 | sh $root/sqldb/logger
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-test.cpp b/sca-cpp/trunk/components/sqldb/pgsql-test.cpp
index 1019667285..d10ab5f4c2 100644
--- a/sca-cpp/trunk/components/sqldb/pgsql-test.cpp
+++ b/sca-cpp/trunk/components/sqldb/pgsql-test.cpp
@@ -33,7 +33,7 @@ namespace tuscany {
namespace pgsql {
bool testPGSql() {
- PGSql pg("host=localhost port=5432 dbname=db", "test");
+ PGSql pg("host=localhost port=6432 dbname=db", "test");
const value k = mklist<value>("a");
assert(hasContent(post(k, string("AAA"), pg)));
@@ -59,7 +59,7 @@ struct getLoop {
bool testGetPerf() {
const value k = mklist<value>("c");
- PGSql pg("host=localhost port=5432 dbname=db", "test");
+ PGSql pg("host=localhost port=6432 dbname=db", "test");
assert(hasContent(post(k, string("CCC"), pg)));
const lambda<bool()> gl = getLoop(k, pg);
diff --git a/sca-cpp/trunk/components/sqldb/pgsql.hpp b/sca-cpp/trunk/components/sqldb/pgsql.hpp
index 74d638f370..d38af54c97 100644
--- a/sca-cpp/trunk/components/sqldb/pgsql.hpp
+++ b/sca-cpp/trunk/components/sqldb/pgsql.hpp
@@ -61,12 +61,30 @@ public:
PGSql(const string& conninfo, const string& table) : owner(true), conn(NULL), conninfo(conninfo), table(table) {
debug(conninfo, "pgsql::pgsql::conninfo");
debug(table, "pgsql::pgsql::table");
+
+ // Connect to the database
conn = PQconnectdb(c_str(conninfo));
if (PQstatus(conn) != CONNECTION_OK) {
mkfailure<bool>(string("Couldn't connect to postgresql database: ") + PQerrorMessage(conn));
return;
}
- setup(true);
+
+ // Find the name of the first column in the target table
+ // Assume that's the key we need to use
+ string ks = string("select a.attname from pg_attribute a, pg_class c where a.attrelid = c.relfilenode and c.relname = '") + table + string("' and a.attnum in (1, 2) order by a.attnum;");
+ PGresult* kr = PQexec(conn, c_str(ks));
+ if (PQresultStatus(kr) != PGRES_TUPLES_OK) {
+ mkfailure<bool>(string("Couldn't execute postgresql column select statement: ") + pgfailure(kr, conn));
+ return;
+ }
+ if (PQntuples(kr) != 2) {
+ PQclear(kr);
+ mkfailure<bool>(string("Couldn't find postgresql table key and value column names"));
+ return;
+ }
+ kname = PQgetvalue(kr, 0, 0);
+ vname = PQgetvalue(kr, 1, 0);
+ PQclear(kr);
}
PGSql(const PGSql& c) : owner(false), conn(c.conn), conninfo(c.conninfo), table(c.table) {
@@ -86,78 +104,29 @@ private:
bool owner;
PGconn *conn;
string conninfo;
- string table;
+ const string table;
+ string kname;
+ string vname;
friend const failable<bool> setup(const PGSql& pgsql);
friend const failable<bool> post(const value& key, const value& val, const PGSql& pgsql);
friend const failable<bool> put(const value& key, const value& val, const PGSql& pgsql);
friend const failable<value> get(const value& key, const PGSql& pgsql);
friend const failable<bool> del(const value& key, const PGSql& pgsql);
-
- /**
- * Setup the database connection.
- */
- const failable<bool> setup(const bool init) const {
-
- // Check the status of the connection and reconnect if necessary
- if (!init) {
- if (PQstatus(conn) == CONNECTION_OK)
- return true;
- debug("pgsql::setup::reset");
- PQreset(conn);
- if (PQstatus(conn) != CONNECTION_OK)
- return mkfailure<bool>(string("Couldn't reconnect to postgresql database: ") + PQerrorMessage(conn));
- }
- debug("pgsql::setup::init");
-
- // Find the name of the first column in the target table
- // Assume that's the key we need to use
- string ks = string("select a.attname from pg_attribute a, pg_class c where a.attrelid = c.relfilenode and c.relname = '") + table + string("' and a.attnum in (1, 2) order by a.attnum;");
- PGresult* kr = PQexec(conn, c_str(ks));
- if (PQresultStatus(kr) != PGRES_TUPLES_OK)
- return mkfailure<bool>(string("Couldn't execute postgresql column select statement: ") + pgfailure(kr, conn));
- if (PQntuples(kr) != 2) {
- PQclear(kr);
- return mkfailure<bool>(string("Couldn't find postgresql table key and value column names"));
- }
- const string kname = PQgetvalue(kr, 0, 0);
- const string vname = PQgetvalue(kr, 1, 0);
- PQclear(kr);
-
- // Prepare the post, put, get and delete statements
- {
- PGresult* r = PQprepare(conn, "post", c_str(string("insert into ") + table + string(" values($1, $2);")), 2, NULL);
- if (PQresultStatus(r) != PGRES_COMMAND_OK)
- return mkfailure<bool>(string("Couldn't prepare post postgresql SQL statement: ") + pgfailure(r, conn));
- PQclear(r);
- }
- {
- PGresult* r = PQprepare(conn, "put", c_str(string("update ") + table + string(" set ") + vname + string(" = $2 where ") + kname + string(" = $1;")), 2, NULL);
- if (PQresultStatus(r) != PGRES_COMMAND_OK)
- return mkfailure<bool>(string("Couldn't prepare put postgresql SQL statement: ") + pgfailure(r, conn));
- PQclear(r);
- }
- {
- PGresult* r = PQprepare(conn, "get", c_str(string("select * from ") + table + string(" where ") + kname + string(" = $1;")), 1, NULL);
- if (PQresultStatus(r) != PGRES_COMMAND_OK)
- return mkfailure<bool>(string("Couldn't prepare get postgresql SQL statement: ") + pgfailure(r, conn));
- PQclear(r);
- }
- {
- PGresult* r = PQprepare(conn, "delete", c_str(string("delete from ") + table + string(" where ") + kname + string(" = $1;")), 1, NULL);
- if (PQresultStatus(r) != PGRES_COMMAND_OK)
- return mkfailure<bool>(string("Couldn't prepare delete postgresql SQL statement: ") + pgfailure(r, conn));
- PQclear(r);
- }
- return true;
- }
};
/**
* Setup the database connection if necessary.
*/
const failable<bool> setup(const PGSql& pgsql) {
- return pgsql.setup(false);
+ debug("pgsql::setup");
+ if (PQstatus(pgsql.conn) == CONNECTION_OK)
+ return true;
+ debug("pgsql::setup::reset");
+ PQreset(pgsql.conn);
+ if (PQstatus(pgsql.conn) != CONNECTION_OK)
+ return mkfailure<bool>(string("Couldn't reconnect to postgresql database: ") + PQerrorMessage(pgsql.conn));
+ return true;
}
/**
@@ -173,7 +142,7 @@ const failable<bool> post(const value& key, const value& val, const PGSql& pgsql
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
const char* params[2] = { c_str(ks), c_str(vs) };
- PGresult* r = PQexecPrepared(pgsql.conn, "post", 2, params, NULL, NULL, 0);
+ PGresult* r = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
PQclear(r);
@@ -195,7 +164,7 @@ const failable<bool> put(const value& key, const value& val, const PGSql& pgsql)
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
const char* params[2] = { c_str(ks), c_str(vs) };
- PGresult* r = PQexecPrepared(pgsql.conn, "put", 2, params, NULL, NULL, 0);
+ PGresult* r = PQexecParams(pgsql.conn, c_str(string("update ") + pgsql.table + string(" set ") + pgsql.vname + string(" = $2 where ") + pgsql.kname + string(" = $1;")), 2, NULL, params, NULL, NULL, 0);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Couldn't execute update postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
const string t = PQcmdTuples(r);
@@ -206,7 +175,7 @@ const failable<bool> put(const value& key, const value& val, const PGSql& pgsql)
}
PQclear(r);
- PGresult* pr = PQexecPrepared(pgsql.conn, "post", 2, params, NULL, NULL, 0);
+ PGresult* pr = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0);
if (PQresultStatus(pr) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(pr, pgsql.conn));
PQclear(pr);
@@ -226,14 +195,14 @@ const failable<value> get(const value& key, const PGSql& pgsql) {
const string ks(scheme::writeValue(key));
const char* params[1] = { c_str(ks) };
- PGresult* r = PQexecPrepared(pgsql.conn, "get", 1, params, NULL, NULL, 0);
+ PGresult* r = PQexecParams(pgsql.conn, c_str(string("select * from ") + pgsql.table + string(" where ") + pgsql.kname + string(" = $1;")), 1, NULL, params, NULL, NULL, 0);
if (PQresultStatus(r) != PGRES_TUPLES_OK)
return mkfailure<value>(string("Couldn't execute select postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
if (PQntuples(r) < 1) {
PQclear(r);
ostringstream os;
os << "Couldn't get postgresql entry: " << key;
- return mkfailure<value>(str(os));
+ return mkfailure<value>(str(os), 404, false);
}
const char* data = PQgetvalue(r, 0, 1);
const value val(scheme::readValue(string(data)));
@@ -254,7 +223,7 @@ const failable<bool> del(const value& key, const PGSql& pgsql) {
const string ks(scheme::writeValue(key));
const char* params[1] = { c_str(ks) };
- PGresult* r = PQexecPrepared(pgsql.conn, "delete", 1, params, NULL, NULL, 0);
+ PGresult* r = PQexecParams(pgsql.conn, c_str(string("delete from ") + pgsql.table + string(" where ") + pgsql.kname + string(" = $1;")), 1, NULL, params, NULL, NULL, 0);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Couldn't execute delete postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
PQclear(r);
diff --git a/sca-cpp/trunk/components/sqldb/sqldb.componentType b/sca-cpp/trunk/components/sqldb/sqldb.componentType
index 5aa6d8e30f..bd024213bd 100644
--- a/sca-cpp/trunk/components/sqldb/sqldb.componentType
+++ b/sca-cpp/trunk/components/sqldb/sqldb.componentType
@@ -23,7 +23,7 @@
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="sqldb"/>
- <property name="conninfo" type="xsd:string">host=localhost port=5432 dbname=db</property>
+ <property name="conninfo" type="xsd:string">host=localhost port=6432 dbname=db</property>
<property name="table" type=xsd:string"/>
</composite>
diff --git a/sca-cpp/trunk/components/sqldb/sqldb.composite b/sca-cpp/trunk/components/sqldb/sqldb.composite
index 19bafd8eca..9e102893b5 100644
--- a/sca-cpp/trunk/components/sqldb/sqldb.composite
+++ b/sca-cpp/trunk/components/sqldb/sqldb.composite
@@ -23,7 +23,7 @@
<component name="sqldb">
<implementation.cpp path="." library="libsqldb"/>
- <property name="conninfo">host=localhost port=5432 dbname=db</property>
+ <property name="conninfo">host=localhost port=6432 dbname=db</property>
<property name="table">test</property>
<service name="sqldb">
<binding.http uri="sqldb"/>