summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/components/sqldb
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/components/sqldb')
-rw-r--r--sca-cpp/trunk/components/sqldb/Makefile.am11
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql12
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-backup41
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-conf105
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-standby-conf122
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-standby-testbin0 -> 526293 bytes
-rw-r--r--sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp88
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-start12
-rwxr-xr-xsca-cpp/trunk/components/sqldb/pgsql-stop3
-rw-r--r--sca-cpp/trunk/components/sqldb/pgsql-test.cpp4
-rw-r--r--sca-cpp/trunk/components/sqldb/pgsql.hpp79
-rwxr-xr-xsca-cpp/trunk/components/sqldb/server-test9
-rwxr-xr-xsca-cpp/trunk/components/sqldb/sqldb-test1
-rw-r--r--sca-cpp/trunk/components/sqldb/sqldb.composite2
-rw-r--r--sca-cpp/trunk/components/sqldb/sqldb.cpp13
-rwxr-xr-xsca-cpp/trunk/components/sqldb/standby-test39
16 files changed, 479 insertions, 62 deletions
diff --git a/sca-cpp/trunk/components/sqldb/Makefile.am b/sca-cpp/trunk/components/sqldb/Makefile.am
index e5c03f5190..7ed24e712c 100644
--- a/sca-cpp/trunk/components/sqldb/Makefile.am
+++ b/sca-cpp/trunk/components/sqldb/Makefile.am
@@ -22,7 +22,7 @@ INCLUDES = -I${PGSQL_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/components/sqldb
-dist_comp_SCRIPTS = pgsql-start pgsql-stop pgsql
+dist_comp_SCRIPTS = pgsql-conf pgsql-start pgsql-stop pgsql pgsql-standby-conf
compdir=$(prefix)/components/sqldb
comp_DATA = pgsql.prefix
@@ -42,11 +42,14 @@ libsqldb.so:
pgsql_test_SOURCES = pgsql-test.cpp
pgsql_test_LDFLAGS = -L${PGSQL_LIB} -R${PGSQL_LIB} -lpq
+pgsql_standby_test_SOURCES = pgsql-standby-test.cpp
+pgsql_standby_test_LDFLAGS = -L${PGSQL_LIB} -R${PGSQL_LIB} -lpq
+
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
-dist_noinst_SCRIPTS = sqldb-test server-test
-noinst_PROGRAMS = pgsql-test client-test
-TESTS = sqldb-test server-test
+dist_noinst_SCRIPTS = sqldb-test standby-test server-test
+noinst_PROGRAMS = pgsql-test pgsql-standby-test client-test
+TESTS = sqldb-test standby-test server-test
endif
diff --git a/sca-cpp/trunk/components/sqldb/pgsql b/sca-cpp/trunk/components/sqldb/pgsql
index 3cd1904e32..dab30e642b 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql
+++ b/sca-cpp/trunk/components/sqldb/pgsql
@@ -21,5 +21,15 @@
here=`readlink -f $0`; here=`dirname $here`
pgsql_prefix=`cat $here/pgsql.prefix`
-$pgsql_prefix/bin/psql -c "$1" db
+if [ "$2" = "" ]; then
+ host="localhost"
+ port="5432"
+ cmd="$1"
+else
+ host="$1"
+ port="$2"
+ cmd="$3"
+fi
+
+$pgsql_prefix/bin/psql -h $host -p $port -c "$cmd" db
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-backup b/sca-cpp/trunk/components/sqldb/pgsql-backup
new file mode 100755
index 0000000000..fad59236bf
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/pgsql-backup
@@ -0,0 +1,41 @@
+#!/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=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+
+if [ "$2" = "" ]; then
+ host="localhost"
+ port="5432"
+else
+ host="$2"
+ port="$3"
+fi
+
+pgsql_prefix=`cat $here/pgsql.prefix`
+$pgsql_prefix/bin/psql -h $host -p $port -c "SELECT pg_start_backup('backup', true)" db 1>>$root/logs/postgresql 2>&1
+
+echo "Content-type: application/x-compressed"
+echo
+
+tar -C $root/sqldb -cz data
+
+$pgsql_prefix/bin/psql -h $host -p $port -c "SELECT pg_stop_backup()" db 1>>$root/logs/postgresql 2>&1
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-conf b/sca-cpp/trunk/components/sqldb/pgsql-conf
new file mode 100755
index 0000000000..f5cc2d23e3
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/pgsql-conf
@@ -0,0 +1,105 @@
+#!/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.
+
+# Configure a postgresql master server
+here=`readlink -f $0`; here=`dirname $here`
+mkdir -p $1
+root=`readlink -f $1`
+
+addr=$2
+if [ "$addr" = "" ]; then
+ ip="*"
+ port="5432"
+else
+ ip=`$here/../../modules/http/httpd-addr ip $addr`
+ if [ "$ip" = "" ]; then
+ ip="*"
+ fi
+ port=`$here/../../modules/http/httpd-addr port $addr`
+fi
+
+pgsql_prefix=`cat $here/pgsql.prefix`
+mkdir -p $root/sqldb/data
+chmod 700 $root/sqldb/data
+mkdir -p $root/sqldb/archive
+mkdir -p $root/logs
+if [ ! -f $root/sqldb/data/postgresql.conf ]; then
+ $pgsql_prefix/bin/pg_ctl init -D $root/sqldb/data 1>>$root/logs/postgresql 2>&1
+ cp $root/sqldb/data/postgresql.conf $root/sqldb/data/postgresql-init.conf
+ cp $root/sqldb/data/pg_hba.conf $root/sqldb/data/pg_hba-init.conf
+fi
+
+# Generate server configuration
+cp $root/sqldb/data/postgresql-init.conf $root/sqldb/data/postgresql.conf
+cat >>$root/sqldb/data/postgresql.conf <<EOF
+
+# Generated by: pgsql-conf $*
+
+# Listen
+listen_addresses = '$ip'
+port = $port
+
+# Setup archival
+archive_mode = on
+archive_command = 'cp %p $root/sqldb/archive/%f'
+
+# Setup hot standby with streaming replication
+wal_level = hot_standby
+max_wal_senders = 5
+wal_keep_segments = 32
+
+EOF
+
+# Generate client auth configuration
+cp $root/sqldb/data/pg_hba-init.conf $root/sqldb/data/pg_hba.conf
+cat >>$root/sqldb/data/pg_hba.conf <<EOF
+
+# Generated by: pgsql-conf $*
+# TYPE DATABASE USER CIDR-ADDRESS METHOD
+host all all samenet trust
+host replication all samenet trust
+
+EOF
+
+# Create the db
+$pgsql_prefix/bin/pg_ctl start -w -D $root/sqldb/data -l $root/logs/postgresql 1>>$root/logs/postgresql 2>&1
+$pgsql_prefix/bin/createdb -h localhost -p $port db 1>>$root/logs/postgresql 2>&1
+$pgsql_prefix/bin/pg_ctl stop -w -D $root/sqldb/data 1>>$root/logs/postgresql 2>&1
+
+# Generate database backup script
+mkdir -p $root/sqldb/scripts
+cat >$root/sqldb/scripts/backup <<EOF
+#!/bin/sh
+$here/pgsql-backup $root localhost $port
+EOF
+chmod 700 $root/sqldb/scripts/backup
+
+# Configure HTTPD to serve backup and archive files
+if [ -f "$root/conf/httpd.conf" ]; then
+ cat >>$root/conf/httpd.conf <<EOF
+# Generated by: pgsql-conf $*
+
+# Serve PostgreSQL backup and WAL archive files
+ScriptAlias /pgsql-backup "$root/sqldb/scripts/backup"
+Alias /pgsql-archive "$root/sqldb/archive"
+
+EOF
+
+fi
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-standby-conf b/sca-cpp/trunk/components/sqldb/pgsql-standby-conf
new file mode 100755
index 0000000000..3b4aa6dff5
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/pgsql-standby-conf
@@ -0,0 +1,122 @@
+#!/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.
+
+# Configure a postgresql hot standby server
+here=`readlink -f $0`; here=`dirname $here`
+mkdir -p $1
+root=`readlink -f $1`
+
+# Master server address
+if [ "$2" = "" ]; then
+ mhost="localhost"
+ mport="5432"
+ mhttpport="80"
+else
+ mhost="$2"
+ mport="$3"
+ mhttpport="$4"
+fi
+
+# Server address
+addr=$5
+if [ "$addr" = "" ]; then
+ ip="*"
+ port="5432"
+else
+ ip=`$here/../../modules/http/httpd-addr ip $addr`
+ if [ "$ip" = "" ]; then
+ ip="*"
+ fi
+ port=`$here/../../modules/http/httpd-addr port $addr`
+fi
+
+pgsql_prefix=`cat $here/pgsql.prefix`
+mkdir -p $root/sqldb/data
+chmod 700 $root/sqldb/data
+mkdir -p $root/sqldb/archive
+mkdir -p $root/logs
+
+# Initialize from a backup of the master
+if [ ! -f $root/sqldb/data/postgresql.conf ]; then
+ (wget http://$mhost:$mhttpport/pgsql-backup -O - | tar -C $root/sqldb -xz) 1>>$root/logs/postgresql 2>&1
+ rm -rf $root/sqldb/data/postmaster.pid $root/sqldb/data/pg_xlog
+ mkdir -p $root/sqldb/data/pg_xlog/archive_status
+ chmod 700 $root/sqldb/data/pg_xlog/archive_status
+fi
+
+# Generate server configuration
+cp $root/sqldb/data/postgresql-init.conf $root/sqldb/data/postgresql.conf
+cat >>$root/sqldb/data/postgresql.conf <<EOF
+
+# Generated by: standby-conf $*
+
+# Listen
+listen_addresses = '$ip'
+port = $port
+
+# Setup archival
+archive_mode = on
+archive_command = 'cp %p $root/sqldb/archive/%f'
+
+# Setup hot standby with streaming replication
+wal_level = hot_standby
+max_wal_senders = 5
+wal_keep_segments = 32
+
+# Enable hot standby
+hot_standby = on
+
+EOF
+
+# Generate recovery configuration
+cat >$root/sqldb/data/recovery.conf << EOF
+# Generated by: pgsql-slave-conf $*
+
+# Start in standby mode
+standby_mode = 'on'
+primary_conninfo = 'host=$mhost port=$mport'
+
+# Failover
+trigger_file = '$root/sqldb/failover'
+
+restore_command = 'wget http://$mhost:$mhttpport/pgsql-archive/%f -O "%p"'
+
+EOF
+
+# Generate database backup script
+mkdir -p $root/sqldb/scripts
+cat >$root/sqldb/scripts/backup <<EOF
+#!/bin/sh
+$here/pgsql-backup $root localhost $port
+EOF
+chmod 700 $root/sqldb/scripts/backup
+
+# Configure HTTPD to serve backup and archive files
+if [ -f "$root/conf/httpd.conf" ]; then
+ cat >>$root/conf/httpd.conf <<EOF
+# Generated by: pgsql-conf $*
+
+# Serve PostgreSQL backup and WAL archive files
+ScriptAlias /pgsql-backup "$root/sqldb/scripts/backup"
+Alias /pgsql-archive "$root/sqldb/archive"
+
+EOF
+
+fi
+
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-standby-test b/sca-cpp/trunk/components/sqldb/pgsql-standby-test
new file mode 100755
index 0000000000..bf6b643c50
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/pgsql-standby-test
Binary files differ
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp b/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp
new file mode 100644
index 0000000000..44f0a4a9e6
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * Test PostgreSQL hot standby support.
+ */
+
+#include <assert.h>
+#include "stream.hpp"
+#include "string.hpp"
+#include "perf.hpp"
+#include "pgsql.hpp"
+
+namespace tuscany {
+namespace pgsql {
+
+bool testPGSql() {
+ PGSql wpg("host=localhost port=5432 dbname=db", "test");
+ PGSql rpg("host=localhost port=5433 dbname=db", "test");
+ const value k = mklist<value>("a");
+
+ assert(hasContent(post(k, string("AAA"), wpg)));
+ sleep(1);
+ assert((get(k, rpg)) == value(string("AAA")));
+ assert(hasContent(put(k, string("aaa"), wpg)));
+ sleep(1);
+ assert((get(k, rpg)) == value(string("aaa")));
+ assert(hasContent(del(k, wpg)));
+ sleep(1);
+ assert(!hasContent(get(k, rpg)));
+
+ return true;
+}
+
+struct getLoop {
+ const value k;
+ PGSql& pg;
+ getLoop(const value& k, PGSql& pg) : k(k), pg(pg) {
+ }
+ const bool operator()() const {
+ assert((get(k, pg)) == value(string("CCC")));
+ return true;
+ }
+};
+
+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");
+ assert(hasContent(post(k, string("CCC"), wpg)));
+ sleep(1);
+
+ const lambda<bool()> gl = getLoop(k, rpg);
+ cout << "PGSql get test " << time(gl, 5, 200) << " ms" << endl;
+ return true;
+}
+
+}
+}
+
+int main() {
+ tuscany::cout << "Testing..." << tuscany::endl;
+
+ tuscany::pgsql::testPGSql();
+ tuscany::pgsql::testGetPerf();
+
+ tuscany::cout << "OK" << tuscany::endl;
+
+ return 0;
+}
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-start b/sca-cpp/trunk/components/sqldb/pgsql-start
index f5c0f87614..3f03d0b4dc 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql-start
+++ b/sca-cpp/trunk/components/sqldb/pgsql-start
@@ -24,14 +24,6 @@ root=`readlink -f $1`
pgsql_prefix=`cat $here/pgsql.prefix`
mkdir -p $root/sqldb
mkdir -p $root/logs
-if [ ! -f $root/sqldb/postgresql.conf ]; then
- $pgsql_prefix/bin/pg_ctl init -D $root/sqldb 1>/dev/null 2>&1
- createdb="true"
-fi
-
-$pgsql_prefix/bin/pg_ctl start -D $root/sqldb -l $root/logs/postgresql 1>/dev/null 2>&1
-sleep 2
-if [ "$createdb" = "true" ]; then
- $pgsql_prefix/bin/createdb db 1>/dev/null 2>&1
-fi
+$pgsql_prefix/bin/pg_ctl start -w -D $root/sqldb/data -l $root/logs/postgresql 1>>$root/logs/postgresql 2>&1
+sleep 1
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-stop b/sca-cpp/trunk/components/sqldb/pgsql-stop
index d0cda096ba..eefade47d2 100755
--- a/sca-cpp/trunk/components/sqldb/pgsql-stop
+++ b/sca-cpp/trunk/components/sqldb/pgsql-stop
@@ -22,7 +22,6 @@ here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
pgsql_prefix=`cat $here/pgsql.prefix`
-mkdir -p $root/sqldb
mkdir -p $root/logs
-$pgsql_prefix/bin/pg_ctl stop -D $root/sqldb 1>/dev/null 2>&1
+$pgsql_prefix/bin/pg_ctl stop -w -D $root/sqldb/data 1>>$root/logs/postgresql 2>&1
diff --git a/sca-cpp/trunk/components/sqldb/pgsql-test.cpp b/sca-cpp/trunk/components/sqldb/pgsql-test.cpp
index 7fb6b0c814..1019667285 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("dbname=db", "test");
+ PGSql pg("host=localhost port=5432 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("dbname=db", "test");
+ PGSql pg("host=localhost port=5432 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 bb37d125b8..f4da8db220 100644
--- a/sca-cpp/trunk/components/sqldb/pgsql.hpp
+++ b/sca-cpp/trunk/components/sqldb/pgsql.hpp
@@ -40,10 +40,13 @@ namespace pgsql {
/**
* Return and clear a Postgres result failure.
*/
-const string pgfailure(PGresult* r) {
- const string e = PQresultErrorMessage(r);
+const string pgfailure(PGresult* r, PGconn* conn) {
+ const string re = PQresultErrorMessage(r);
PQclear(r);
- return e;
+ if (length(re) != 0)
+ return re;
+ const string ce = PQerrorMessage(conn);
+ return ce;
}
/**
@@ -54,19 +57,23 @@ public:
PGSql() : owner(false) {
}
- PGSql(const string& conninfo, const string& table) : owner(true), conninfo(conninfo), table(table) {
- init();
+ PGSql(const string& conninfo, const string& table) : owner(true), conn(NULL), conninfo(conninfo), table(table) {
+ conn = PQconnectdb(c_str(conninfo));
+ if (PQstatus(conn) != CONNECTION_OK) {
+ mkfailure<bool>(string("Could not connect to postgresql database: ") + PQerrorMessage(conn));
+ return;
+ }
+ setup(true);
}
- PGSql(const PGSql& c) : owner(false) {
- conninfo = c.conninfo;
- conn = c.conn;
- table = c.table;
+ PGSql(const PGSql& c) : owner(false), conn(c.conn), conninfo(c.conninfo), table(c.table) {
}
~PGSql() {
if (!owner)
return;
+ if (conn == NULL)
+ return;
PQfinish(conn);
}
@@ -76,28 +83,37 @@ private:
string conninfo;
string table;
+ 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);
/**
- * Initialize the database connection
+ * Setup the database connection.
*/
- const failable<bool> init() {
- conn = PQconnectdb(c_str(conninfo));
- if (PQstatus(conn) != CONNECTION_OK)
- return mkfailure<bool>(string("Could not connect to database: ") + PQerrorMessage(conn));
+ 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("Could not 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("Could not execute column select statement: ") + pgfailure(kr));
+ return mkfailure<bool>(string("Could not execute postgresql column select statement: ") + pgfailure(kr, conn));
if (PQntuples(kr) != 2) {
PQclear(kr);
- return mkfailure<bool>(string("Could not find table key and value column names"));
+ return mkfailure<bool>(string("Could not find postgresql table key and value column names"));
}
const string kname = PQgetvalue(kr, 0, 0);
const string vname = PQgetvalue(kr, 1, 0);
@@ -107,25 +123,25 @@ private:
{
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("Could not prepare post SQL statement: ") + pgfailure(r));
+ return mkfailure<bool>(string("Could not 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("Could not prepare put SQL statement: ") + pgfailure(r));
+ return mkfailure<bool>(string("Could not 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("Could not prepare get SQL statement: ") + pgfailure(r));
+ return mkfailure<bool>(string("Could not 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("Could not prepare delete SQL statement: ") + pgfailure(r));
+ return mkfailure<bool>(string("Could not prepare delete postgresql SQL statement: ") + pgfailure(r, conn));
PQclear(r);
}
return true;
@@ -133,6 +149,13 @@ private:
};
/**
+ * Setup the database connection if necessary.
+ */
+const failable<bool> setup(const PGSql& pgsql) {
+ return pgsql.setup(false);
+}
+
+/**
* Post a new item to the database.
*/
const failable<bool> post(const value& key, const value& val, const PGSql& pgsql) {
@@ -140,13 +163,14 @@ const failable<bool> post(const value& key, const value& val, const PGSql& pgsql
debug(val, "pgsql::post::value");
debug(pgsql.conninfo, "pgsql::post::conninfo");
debug(pgsql.table, "pgsql::post::table");
+ setup(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);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
- return mkfailure<bool>(string("Could not execute post SQL statement: ") + pgfailure(r));
+ return mkfailure<bool>(string("Could not execute insert postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
PQclear(r);
debug(true, "pgsql::post::result");
@@ -161,13 +185,14 @@ const failable<bool> put(const value& key, const value& val, const PGSql& pgsql)
debug(val, "pgsql::put::value");
debug(pgsql.conninfo, "pgsql::put::conninfo");
debug(pgsql.table, "pgsql::put::table");
+ setup(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);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
- return mkfailure<bool>(string("Could not execute put SQL statement: ") + pgfailure(r));
+ return mkfailure<bool>(string("Could not execute update postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
const string t = PQcmdTuples(r);
if (t != "0") {
PQclear(r);
@@ -178,7 +203,7 @@ const failable<bool> put(const value& key, const value& val, const PGSql& pgsql)
PGresult* pr = PQexecPrepared(pgsql.conn, "post", 2, params, NULL, NULL, 0);
if (PQresultStatus(pr) != PGRES_COMMAND_OK)
- return mkfailure<bool>(string("Could not execute post SQL statement: ") + pgfailure(pr));
+ return mkfailure<bool>(string("Could not execute insert postgresql SQL statement: ") + pgfailure(pr, pgsql.conn));
PQclear(pr);
debug(true, "pgsql::put::result");
@@ -192,15 +217,16 @@ const failable<value> get(const value& key, const PGSql& pgsql) {
debug(key, "pgsql::get::key");
debug(pgsql.conninfo, "pgsql::get::conninfo");
debug(pgsql.table, "pgsql::get::table");
+ setup(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);
if (PQresultStatus(r) != PGRES_TUPLES_OK)
- return mkfailure<value>(string("Could not execute get SQL statement: ") + pgfailure(r));
+ return mkfailure<value>(string("Could not execute select postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
if (PQntuples(r) < 1) {
PQclear(r);
- return mkfailure<value>(string("Could not get entry: ") + PQerrorMessage(pgsql.conn));
+ return mkfailure<value>(string("Could not get postgresql entry: ") + PQerrorMessage(pgsql.conn));
}
const char* data = PQgetvalue(r, 0, 1);
const value val(scheme::readValue(string(data)));
@@ -217,12 +243,13 @@ const failable<bool> del(const value& key, const PGSql& pgsql) {
debug(key, "pgsql::delete::key");
debug(pgsql.conninfo, "pgsql::delete::conninfo");
debug(pgsql.table, "pgsql::delete::table");
+ setup(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);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
- return mkfailure<bool>(string("Could not execute delete SQL statement: ") + pgfailure(r));
+ return mkfailure<bool>(string("Could not execute delete postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
PQclear(r);
debug(true, "pgsql::delete::result");
diff --git a/sca-cpp/trunk/components/sqldb/server-test b/sca-cpp/trunk/components/sqldb/server-test
index 784c7156c5..c07d3b0510 100755
--- a/sca-cpp/trunk/components/sqldb/server-test
+++ b/sca-cpp/trunk/components/sqldb/server-test
@@ -19,6 +19,11 @@
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
+./pgsql-conf tmp
+./pgsql-start tmp
+./pgsql "drop table test;" 1>/dev/null 2>&1
+./pgsql "create table test(key text, value text);" 1>/dev/null 2>&1
+
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
@@ -26,9 +31,6 @@ SCAContribution `pwd`/
SCAComposite sqldb.composite
EOF
-./pgsql-start tmp
-./pgsql "drop table test;" 1>/dev/null 2>&1
-./pgsql "create table test(key text, value text);" 1>/dev/null 2>&1
../../modules/http/httpd-start tmp
sleep 2
@@ -39,5 +41,4 @@ rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
./pgsql-stop tmp
-sleep 2
return $rc
diff --git a/sca-cpp/trunk/components/sqldb/sqldb-test b/sca-cpp/trunk/components/sqldb/sqldb-test
index 05fe413d50..e910ae0059 100755
--- a/sca-cpp/trunk/components/sqldb/sqldb-test
+++ b/sca-cpp/trunk/components/sqldb/sqldb-test
@@ -18,6 +18,7 @@
# under the License.
# Setup
+./pgsql-conf tmp
./pgsql-start tmp
./pgsql "drop table test;" 1>/dev/null 2>&1
./pgsql "create table test(key text, value text);" 1>/dev/null 2>&1
diff --git a/sca-cpp/trunk/components/sqldb/sqldb.composite b/sca-cpp/trunk/components/sqldb/sqldb.composite
index a27332e649..1511e66024 100644
--- a/sca-cpp/trunk/components/sqldb/sqldb.composite
+++ b/sca-cpp/trunk/components/sqldb/sqldb.composite
@@ -24,7 +24,7 @@
<component name="sqldb">
<implementation.cpp path="." library="libsqldb"/>
- <property name="conninfo">dbname=db</property>
+ <property name="conninfo">host=localhost port=5432 dbname=db</property>
<property name="table">test</property>
<service name="sqldb">
<t:binding.http uri="sqldb"/>
diff --git a/sca-cpp/trunk/components/sqldb/sqldb.cpp b/sca-cpp/trunk/components/sqldb/sqldb.cpp
index e84a732511..0524b00bd2 100644
--- a/sca-cpp/trunk/components/sqldb/sqldb.cpp
+++ b/sca-cpp/trunk/components/sqldb/sqldb.cpp
@@ -23,10 +23,7 @@
* PostgreSQL-based database component implementation.
*/
-#include <apr_uuid.h>
-
#include "string.hpp"
-
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
@@ -46,16 +43,8 @@ const failable<value> get(const list<value>& params, pgsql::PGSql& pg) {
/**
* Post an item to the database.
*/
-const value uuidValue() {
- apr_uuid_t uuid;
- apr_uuid_get(&uuid);
- char buf[APR_UUID_FORMATTED_LENGTH];
- apr_uuid_format(buf, &uuid);
- return value(string(buf, APR_UUID_FORMATTED_LENGTH));
-}
-
const failable<value> post(const list<value>& params, pgsql::PGSql& pg) {
- const value id = append<value>(car(params), mklist(uuidValue()));
+ const value id = append<value>(car(params), mklist(mkuuid()));
const failable<bool> val = pgsql::post(id, cadr(params), pg);
if (!hasContent(val))
return mkfailure<value>(reason(val));
diff --git a/sca-cpp/trunk/components/sqldb/standby-test b/sca-cpp/trunk/components/sqldb/standby-test
new file mode 100755
index 0000000000..e572de6fe2
--- /dev/null
+++ b/sca-cpp/trunk/components/sqldb/standby-test
@@ -0,0 +1,39 @@
+#!/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.
+
+# Setup
+../../modules/http/httpd-conf tmp/master localhost 8090 tmp/master/htdocs
+./pgsql-conf tmp/master 5432
+./pgsql-start tmp/master
+./pgsql localhost 5432 "drop table test;" 1>/dev/null 2>&1
+./pgsql localhost 5432 "create table test(key text, value text);" 1>/dev/null 2>&1
+../../modules/http/httpd-start tmp/master
+sleep 2
+./pgsql-standby-conf tmp/standby localhost 5432 8090 5433
+./pgsql-start tmp/standby
+
+# Test
+./pgsql-standby-test 2>/dev/null
+rc=$?
+
+# Cleanup
+../../modules/http/httpd-stop tmp/master
+./pgsql-stop tmp/standby
+./pgsql-stop tmp/master
+return $rc