From 36adc76235fb0a38e7042bc751f988b71627e2a0 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Tue, 11 Dec 2012 06:13:02 +0000 Subject: Changes to get successful C++11 based build. Code cleanup, dependency upgrades, and const + inline optimizations in components, samples, and app hosting server. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1420007 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/INSTALL | 24 +- sca-cpp/trunk/README | 7 +- sca-cpp/trunk/components/cache/Makefile.am | 2 +- sca-cpp/trunk/components/cache/cache.composite | 2 +- sca-cpp/trunk/components/cache/client-test.cpp | 83 +++-- sca-cpp/trunk/components/cache/datacache.cpp | 12 +- sca-cpp/trunk/components/cache/memcache-test.cpp | 26 +- sca-cpp/trunk/components/cache/memcache.cpp | 51 ++- sca-cpp/trunk/components/cache/memcache.hpp | 78 ++--- sca-cpp/trunk/components/cache/memocache.cpp | 2 +- sca-cpp/trunk/components/cache/partitioner.cpp | 97 ++++-- sca-cpp/trunk/components/cache/select-test.scm | 2 +- sca-cpp/trunk/components/chat/Makefile.am | 10 +- sca-cpp/trunk/components/chat/chat-send.cpp | 4 +- sca-cpp/trunk/components/chat/chat-sender.cpp | 91 ++---- sca-cpp/trunk/components/chat/chat-sender2.cpp | 36 +-- .../trunk/components/chat/chat-sendreceiver.cpp | 99 ++---- sca-cpp/trunk/components/chat/client-test.cpp | 39 +-- sca-cpp/trunk/components/chat/xmpp-test.cpp | 23 +- sca-cpp/trunk/components/chat/xmpp.hpp | 73 ++--- sca-cpp/trunk/components/constdb/Makefile.am | 2 +- sca-cpp/trunk/components/constdb/client-test.cpp | 71 ++--- sca-cpp/trunk/components/constdb/constdb.cpp | 39 +-- sca-cpp/trunk/components/constdb/tinycdb-test.cpp | 24 +- sca-cpp/trunk/components/constdb/tinycdb.hpp | 248 +++++++-------- sca-cpp/trunk/components/filedb/Makefile.am | 6 +- sca-cpp/trunk/components/filedb/client-test.cpp | 71 ++--- sca-cpp/trunk/components/filedb/file-test.cpp | 32 +- sca-cpp/trunk/components/filedb/filedb.cpp | 43 +-- sca-cpp/trunk/components/filedb/filedb.hpp | 57 ++-- sca-cpp/trunk/components/http/Makefile.am | 12 +- sca-cpp/trunk/components/http/client-test.cpp | 33 +- sca-cpp/trunk/components/http/httpdelete.cpp | 57 ++-- sca-cpp/trunk/components/http/httpget.cpp | 58 ++-- sca-cpp/trunk/components/http/httppatch.cpp | 61 ++-- sca-cpp/trunk/components/http/httppost.cpp | 61 ++-- sca-cpp/trunk/components/http/httpput.cpp | 61 ++-- sca-cpp/trunk/components/kvdb/Makefile.am | 49 --- sca-cpp/trunk/components/kvdb/client-test.cpp | 139 --------- sca-cpp/trunk/components/kvdb/kvdb-test | 30 -- sca-cpp/trunk/components/kvdb/kvdb.componentType | 28 -- sca-cpp/trunk/components/kvdb/kvdb.composite | 32 -- sca-cpp/trunk/components/kvdb/kvdb.cpp | 124 -------- sca-cpp/trunk/components/kvdb/leveldb | 24 -- sca-cpp/trunk/components/kvdb/leveldb-test.cpp | 82 ----- sca-cpp/trunk/components/kvdb/leveldb.hpp | 271 ---------------- sca-cpp/trunk/components/kvdb/server-test | 41 --- sca-cpp/trunk/components/log/Makefile.am | 2 +- sca-cpp/trunk/components/log/client-test.cpp | 57 ++-- sca-cpp/trunk/components/log/log.cpp | 37 +-- sca-cpp/trunk/components/log/logger.cpp | 46 +-- sca-cpp/trunk/components/log/scribe-cat.cpp | 8 +- sca-cpp/trunk/components/log/scribe-status.cpp | 2 +- sca-cpp/trunk/components/log/scribe.hpp | 38 +-- sca-cpp/trunk/components/queue/Makefile.am | 2 +- sca-cpp/trunk/components/queue/client-test.cpp | 24 +- sca-cpp/trunk/components/queue/qpid-test.cpp | 14 +- sca-cpp/trunk/components/queue/qpid.hpp | 27 +- sca-cpp/trunk/components/queue/queue-listener.cpp | 106 ++----- sca-cpp/trunk/components/queue/queue-sender.cpp | 2 +- sca-cpp/trunk/components/smtp/Makefile.am | 4 +- sca-cpp/trunk/components/smtp/client-test.cpp | 4 +- sca-cpp/trunk/components/smtp/smtppost.cpp | 90 +++--- sca-cpp/trunk/components/sqldb/Makefile.am | 4 +- sca-cpp/trunk/components/sqldb/client-test.cpp | 71 ++--- .../trunk/components/sqldb/pgsql-standby-test.cpp | 20 +- sca-cpp/trunk/components/sqldb/pgsql-test.cpp | 33 +- sca-cpp/trunk/components/sqldb/pgsql.hpp | 204 +++++++++--- sca-cpp/trunk/components/sqldb/sqldb.cpp | 65 ++-- sca-cpp/trunk/components/webservice/Makefile.am | 5 +- sca-cpp/trunk/components/webservice/axiom-test.cpp | 12 +- .../components/webservice/axis2-dispatcher.cpp | 2 +- .../trunk/components/webservice/axis2-service.cpp | 20 +- sca-cpp/trunk/components/webservice/axis2-test.cpp | 15 +- sca-cpp/trunk/components/webservice/axis2.hpp | 41 +-- .../trunk/components/webservice/client-test.cpp | 30 +- sca-cpp/trunk/components/webservice/echo-test | 1 + sca-cpp/trunk/components/webservice/server-test | 1 + .../components/webservice/webservice-client.cpp | 4 +- .../components/webservice/webservice-listener.cpp | 10 +- sca-cpp/trunk/configure.ac | 48 ++- sca-cpp/trunk/hosting/server/client-test.cpp | 2 +- sca-cpp/trunk/hosting/server/client-test.hpp | 343 ++++++++------------- sca-cpp/trunk/patches/scribe-2.2.patch | 53 ++++ sca-cpp/trunk/patches/thrift-0.2.0.patch | 39 --- sca-cpp/trunk/patches/thrift-0.8.0.patch | 41 +++ sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp | 22 +- sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp | 14 +- sca-cpp/trunk/samples/store-java/Makefile.am | 9 +- sca-cpp/trunk/samples/store-scheme/Makefile.am | 2 +- sca-cpp/trunk/samples/store-scheme/script-test.cpp | 14 +- .../trunk/unmaintained/components/kvdb/Makefile.am | 49 +++ .../unmaintained/components/kvdb/client-test.cpp | 139 +++++++++ .../trunk/unmaintained/components/kvdb/kvdb-test | 30 ++ .../components/kvdb/kvdb.componentType | 28 ++ .../unmaintained/components/kvdb/kvdb.composite | 32 ++ .../trunk/unmaintained/components/kvdb/kvdb.cpp | 124 ++++++++ sca-cpp/trunk/unmaintained/components/kvdb/leveldb | 24 ++ .../unmaintained/components/kvdb/leveldb-test.cpp | 82 +++++ .../trunk/unmaintained/components/kvdb/leveldb.hpp | 271 ++++++++++++++++ .../trunk/unmaintained/components/kvdb/server-test | 41 +++ 101 files changed, 2270 insertions(+), 2655 deletions(-) delete mode 100644 sca-cpp/trunk/components/kvdb/Makefile.am delete mode 100644 sca-cpp/trunk/components/kvdb/client-test.cpp delete mode 100755 sca-cpp/trunk/components/kvdb/kvdb-test delete mode 100644 sca-cpp/trunk/components/kvdb/kvdb.componentType delete mode 100644 sca-cpp/trunk/components/kvdb/kvdb.composite delete mode 100644 sca-cpp/trunk/components/kvdb/kvdb.cpp delete mode 100755 sca-cpp/trunk/components/kvdb/leveldb delete mode 100644 sca-cpp/trunk/components/kvdb/leveldb-test.cpp delete mode 100644 sca-cpp/trunk/components/kvdb/leveldb.hpp delete mode 100755 sca-cpp/trunk/components/kvdb/server-test delete mode 100644 sca-cpp/trunk/patches/thrift-0.2.0.patch create mode 100644 sca-cpp/trunk/patches/thrift-0.8.0.patch create mode 100644 sca-cpp/trunk/unmaintained/components/kvdb/Makefile.am create mode 100644 sca-cpp/trunk/unmaintained/components/kvdb/client-test.cpp create mode 100755 sca-cpp/trunk/unmaintained/components/kvdb/kvdb-test create mode 100644 sca-cpp/trunk/unmaintained/components/kvdb/kvdb.componentType create mode 100644 sca-cpp/trunk/unmaintained/components/kvdb/kvdb.composite create mode 100644 sca-cpp/trunk/unmaintained/components/kvdb/kvdb.cpp create mode 100755 sca-cpp/trunk/unmaintained/components/kvdb/leveldb create mode 100644 sca-cpp/trunk/unmaintained/components/kvdb/leveldb-test.cpp create mode 100644 sca-cpp/trunk/unmaintained/components/kvdb/leveldb.hpp create mode 100755 sca-cpp/trunk/unmaintained/components/kvdb/server-test (limited to 'sca-cpp') diff --git a/sca-cpp/trunk/INSTALL b/sca-cpp/trunk/INSTALL index c66c88bce5..80a4d8472f 100644 --- a/sca-cpp/trunk/INSTALL +++ b/sca-cpp/trunk/INSTALL @@ -31,11 +31,11 @@ The installation script will display each command as it's executed. That's all you need to do to build and install the Tuscany SCA runtime on Ubuntu Server. -Automated installation on Max OS X 10.7.4 -========================================= +Automated installation on Max OS X 10.8 +======================================= -Tuscany provides an automated install script for Mac OS X 10.7.4 and Xcode 4.1. -You can start with a fresh Mac OS X 10.7.4 + Xcode 4.1 system and the script +Tuscany provides an automated install script for Mac OS X 10.8 and Xcode 4.4. +You can start with a fresh Mac OS X 10.8 + Xcode 4.4 system and the script will take care of all the download, build and installation steps for you. macos/macos-install: @@ -89,12 +89,11 @@ XML: libxml2-2.7.7 (http://xmlsoft.org/) CURL: -curl-7-24.0 +curl-7-28.0 (http://curl.haxx.se) +built with c-ares-1.9.1 (http://c-ares.haxx.se) JSON: -Mozilla SpiderMonkey libmozjs 1.8.5 and -(https://developer.mozilla.org/en/SpiderMonkey) -built with Mozilla nspr-4.8.8 +Jansson 2.4 (http://www.digip.org/jansson/) Key/value persistent store: tinycdb-0.77 (http://www.corpit.ru/mjt/tinycdb.html) @@ -143,16 +142,13 @@ Apache Vysper 0.5 (http://mina.apache.org/) Libstrophe (http://code.stanziq.com/strophe/) build it from source at git://github.com/jsdelfino/libstrophe.git -Key/value persistent store: -Google LevelDB 1.2 (http://code.google.com/p/leveldb/) - SQL database: PostgreSQL 9.1.2 (http://www.postgresql.org/) PgBouncer 1.5 (http://wiki.postgresql.org/wiki/PgBouncer) Logging: Facebook Scribe 2.2 (http://github.com/facebook/scribe/downloads) -requires Apache Thrift 0.2.0 (http://incubator.apache.org/thrift/) +requires Apache Thrift 0.8.0 (http://incubator.apache.org/thrift/) Cloud deployment: Apache Libcloud 0.3.1 (http://incubator.apache.org/libcloud/) @@ -228,7 +224,7 @@ most useful options and the corresponding dependencies installed under $build: ./configure --prefix=$build/tuscany-sca-cpp-bin \ --enable-threads --enable-maintainer-mode \ ---with-curl=$build/curl-7.24.0-bin --with-libxml2=$build/libxml2-2.7.7-bin \ +--with-curl=$build/curl-7.28.0-bin --with-libxml2=$build/libxml2-2.7.7-bin \ --with-apr=$build/apr-1.4.6-bin --with-apr-util=$build/apr-util-1.4.1-bin \ --with-httpd=$build/httpd-2.4.2-bin \ --with-memcached=$build/memcached-1.4.7-bin \ @@ -238,7 +234,7 @@ most useful options and the corresponding dependencies installed under $build: --enable-python --with-python=$build/python-2.7.3-bin \ --enable-sqldb --with-pgsql=$build/postgresql-9.1.2-bin \ --with-pgbouncer=$build/pgbouncer-1.5-bin \ ---enable-log --with-thrift=$build/thrift-0.2.0-bin \ +--enable-log --with-thrift=$build/thrift-0.8.0-bin \ --with-scribe=$build/scribe-2.2-bin \ --enable-oauth --with-liboauth=$build/liboauth-0.9.1-bin \ --enable-mod-security --with-mod-security=$build/modsecurity-apache-2.6.6-bin \ diff --git a/sca-cpp/trunk/README b/sca-cpp/trunk/README index 1d81008041..bca9c53f74 100644 --- a/sca-cpp/trunk/README +++ b/sca-cpp/trunk/README @@ -6,8 +6,8 @@ in C++ and integrated with the Apache HTTPD server. It supports SCA components written in C++ and Python. Experimental support for other programming languages is under construction. SCA bindings are -available for the JSON-RPC, ATOMPub and RSS protocols. User signin is -implemented using OpenID and OAuth. +available for REST services and the JSON-RPC, ATOMPub and RSS protocols. +User signin is implemented using OpenID and OAuth. Several useful SCA components are provided on top of the SCA runtime, which can be used to help assemble distributed SCA composite applications: @@ -18,7 +18,6 @@ Constdb: fast persistent store for mostly constant data, using TinyCDB; Filedb: key/value persistent store, using plain files; Http: HTTP client, using Libcurl; Smtp: SMTP client, using Libcurl; -Kvdb: fast key/value persistent store, using LevelDB; Log: distributed logger, using Facebook Scribe; Queue: AMQP queuing, using Apache Qpid/C; Sqldb: SQL database, using PostgreSQL and PgBouncer; @@ -78,7 +77,6 @@ Here's a rough guide to the Tuscany SCA source tree: | | |-- constdb TinyCDB constant persistent store | | |-- filedb Plain file persistent store | | |-- http HTTP client - | | |-- kvdb LevelDB key/value persistent store | | |-- log Scribe logger | | |-- queue AMQP message queue | | |-- smtp SMTP client @@ -99,6 +97,7 @@ Here's a rough guide to the Tuscany SCA source tree: | |-- macos Automated install on Mac OS X 10.7.4 | |-- ubuntu Automated install on Ubuntu 12.04 | |-- patches Temporary patches to some of the dependencies + | |-- unmaintained Unmaintained or outdated modules | |-- branches Topic and release branches | diff --git a/sca-cpp/trunk/components/cache/Makefile.am b/sca-cpp/trunk/components/cache/Makefile.am index 0240a32bb4..3704a7a3ce 100644 --- a/sca-cpp/trunk/components/cache/Makefile.am +++ b/sca-cpp/trunk/components/cache/Makefile.am @@ -50,7 +50,7 @@ memcache_test_SOURCES = memcache-test.cpp memcache_test_LDFLAGS = -lxml2 client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = memcached-test memcached-ssl-test server-test noinst_PROGRAMS = memcache-test client-test diff --git a/sca-cpp/trunk/components/cache/cache.composite b/sca-cpp/trunk/components/cache/cache.composite index a85f909db9..99fdd8ffc0 100644 --- a/sca-cpp/trunk/components/cache/cache.composite +++ b/sca-cpp/trunk/components/cache/cache.composite @@ -81,7 +81,7 @@ - + diff --git a/sca-cpp/trunk/components/cache/client-test.cpp b/sca-cpp/trunk/components/cache/client-test.cpp index 63d1691f8b..5e9be6c14a 100644 --- a/sca-cpp/trunk/components/cache/client-test.cpp +++ b/sca-cpp/trunk/components/cache/client-test.cpp @@ -42,15 +42,15 @@ const string memocacheuri("http://localhost:8090/memocache"); const string partition1uri("http://localhost:8090/partitioner/a"); const string partition2uri("http://localhost:8090/partitioner/b"); -bool testCache(const string& uri) { - http::CURLSession cs("", "", "", "", 0); - - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testCache(const string& uri) { + const http::CURLSession cs("", "", "", "", 0); + + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); const failable id = http::post(a, uri, cs); @@ -63,18 +63,18 @@ bool testCache(const string& uri) { assert(content(val) == a); } - const list j = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$3.55"))); - const list b = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list j = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$3.55"))); + const list b = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + j); { const failable r = http::put(b, uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable val = http::get(uri + p, cs); @@ -84,7 +84,7 @@ bool testCache(const string& uri) { { const failable r = http::del(uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable val = http::get(uri + p, cs); @@ -94,16 +94,16 @@ bool testCache(const string& uri) { return true; } -bool testMemcache() { +const bool testMemcache() { return testCache(memcacheuri); } -bool testDatacache() { +const bool testDatacache() { return testCache(datacacheuri); } -bool testMemocache() { - http::CURLSession cs("", "", "", "", 0); +const bool testMemocache() { + const http::CURLSession cs("", "", "", "", 0); const failable res = http::evalExpr(mklist(string("add"), 33, 22), memocacheuri, cs); assert(hasContent(res)); @@ -116,8 +116,8 @@ bool testMemocache() { return true; } -bool testPartitioner() { - http::CURLSession cs("", "", "", "", 0); +const bool testPartitioner() { + const http::CURLSession cs("", "", "", "", 0); const failable res1 = http::get(partition1uri, cs); assert(hasContent(res1)); @@ -130,35 +130,26 @@ bool testPartitioner() { return true; } -struct getLoop { - const string path; - const value entry; - http::CURLSession& cs; - getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { - } - const bool operator()() const { - const failable val = http::get(memcacheuri + path, cs); - assert(hasContent(val)); - assert(content(val) == entry); - return true; - } -}; - -bool testGetPerf() { - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$4.55"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testGetPerf() { + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$4.55"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", "", 0); + const http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, memcacheuri, cs); assert(hasContent(id)); const string p = path(content(id)); - const lambda gl = getLoop(p, a, cs); + const blambda gl = [p, a, cs]() -> const bool { + const failable val = http::get(memcacheuri + p, cs); + assert(hasContent(val)); + assert(content(val) == a); + return true; + }; cout << "Cache get test " << time(gl, 5, 200) << " ms" << endl; return true; diff --git a/sca-cpp/trunk/components/cache/datacache.cpp b/sca-cpp/trunk/components/cache/datacache.cpp index c259ec33c6..975ca43dce 100644 --- a/sca-cpp/trunk/components/cache/datacache.cpp +++ b/sca-cpp/trunk/components/cache/datacache.cpp @@ -44,7 +44,7 @@ namespace datacache { /** * Get an item from the cache. */ -const failable get(const value& key, const lambda&)>& rcache1, const lambda&)>& wcache1, const lambda&)>& rcache2, unused const lambda&)>& wcache2) { +const failable get(const value& key, const lvvlambda& rcache1, const lvvlambda& wcache1, const lvvlambda& rcache2, unused const lvvlambda& wcache2) { // Lookup level1 cache const value val1 = rcache1(mklist("get", key)); @@ -68,7 +68,7 @@ const failable get(const value& key, const lambda /** * Post an item to the cache. */ -const failable post(const value& key, const value& val, unused const lambda&)>& rcache1, const lambda&)>& wcache1, unused const lambda&)>& rcache2, const lambda&)>& wcache2) { +const failable post(const value& key, const value& val, unused const lvvlambda& rcache1, const lvvlambda& wcache1, unused const lvvlambda& rcache2, const lvvlambda& wcache2) { const value id = append(key, mklist(mkuuid())); // Update level1 cache @@ -83,7 +83,7 @@ const failable post(const value& key, const value& val, unused const lamb /** * Put an item into the cache. */ -const failable put(const value& key, const value& val, unused const lambda&)>& rcache1, const lambda&)>& wcache1, unused const lambda&)>& rcache2, const lambda&)>& wcache2) { +const failable put(const value& key, const value& val, unused const lvvlambda& rcache1, const lvvlambda& wcache1, unused const lvvlambda& rcache2, const lvvlambda& wcache2) { // Update level1 cache wcache1(mklist("put", key, val)); @@ -91,13 +91,13 @@ const failable put(const value& key, const value& val, unused const lambd // Update level2 cache wcache2(mklist("put", key, val)); - return value(true); + return trueValue; } /** * Delete an item from the cache. */ -const failable del(const value& key, unused const lambda&)>& rcache1, const lambda&)>& wcache1, unused const lambda&)>& rcache2, const lambda&)>& wcache2) { +const failable del(const value& key, unused const lvvlambda& rcache1, const lvvlambda& wcache1, unused const lvvlambda& rcache2, const lvvlambda& wcache2) { // Delete from level1 cache wcache1(mklist("delete", key)); @@ -105,7 +105,7 @@ const failable del(const value& key, unused const lambda("delete", key)); - return value(true); + return trueValue; } } diff --git a/sca-cpp/trunk/components/cache/memcache-test.cpp b/sca-cpp/trunk/components/cache/memcache-test.cpp index 85fc339f1a..6c6adb0541 100644 --- a/sca-cpp/trunk/components/cache/memcache-test.cpp +++ b/sca-cpp/trunk/components/cache/memcache-test.cpp @@ -33,7 +33,7 @@ namespace tuscany { namespace memcache { bool testMemCached() { - MemCached ch(mklist("localhost:11211", "localhost:11212", "localhost:11213")); + const MemCached ch(mklist("localhost:11211", "localhost:11212", "localhost:11213")); const value k = mklist("a"); assert(hasContent(post(k, string("AAA"), ch))); @@ -46,24 +46,16 @@ bool testMemCached() { return true; } -struct getLoop { - const value k; - MemCached& ch; - getLoop(const value& k, MemCached& ch) : k(k), ch(ch) { - } - const bool operator()() const { - gc_scoped_pool p; - assert(get(k, ch) == value(string("CCC"))); - return true; - } -}; - -bool testGetPerf() { +const bool testGetPerf() { const value k = mklist("c"); - MemCached ch(mklist("localhost:11211", "localhost:11212", "localhost:11213")); + const MemCached ch(mklist("localhost:11211", "localhost:11212", "localhost:11213")); assert(hasContent(post(k, string("CCC"), ch))); - const lambda gl = getLoop(k, ch); + const blambda gl = [k, ch]() -> const bool { + const gc_scoped_pool p; + assert(get(k, ch) == value(string("CCC"))); + return true; + }; cout << "Memcached get test " << time(gl, 5, 200) << " ms" << endl; return true; } @@ -72,7 +64,7 @@ bool testGetPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::memcache::testMemCached(); diff --git a/sca-cpp/trunk/components/cache/memcache.cpp b/sca-cpp/trunk/components/cache/memcache.cpp index 738a6ddd5a..2e4597efd3 100644 --- a/sca-cpp/trunk/components/cache/memcache.cpp +++ b/sca-cpp/trunk/components/cache/memcache.cpp @@ -37,14 +37,14 @@ namespace cache { /** * Get an item from the cache. */ -const failable get(const list& params, memcache::MemCached& ch) { +const failable get(const list& params, const memcache::MemCached& ch) { return memcache::get(car(params), ch); } /** * Post an item to the cache. */ -const failable post(const list& params, memcache::MemCached& ch) { +const failable post(const list& params, const memcache::MemCached& ch) { const value id = append(car(params), mklist(mkuuid())); const failable val = memcache::post(id, cadr(params), ch); if (!hasContent(val)) @@ -55,7 +55,7 @@ const failable post(const list& params, memcache::MemCached& ch) { /** * Put an item into the cache. */ -const failable put(const list& params, memcache::MemCached& ch) { +const failable put(const list& params, const memcache::MemCached& ch) { const failable val = memcache::put(car(params), cadr(params), ch); if (!hasContent(val)) return mkfailure(val); @@ -65,45 +65,20 @@ const failable put(const list& params, memcache::MemCached& ch) { /** * Delete an item from the cache. */ -const failable del(const list& params, memcache::MemCached& ch) { +const failable del(const list& params, const memcache::MemCached& ch) { const failable val = memcache::del(car(params), ch); if (!hasContent(val)) return mkfailure(val); return value(content(val)); } -/** - * Component implementation lambda function. - */ -class applyCache { -public: - applyCache(memcache::MemCached& ch) : ch(ch) { - } - - const value operator()(const list& params) const { - const value func(car(params)); - if (func == "get") - return get(cdr(params), ch); - if (func == "post") - return post(cdr(params), ch); - if (func == "put") - return put(cdr(params), ch); - if (func == "delete") - return del(cdr(params), ch); - return mkfailure(); - } - -private: - memcache::MemCached& ch; -}; - /** * Convert a list of properties to a list of server addresses. */ const list servers(const list& params) { if (isNil(params)) return list(); - const value s = ((lambda&)>)car(params))(list()); + const value s = ((lvvlambda)car(params))(nilListValue); return cons(s, servers(cdr(params))); } @@ -112,10 +87,22 @@ const list servers(const list& params) { */ const failable start(const list& params) { // Connect to memcached - memcache::MemCached& ch = *(new (gc_new()) memcache::MemCached(servers(params))); + const memcache::MemCached& ch = *(new (gc_new()) memcache::MemCached(servers(params))); // Return the component implementation lambda function - return value(lambda&)>(applyCache(ch))); + const lvvlambda applyCache = [ch](const list& params) -> const value { + const value func(car(params)); + if (func == "get") + return get(cdr(params), ch); + if (func == "post") + return post(cdr(params), ch); + if (func == "put") + return put(cdr(params), ch); + if (func == "delete") + return del(cdr(params), ch); + return mkfailure(); + }; + return value(applyCache); } } diff --git a/sca-cpp/trunk/components/cache/memcache.hpp b/sca-cpp/trunk/components/cache/memcache.hpp index f18405b2ec..00ee9c6291 100644 --- a/sca-cpp/trunk/components/cache/memcache.hpp +++ b/sca-cpp/trunk/components/cache/memcache.hpp @@ -48,43 +48,28 @@ namespace memcache { */ class MemCached { public: - MemCached() : owner(false) { + MemCached() : owner(false), mc(NULL) { } - MemCached(const string host, const int port) : p(), owner(true) { - debug(host, "memcache::memcached::host"); - debug(port, "memcache::memcached::port"); - apr_memcache_create(pool(p), 1, 0, &mc); - addServer(host, port); + MemCached(const string& host, const int port) : p(), owner(true), mc(mkmc(host, port)) { } - MemCached(const list& servers) : p(), owner(true) { - debug(servers, "memcache::memcached::servers"); - apr_memcache_create(pool(p), (apr_uint16_t)length(servers), 0, &mc); - addServers(servers); + MemCached(const list& servers) : p(), owner(true), mc(mkmc(servers)) { } MemCached(const MemCached& c) : p(c.p), owner(false), mc(c.mc) { debug("memcache::memcached::copy"); } - const MemCached& operator=(const MemCached& c) { - debug("memcache::memcached::operator="); - if(this == &c) - return *this; - p = c.p; - owner = false; - mc = c.mc; - return *this; - } + MemCached& operator=(const MemCached& c) = delete; ~MemCached() { } private: - gc_child_pool p; - bool owner; - apr_memcache_t* mc; + const gc_child_pool p; + const bool owner; + apr_memcache_t* const mc; friend const failable post(const value& key, const value& val, const MemCached& cache); friend const failable put(const value& key, const value& val, const MemCached& cache); @@ -94,7 +79,7 @@ private: /** * Add servers to the memcached context. */ - const failable addServer(const string& host, const int port) { + const failable addServer(apr_memcache_t* const m, const string& host, const int port) { apr_memcache_server_t *server; const apr_status_t sc = apr_memcache_server_create(pool(p), c_str(host), (apr_port_t)port, 1, 1, 1, 600, &server); if (sc != APR_SUCCESS) { @@ -102,27 +87,48 @@ private: os << "Couldn't connect to memcached server: " << host << ":" << port; return mkfailure(str(os)); } - const apr_status_t as = apr_memcache_add_server(mc, server); + const apr_status_t as = apr_memcache_add_server(m, server); if (as != APR_SUCCESS) return mkfailure("Couldn't add memcached server"); return true; } - const failable addServers(const list& servers) { + const failable addServers(apr_memcache_t* const m, const list& servers) { if (isNil(servers)) return true; const list toks = tokenize(":", car(servers)); - const failable r = addServer(car(toks), isNil(cdr(toks))? 11211 : atoi(c_str(cadr(toks)))); + const failable r = addServer(m, car(toks), isNil(cdr(toks))? 11211 : atoi(c_str(cadr(toks)))); if (!hasContent(r)) return r; - return addServers(cdr(servers)); + return addServers(m, cdr(servers)); + } + + /** + * Create memcached handle. + */ + apr_memcache_t* const mkmc(const string& host, const int port) { + debug(host, "memcache::memcached::host"); + debug(port, "memcache::memcached::port"); + apr_memcache_t* m; + apr_memcache_create(pool(p), 1, 0, &m); + addServer(m, host, port); + return m; } + + apr_memcache_t* const mkmc(const list& servers) { + debug(servers, "memcache::memcached::servers"); + apr_memcache_t* m; + apr_memcache_create(pool(p), (apr_uint16_t)length(servers), 0, &m); + addServers(m, servers); + return m; + } + }; /** * Replace spaces by tabs (as spaces are not allowed in memcached keys). */ -const char* nospaces(const char* s) { +const char* const nospaces(const char* const s) { char* c = const_cast(s); for (; *c; c++) if (*c == ' ') @@ -137,8 +143,8 @@ const failable post(const value& key, const value& val, const MemCached& c debug(key, "memcache::post::key"); debug(val, "memcache::post::value"); - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); const apr_status_t rc = apr_memcache_add(cache.mc, nospaces(c_str(ks)), const_cast(c_str(vs)), length(vs), 0, 27); if (rc != APR_SUCCESS) { ostringstream os; @@ -157,8 +163,8 @@ const failable put(const value& key, const value& val, const MemCached& ca debug(key, "memcache::put::key"); debug(val, "memcache::put::value"); - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); const apr_status_t rc = apr_memcache_set(cache.mc, nospaces(c_str(ks)), const_cast(c_str(vs)), length(vs), 0, 27); if (rc != APR_SUCCESS) { ostringstream os; @@ -176,17 +182,17 @@ const failable put(const value& key, const value& val, const MemCached& ca const failable get(const value& key, const MemCached& cache) { debug(key, "memcache::get::key"); - const string ks(scheme::writeValue(key)); + const string ks(write(content(scheme::writeValue(key)))); char *data; apr_size_t size; - gc_local_pool lp; + const gc_local_pool lp; const apr_status_t rc = apr_memcache_getp(cache.mc, pool(lp), nospaces(c_str(ks)), &data, &size, NULL); if (rc != APR_SUCCESS) { ostringstream os; os << "Couldn't get memcached entry: " << key; return mkfailure(str(os), 404, false); } - const value val(scheme::readValue(string(data, size))); + const value val(content(scheme::readValue(string(data, size)))); debug(val, "memcache::get::result"); return val; @@ -198,7 +204,7 @@ const failable get(const value& key, const MemCached& cache) { const failable del(const value& key, const MemCached& cache) { debug(key, "memcache::delete::key"); - const string ks(scheme::writeValue(key)); + const string ks(write(content(scheme::writeValue(key)))); const apr_status_t rc = apr_memcache_delete(cache.mc, nospaces(c_str(ks)), 0); if (rc != APR_SUCCESS) { ostringstream os; diff --git a/sca-cpp/trunk/components/cache/memocache.cpp b/sca-cpp/trunk/components/cache/memocache.cpp index e7e52cdc59..5539ccee2f 100644 --- a/sca-cpp/trunk/components/cache/memocache.cpp +++ b/sca-cpp/trunk/components/cache/memocache.cpp @@ -42,7 +42,7 @@ namespace memocache { /** * Memoize the value of a function application in a cache. */ -const failable memoize(const list& params, const lambda&)>& relay, const lambda&)>& cache) { +const failable memoize(const list& params, const lvvlambda& relay, const lvvlambda& cache) { debug(params, "memocache::memoize::params"); // Lookup memoized value from cache diff --git a/sca-cpp/trunk/components/cache/partitioner.cpp b/sca-cpp/trunk/components/cache/partitioner.cpp index e3f04ba112..a38c053358 100644 --- a/sca-cpp/trunk/components/cache/partitioner.cpp +++ b/sca-cpp/trunk/components/cache/partitioner.cpp @@ -22,7 +22,7 @@ /** * A partitioner component implementation which forwards data access requests to a * dynamically selected data store component. The selection is externalized, performed - * by a selector component, responsible for selecting the target data store given the + * by a selector component, responsible for selecting the target data stores given the * data access request key and a list of references to available data store components. * This pattern can be used for sharding or load balancing for example. */ @@ -38,54 +38,89 @@ namespace tuscany { namespace partitioner { /** - * Return the target partition for a key. + * Return a list of target partitions for a key. */ -const failable&)> > partition(const value& key, const lambda&)>& selector, const list& partitions) { +const failable > partition(const value& key, const lvvlambda& selector, const list& partitions) { - // Call the selector component to convert the given key to a partition number + // Call the selector component to convert the given key to a list of partitions const value p = selector(mklist("get", key, partitions)); if (isNil(p)) { ostringstream os; - os << "Couldn't get partition number: " << key; - return mkfailure&)> >(str(os), -1, false); + os << "Couldn't get partition: " << key; + return mkfailure >(str(os), -1, false); } - return (const lambda&)>)p; + return (list)p; +} + + +/** + * Get lists of items from a list of partitions. + */ +const failable > getlist(const value& key, const list& partitions) { + if (isNil(partitions)) + return nilListValue; + + const lvvlambda l = car(partitions); + const value val = l(mklist("get", key)); + if (isNil(val)) + return getlist(key, cdr(partitions)); + if (!isList(val)) { + ostringstream os; + os << "Couldn't get list of entries from partition: " << key; + return mkfailure >(str(os), 500, false); + } + + const failable > cdrval = getlist(key, cdr(partitions)); + if (!hasContent(cdrval)) + return cdrval; + + return append((list)val, content(cdrval)); } /** * Get an item from a partition. */ -const failable get(const value& key, const lambda&)>& selector, const list& partitions) { +const failable get(const value& key, const lvvlambda& selector, const list& partitions) { // Select partition - const failable&)> > p = partition(key, selector, partitions); - if (!hasContent(p)) - return mkfailure(p); - - // Get from selected partition - const value val = content(p)(mklist("get", key)); - if (isNil(val)) { - ostringstream os; - os << "Couldn't get entry from partition: " << key; - return mkfailure(str(os), 404, false); + const failable > fp = partition(key, selector, partitions); + if (!hasContent(fp)) + return mkfailure(fp); + const list p = content(fp); + + // Get a single item from the selected partition + if (length(p) == 1) { + const lvvlambda l = car(p); + const value val = l(mklist("get", key)); + if (isNil(val)) { + ostringstream os; + os << "Couldn't get entry from partition: " << key; + return mkfailure(str(os), 404, false); + } + return val; } - return val; + // Get list of items from the list of selected partitions + const failable > val = getlist(key, p); + if (!hasContent(val)) + return mkfailure(val); + return (value)content(val); } /** * Post an item to a partition. */ -const failable post(const value& key, const value& val, const lambda&)>& selector, const list& partitions) { +const failable post(const value& key, const value& val, const lvvlambda& selector, const list& partitions) { const value id = append(key, mklist(mkuuid())); // Select partition - const failable&)> > p = partition(id, selector, partitions); + const failable > p = partition(id, selector, partitions); if (!hasContent(p)) return mkfailure(p); // Put into select partition - content(p)(mklist("put", id, val)); + const lvvlambda l = car(content(p)); + l(mklist("post", id, val)); return id; } @@ -93,33 +128,35 @@ const failable post(const value& key, const value& val, const lambda put(const value& key, const value& val, const lambda&)>& selector, const list& partitions) { +const failable put(const value& key, const value& val, const lvvlambda& selector, const list& partitions) { // Select partition - const failable&)> > p = partition(key, selector, partitions); + const failable > p = partition(key, selector, partitions); if (!hasContent(p)) return mkfailure(p); // Put into selected partition - content(p)(mklist("put", key, val)); + const lvvlambda l = car(content(p)); + l(mklist("put", key, val)); - return value(true); + return trueValue; } /** * Delete an item from a partition. */ -const failable del(const value& key, const lambda&)>& selector, const list& partitions) { +const failable del(const value& key, const lvvlambda& selector, const list& partitions) { // Select partition - const failable&)> > p = partition(key, selector, partitions); + const failable > p = partition(key, selector, partitions); if (!hasContent(p)) return mkfailure(p); // Delete from selected partition - content(p)(mklist("delete", key)); + const lvvlambda l = car(content(p)); + l(mklist("delete", key)); - return value(true); + return trueValue; } } diff --git a/sca-cpp/trunk/components/cache/select-test.scm b/sca-cpp/trunk/components/cache/select-test.scm index 9baa82a5da..f788a6104a 100644 --- a/sca-cpp/trunk/components/cache/select-test.scm +++ b/sca-cpp/trunk/components/cache/select-test.scm @@ -17,5 +17,5 @@ ; Partition selector test case -(define (get key partitions) (if (= (car key) "a") (car partitions) (cadr partitions))) +(define (get key partitions) (if (= (car key) "a") (list (car partitions)) (list (cadr partitions)))) diff --git a/sca-cpp/trunk/components/chat/Makefile.am b/sca-cpp/trunk/components/chat/Makefile.am index 5c995ad452..1efbb5b298 100644 --- a/sca-cpp/trunk/components/chat/Makefile.am +++ b/sca-cpp/trunk/components/chat/Makefile.am @@ -58,7 +58,7 @@ xmpp_test_SOURCES = xmpp-test.cpp xmpp_test_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lssl -lresolv client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lssl -lresolv +client_test_LDFLAGS = -lxml2 -lcurl -ljansson -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lssl -lresolv comp_PROGRAMS = chat-send @@ -67,12 +67,18 @@ dist_noinst_SCRIPTS = server-test if WANT_VYSPER +noinst_DATA += test/TestVysperServer.class + AM_JAVACFLAGS = -cp `${top_builddir}/components/chat/vysper-classpath ${VYSPER_PREFIX}`${JAVAROOT} dist_noinst_JAVA = test/*.java +.java.class: + ${JAVAC} ${AM_JAVACFLAGS} test/*.java + CLEANFILES = test/*.class dist_noinst_SCRIPTS += echo-test -TESTS = echo-test server-test +#TESTS = echo-test server-test + endif endif diff --git a/sca-cpp/trunk/components/chat/chat-send.cpp b/sca-cpp/trunk/components/chat/chat-send.cpp index bb3907acfd..b4c21a49ee 100644 --- a/sca-cpp/trunk/components/chat/chat-send.cpp +++ b/sca-cpp/trunk/components/chat/chat-send.cpp @@ -37,7 +37,7 @@ namespace tuscany { namespace chat { -bool sendmsg(const string& jid, const string& pass, const string& to, const string& msg) { +const bool sendmsg(const string& jid, const string& pass, const string& to, const string& msg) { XMPPClient xc(jid, pass); const failable c = connect(xc); assert(hasContent(c)); @@ -49,7 +49,7 @@ bool sendmsg(const string& jid, const string& pass, const string& to, const stri } } -int main(unused const int argc, const char** argv) { +int main(unused const int argc, const char** const argv) { tuscany::chat::sendmsg(argv[1], argv[2], argv[3], argv[4]); return 0; } diff --git a/sca-cpp/trunk/components/chat/chat-sender.cpp b/sca-cpp/trunk/components/chat/chat-sender.cpp index a4cabef8de..64d0271d43 100644 --- a/sca-cpp/trunk/components/chat/chat-sender.cpp +++ b/sca-cpp/trunk/components/chat/chat-sender.cpp @@ -51,45 +51,38 @@ const failable post(const list& params, XMPPClient& xc) { } /** - * Subscribe and listen to an XMPP session. + * Start the component. */ -class noop { -public: - noop() { - } - - const failable operator()(unused const value& jid, unused const value& val, unused XMPPClient& xc) const { - return true; - } -}; - -class subscribe { -public: - subscribe(XMPPClient& xc) : xc(xc) { - } - - const failable operator()() const { - gc_pool pool; +const failable start(const list& params) { + // Extract the the XMPP JID and password + const list props = params; + const value jid = ((lvvlambda)car(props))(nilListValue); + const value pass = ((lvvlambda)cadr(props))(nilListValue); + + // Create an XMPP client session + XMPPClient xc(jid, pass, false); + const failable r = connect(xc); + if (!hasContent(r)) + return mkfailure(r); + + // Subscribe and listen to XMPP session + const lambda()> subscribe = [xc]() -> const failable { + const gc_pool pool; debug("chat::subscribe::listen"); - const failable r = listen(noop(), const_cast(xc)); + const lambda(const value&, const value&, XMPPClient&)> noop = [](unused const value& jid, unused const value& val, unused XMPPClient& xc) -> const failable { + return true; + }; + const failable r = listen(noop, const_cast(xc)); debug("chat::subscribe::stopped"); return r; - } - -private: - const lambda(const value&, const value&, XMPPClient&)> l; - XMPPClient xc; -}; + }; -/** - * Chatter component lambda function - */ -class chatSender { -public: - chatSender(XMPPClient& xc, worker& w) : xc(xc), w(w) { - } + // Listen and relay messages in a worker thread + worker w(3); + submit >(w, subscribe); - const value operator()(const list& params) const { + // Return the chat sender component lambda function + const lvvlambda chatSender = [xc, w](const list& params) -> const value { const tuscany::value func(car(params)); if (func == "post") return post(cdr(params), const_cast(xc)); @@ -104,35 +97,9 @@ public: cancel(const_cast(w)); debug("chat::sender::stopped"); - return failable(value(lambda&)>())); - } - -private: - const XMPPClient xc; - worker w; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Extract the the XMPP JID and password - const list props = params; - const value jid = ((lambda&)>)car(props))(list()); - const value pass = ((lambda&)>)cadr(props))(list()); - - // Create an XMPP client session - XMPPClient xc(jid, pass, false); - const failable r = connect(xc); - if (!hasContent(r)) - return mkfailure(r); - - // Listen and relay messages in a worker thread - worker w(3); - submit >(w, lambda()>(subscribe(xc))); - - // Return the chat sender component lambda function - return value(lambda&)>(chatSender(xc, w))); + return failable(value(lvvlambda())); + }; + return value(chatSender); } } diff --git a/sca-cpp/trunk/components/chat/chat-sender2.cpp b/sca-cpp/trunk/components/chat/chat-sender2.cpp index 0e00728022..2101617899 100644 --- a/sca-cpp/trunk/components/chat/chat-sender2.cpp +++ b/sca-cpp/trunk/components/chat/chat-sender2.cpp @@ -41,7 +41,7 @@ namespace sender { /** * Post an item to an XMPP JID. */ -const failable post(const lambda&)>& jid, const lambda&)>& pass, const lambda&)>& to, const lambda&)>& msg, const list& params) { +const failable post(const lvvlambda& jid, const lvvlambda& pass, const lvvlambda& to, const lvvlambda& msg, const list& params) { const value vjid = jid(mklist("get", params)); const value vpass = pass(mklist("get", params)); @@ -65,14 +65,16 @@ const failable post(const lambda&)>& jid, const l } /** - * Chat sender component lambda function + * Start the component. */ -class chatSender { -public: - chatSender(const lambda&)>& jid, const lambda&)>& pass, const lambda&)>& to, const lambda&)>& msg) : jid(jid), pass(pass), to(to), msg(msg) { - } +const failable start(const list& params) { - const value operator()(const list& params) const { + // Return the chat sender component lambda function + const lvvlambda jid = car(params); + const lvvlambda pass = cadr(params); + const lvvlambda to = caddr(params); + const lvvlambda msg = cadddr(params); + const lvvlambda sender = [jid, pass, to, msg](const list& params) -> const value { const tuscany::value func(car(params)); if (func == "get") return post(jid, pass, to, msg, cdr(params)); @@ -81,23 +83,9 @@ public: if (func != "stop") return mkfailure(); debug("chat::sender::stop"); - return failable(value(lambda&)>())); - } - -private: - const lambda&)> jid; - const lambda&)> pass; - const lambda&)> to; - const lambda&)> msg; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - - // Return the chat sender component lambda function - return value(lambda&)>(chatSender(car(params), cadr(params), caddr(params), cadddr(params)))); + return failable(value(lvvlambda())); + }; + return value(sender); } } diff --git a/sca-cpp/trunk/components/chat/chat-sendreceiver.cpp b/sca-cpp/trunk/components/chat/chat-sendreceiver.cpp index bfbd32b9ae..94577b7551 100644 --- a/sca-cpp/trunk/components/chat/chat-sendreceiver.cpp +++ b/sca-cpp/trunk/components/chat/chat-sendreceiver.cpp @@ -51,56 +51,46 @@ const failable post(const list& params, XMPPClient& xc) { } /** - * A relay function that posts the XMPP messages it receives to a relay component reference. + * Start the component. */ -class relay { -public: - relay(const lambda&)>& rel) : rel(rel) { - } +const failable start(const list& params) { + // Extract the relay reference and the XMPP JID and password + const bool hasRelay = !isNil(cddr(params)); + const lvvlambda rel = hasRelay? (lvvlambda)car(params) : lvvlambda(); + const list props = hasRelay? cdr(params) : params; + const value jid = ((lvvlambda)car(props))(nilListValue); + const value pass = ((lvvlambda)cadr(props))(nilListValue); + + // Create an XMPP client session + XMPPClient xc(jid, pass, false); + const failable r = connect(xc); + if (!hasContent(r)) + return mkfailure(r); - const failable operator()(const value& jid, const value& val, unused XMPPClient& xc) const { + // Listen and relay messages in a worker thread + worker w(3); + const lambda(const value&, const value&, XMPPClient&)> rl = [rel](const value& jid, const value& val, unused XMPPClient& xc) -> const failable { + // A relay function that posts the XMPP messages it receives to a relay component reference. if (isNil(rel)) return true; debug(jid, "chat::relay::jid"); debug(val, "chat::relay::value"); const value res = rel(mklist("post", mklist(jid), val)); return true; - } - -private: - const lambda&)> rel; -}; - -/** - * Subscribe and listen to an XMPP session. - */ -class subscribe { -public: - subscribe(const lambda(const value&, const value&, XMPPClient&)>& l, XMPPClient& xc) : l(l), xc(xc) { - } + }; - const failable operator()() const { - gc_pool pool; + // Subscribe and listen to the XMPP session. + const lambda()> subscribe = [rl, xc]() -> const failable { + const gc_pool pool; debug("chat::subscribe::listen"); - const failable r = listen(l, const_cast(xc)); + const failable r = listen(rl, const_cast(xc)); debug("chat::subscribe::stopped"); return r; - } - -private: - const lambda(const value&, const value&, XMPPClient&)> l; - XMPPClient xc; -}; - -/** - * Chat sender/receiver component lambda function - */ -class chatSenderReceiver { -public: - chatSenderReceiver(XMPPClient& xc, worker& w) : xc(xc), w(w) { - } + }; + submit >(w, subscribe); - const value operator()(const list& params) const { + // Return the chat sender/receiver component lambda function + const lvvlambda senderReceiver = [xc, w](const list& params) -> const value { const tuscany::value func(car(params)); if (func == "post") return post(cdr(params), const_cast(xc)); @@ -115,38 +105,9 @@ public: cancel(const_cast(w)); debug("chat::sendreceiver::stopped"); - return failable(value(lambda&)>())); - } - -private: - const XMPPClient xc; - worker w; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Extract the relay reference and the XMPP JID and password - const bool hasRelay = !isNil(cddr(params)); - const value rel = hasRelay? car(params) : value(lambda&)>()); - const list props = hasRelay? cdr(params) : params; - const value jid = ((lambda&)>)car(props))(list()); - const value pass = ((lambda&)>)cadr(props))(list()); - - // Create an XMPP client session - XMPPClient xc(jid, pass, false); - const failable r = connect(xc); - if (!hasContent(r)) - return mkfailure(r); - - // Listen and relay messages in a worker thread - worker w(3); - const lambda(const value&, const value&, XMPPClient&)> rl = relay(rel); - submit >(w, lambda()>(subscribe(rl, xc))); - - // Return the chat sender/receiver component lambda function - return value(lambda&)>(chatSenderReceiver(xc, w))); + return failable(value(lvvlambda())); + }; + return value(senderReceiver); } } diff --git a/sca-cpp/trunk/components/chat/client-test.cpp b/sca-cpp/trunk/components/chat/client-test.cpp index 220382fa89..11c7bed35e 100644 --- a/sca-cpp/trunk/components/chat/client-test.cpp +++ b/sca-cpp/trunk/components/chat/client-test.cpp @@ -45,12 +45,12 @@ const value pass2("sca2"); const value jid3("sca3@localhost"); const value pass3("sca3"); -const list item = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); -const list entry = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const list item = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); +const list entry = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + item); worker w(2); @@ -63,36 +63,29 @@ const failable listener(const value& from, const value& val, unused XMPPCl return false; } -struct subscribe { - XMPPClient& xc; - subscribe(XMPPClient& xc) : xc(xc) { - } - const failable operator()() const { - const lambda(const value&, const value&, XMPPClient&)> l(listener); - listen(l, xc); - return true; - } -}; - -bool testListen() { +const bool testListen() { received = false; XMPPClient& xc = *(new (gc_new()) XMPPClient(jid3, pass3)); const failable c = connect(xc); assert(hasContent(c)); - const lambda()> subs = subscribe(xc); + const lambda()> subs = [&xc]() -> const failable { + const lambda(const value&, const value&, XMPPClient&)> l(listener); + listen(l, xc); + return true; + }; submit(w, subs); return true; } -bool testPost() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); +const bool testPost() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); const failable id = http::post(entry, "http://localhost:8090/print-sender/sca2@localhost", ch); assert(hasContent(id)); return true; } -bool testReceived() { +const bool testReceived() { shutdown(w); assert(received == true); return true; diff --git a/sca-cpp/trunk/components/chat/xmpp-test.cpp b/sca-cpp/trunk/components/chat/xmpp-test.cpp index 6b7fa3439f..853029a836 100644 --- a/sca-cpp/trunk/components/chat/xmpp-test.cpp +++ b/sca-cpp/trunk/components/chat/xmpp-test.cpp @@ -52,28 +52,21 @@ const failable listener(const value& from, const value& val, unused XMPPCl return false; } -struct subscribe { - XMPPClient& xc; - subscribe(XMPPClient& xc) : xc(xc) { - } - const failable operator()() const { - const lambda(const value&, const value&, XMPPClient&)> l(listener); - listen(l, xc); - return true; - } -}; - -bool testListen() { +const bool testListen() { received = false; XMPPClient& xc = *(new (gc_new()) XMPPClient(jid2, pass2)); const failable c = connect(xc); assert(hasContent(c)); - const lambda()> subs = subscribe(xc); + const lambda()> subs = [&xc]() -> const failable { + const lambda(const value&, const value&, XMPPClient&)> l(listener); + listen(l, xc); + return true; + }; submit(w, subs); return true; } -bool testPost() { +const bool testPost() { XMPPClient xc(jid1, pass1); const failable c = connect(xc); assert(hasContent(c)); @@ -82,7 +75,7 @@ bool testPost() { return true; } -bool testReceived() { +const bool testReceived() { shutdown(w); assert(received == true); return true; diff --git a/sca-cpp/trunk/components/chat/xmpp.hpp b/sca-cpp/trunk/components/chat/xmpp.hpp index aa006029fa..88174613a0 100644 --- a/sca-cpp/trunk/components/chat/xmpp.hpp +++ b/sca-cpp/trunk/components/chat/xmpp.hpp @@ -66,8 +66,8 @@ private: */ class XMPPClient { public: - XMPPClient(const string& jid, const string& pass, bool owner = true) : owner(owner), ctx(xmpp_ctx_new(NULL, xmppRuntime.log)), conn(xmpp_conn_new(ctx)), connecting(false), connected(false), disconnecting(false) { - xmpp_conn_set_jid(conn, c_str(jid + "/" + mkuuid())); + XMPPClient(const string& jid, const string& pass, const bool owner = true) : owner(owner), ctx(xmpp_ctx_new(NULL, xmppRuntime.log)), conn(xmpp_conn_new(ctx)), connecting(false), connected(false), disconnecting(false) { + xmpp_conn_set_jid(conn, c_str(jid + "/" + (string)mkuuid())); xmpp_conn_set_pass(conn, c_str(pass)); debug(jid, "chat::xmppclient::jid"); } @@ -76,19 +76,7 @@ public: debug("chat::xmppclient::copy"); } - const XMPPClient& operator=(const XMPPClient& xc) { - debug("chat::xmppclient::operator="); - if(this == &xc) - return *this; - owner = false; - ctx = xc.ctx; - conn = xc.conn; - listener = xc.listener; - connecting = xc.connecting; - connected = xc.connected; - disconnecting = xc.disconnecting; - return *this; - } + XMPPClient& operator=(const XMPPClient& xc) = delete; ~XMPPClient() { debug("chat::~xmppclient"); @@ -110,12 +98,12 @@ private: friend const failable send(xmpp_stanza_t* const stanza, XMPPClient& xc); friend const failable post(const value& to, const value& val, XMPPClient& xc); friend const failable disconnect(XMPPClient& xc); - friend const failable listen(const lambda(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc); + friend const failable listen(const lambda(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc); - bool owner; + const bool owner; xmpp_ctx_t* ctx; xmpp_conn_t* conn; - lambda(const value&, const value&, XMPPClient&)> listener; + gc_mutable_ref(const value&, const value&, XMPPClient&)> > listener; bool connecting; bool connected; bool disconnecting; @@ -124,8 +112,8 @@ private: /** * Make a text stanza. */ -xmpp_stanza_t* textStanza(const char* text, xmpp_ctx_t* ctx) { - xmpp_stanza_t* stanza = xmpp_stanza_new(ctx); +xmpp_stanza_t* const textStanza(const char* const text, xmpp_ctx_t* const ctx) { + xmpp_stanza_t* const stanza = xmpp_stanza_new(ctx); xmpp_stanza_set_text(stanza, text); return stanza; } @@ -133,8 +121,8 @@ xmpp_stanza_t* textStanza(const char* text, xmpp_ctx_t* ctx) { /** * Make a named stanza. */ -xmpp_stanza_t* namedStanza(const char* ns, const char* name, xmpp_ctx_t* ctx) { - xmpp_stanza_t* stanza = xmpp_stanza_new(ctx); +xmpp_stanza_t* const namedStanza(const char* const ns, const char* const name, xmpp_ctx_t* const ctx) { + xmpp_stanza_t* const stanza = xmpp_stanza_new(ctx); xmpp_stanza_set_name(stanza, name); if (ns != NULL) xmpp_stanza_set_ns(stanza, ns); @@ -144,8 +132,8 @@ xmpp_stanza_t* namedStanza(const char* ns, const char* name, xmpp_ctx_t* ctx) { /** * Make a named stanza using a qualified name. */ -xmpp_stanza_t* namedStanza(const char* name, xmpp_ctx_t* ctx) { - xmpp_stanza_t* stanza = xmpp_stanza_new(ctx); +xmpp_stanza_t* const namedStanza(const char* const name, xmpp_ctx_t* const ctx) { + xmpp_stanza_t* const stanza = xmpp_stanza_new(ctx); xmpp_stanza_set_name(stanza, name); return stanza; } @@ -157,16 +145,16 @@ int versionHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* c XMPPClient& xc = *(XMPPClient*)udata; // Build version reply stanza - xmpp_stanza_t* reply = namedStanza("iq", xc.ctx); + xmpp_stanza_t* const reply = namedStanza("iq", xc.ctx); xmpp_stanza_set_type(reply, "result"); xmpp_stanza_set_id(reply, xmpp_stanza_get_id(stanza)); xmpp_stanza_set_attribute(reply, "to", xmpp_stanza_get_attribute(stanza, "from")); - xmpp_stanza_t* query = namedStanza(xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)), "query", xc.ctx); + xmpp_stanza_t* const query = namedStanza(xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)), "query", xc.ctx); xmpp_stanza_add_child(reply, query); - xmpp_stanza_t* name = namedStanza("name", xc.ctx); + xmpp_stanza_t* const name = namedStanza("name", xc.ctx); xmpp_stanza_add_child(query, name); xmpp_stanza_add_child(name, textStanza("Apache Tuscany", xc.ctx)); - xmpp_stanza_t* version = namedStanza("version", xc.ctx); + xmpp_stanza_t* const version = namedStanza("version", xc.ctx); xmpp_stanza_add_child(query, version); xmpp_stanza_add_child(version, textStanza("1.0", xc.ctx)); @@ -188,17 +176,18 @@ int messageHandler(unused xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, // Call the client listener function XMPPClient& xc = *(XMPPClient*)udata; - const char* from = xmpp_stanza_get_attribute(stanza, "from"); - const char* text = xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body")); - if (isNil(xc.listener)) + const char* const from = xmpp_stanza_get_attribute(stanza, "from"); + const char* const text = xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body")); + if (isNil((lambda(const value&, const value&, XMPPClient&)>)xc.listener)) return 1; - const value val(scheme::readValue(text)); + const value val(content(scheme::readValue(text))); debug(from, "chat::messageHandler::from"); debug(val, "chat::messageHandler::body"); - const failable r = xc.listener(value(string(from)), val, xc); + const lambda(const value&, const value&, XMPPClient&)> listener = xc.listener; + const failable r = listener(value(string(from)), val, xc); if (!hasContent(r) || !content(r)) { // Stop listening - xc.listener = lambda(const value&, const value&, XMPPClient&)>(); + xc.listener = lambda(const value&, const value&, XMPPClient&)>(); return 0; } return 1; @@ -216,7 +205,7 @@ void connHandler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, unuse xmpp_handler_add(conn, versionHandler, "jabber:iq:version", "iq", NULL, &xc); // Send a stanza so that we appear online to contacts - xmpp_stanza_t* pres = xmpp_stanza_new(xc.ctx); + xmpp_stanza_t* const pres = xmpp_stanza_new(xc.ctx); xmpp_stanza_set_name(pres, "presence"); xmpp_send(conn, pres); xmpp_stanza_release(pres); @@ -246,7 +235,7 @@ const failable connect(XMPPClient& xc) { /** * Send a buffer on an XMPP session. */ -const failable send(const char* data, const size_t len, XMPPClient& xc) { +const failable send(const char* const data, const size_t len, XMPPClient& xc) { if (len == 0) return 0; const size_t written = xc.conn->tls? tls_write(xc.conn->tls, data, len) : sock_write(xc.conn->sock, data, len); @@ -268,7 +257,7 @@ const failable send(const string& data, XMPPClient& xc) { * Send a stanza on an XMPP session. */ const failable send(xmpp_stanza_t* const stanza, XMPPClient& xc) { - char *buf; + char* buf; size_t len; const int rc = xmpp_stanza_to_text(stanza, &buf, &len); if (rc != 0) @@ -291,13 +280,13 @@ const failable post(const value& to, const value& val, XMPPClient& xc) { debug(val, "chat::post::body"); // Convert the value to a string - const string vs(scheme::writeValue(val)); + const string vs(write(content(scheme::writeValue(val)))); // Build message stanza - xmpp_stanza_t* stanza = namedStanza("message", xc.ctx); + xmpp_stanza_t* const stanza = namedStanza("message", xc.ctx); xmpp_stanza_set_type(stanza, "chat"); xmpp_stanza_set_attribute(stanza, "to", c_str(string(to))); - xmpp_stanza_t* body = namedStanza("body", xc.ctx); + xmpp_stanza_t* const body = namedStanza("body", xc.ctx); xmpp_stanza_add_child(stanza, body); xmpp_stanza_add_child(body, textStanza(c_str(vs), xc.ctx)); @@ -323,12 +312,12 @@ const failable disconnect(XMPPClient& xc) { /** * Listen to messages received by an XMPP client. */ -const failable listen(const lambda(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc) { +const failable listen(const lambda(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc) { debug("chat::listen"); xc.listener = listener; xmpp_handler_add(xc.conn, messageHandler, NULL, "message", NULL, &xc); xc.ctx->loop_status = XMPP_LOOP_RUNNING; - while(xc.connected && !isNil(xc.listener) && xc.ctx->loop_status == XMPP_LOOP_RUNNING) + while(xc.connected && !isNil((lambda(const value&, const value&, XMPPClient&)>)xc.listener) && xc.ctx->loop_status == XMPP_LOOP_RUNNING) xmpp_run_once(xc.ctx, 1000L); return true; } diff --git a/sca-cpp/trunk/components/constdb/Makefile.am b/sca-cpp/trunk/components/constdb/Makefile.am index e4504a53e7..a64d13da1c 100644 --- a/sca-cpp/trunk/components/constdb/Makefile.am +++ b/sca-cpp/trunk/components/constdb/Makefile.am @@ -41,7 +41,7 @@ tinycdb_test_SOURCES = tinycdb-test.cpp tinycdb_test_LDFLAGS = -L${TINYCDB_LIB} -R${TINYCDB_LIB} -lcdb client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = constdb-test server-test noinst_PROGRAMS = tinycdb-test client-test diff --git a/sca-cpp/trunk/components/constdb/client-test.cpp b/sca-cpp/trunk/components/constdb/client-test.cpp index ea45762cd6..b796ef01dd 100644 --- a/sca-cpp/trunk/components/constdb/client-test.cpp +++ b/sca-cpp/trunk/components/constdb/client-test.cpp @@ -38,15 +38,15 @@ namespace constdb { const string uri("http://localhost:8090/constdb"); -bool testConstDb() { - http::CURLSession cs("", "", "", "", 0); - - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testConstDb() { + const http::CURLSession cs("", "", "", "", 0); + + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); const failable id = http::post(a, uri, cs); @@ -59,18 +59,18 @@ bool testConstDb() { assert(content(val) == a); } - const list j = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$3.55"))); - const list b = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list j = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$3.55"))); + const list b = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + j); { const failable r = http::put(b, uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable val = http::get(uri + p, cs); @@ -80,7 +80,7 @@ bool testConstDb() { { const failable r = http::del(uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable val = http::get(uri + p, cs); @@ -90,35 +90,26 @@ bool testConstDb() { return true; } -struct getLoop { - const string path; - const value entry; - http::CURLSession& cs; - getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { - } - const bool operator()() const { - const failable val = http::get(uri + path, cs); - assert(hasContent(val)); - assert(content(val) == entry); - return true; - } -}; - -bool testGetPerf() { - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$4.55"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testGetPerf() { + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$4.55"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", "", 0); + const http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); - const lambda gl = getLoop(p, a, cs); + const blambda gl = [p, a, cs]() -> const bool { + const failable val = http::get(uri + p, cs); + assert(hasContent(val)); + assert(content(val) == a); + return true; + }; cout << "ConstDb get test " << time(gl, 5, 200) << " ms" << endl; return true; diff --git a/sca-cpp/trunk/components/constdb/constdb.cpp b/sca-cpp/trunk/components/constdb/constdb.cpp index 6d1cb15baf..a9a5bc5817 100644 --- a/sca-cpp/trunk/components/constdb/constdb.cpp +++ b/sca-cpp/trunk/components/constdb/constdb.cpp @@ -37,14 +37,14 @@ namespace constdb { /** * Get an item from the database. */ -const failable get(const list& params, tinycdb::TinyCDB& cdb) { +const failable get(const list& params, const tinycdb::TinyCDB& cdb) { return tinycdb::get(car(params), cdb); } /** * Post an item to the database. */ -const failable post(const list& params, tinycdb::TinyCDB& cdb) { +const failable post(const list& params, const tinycdb::TinyCDB& cdb) { const value id = append(car(params), mklist(mkuuid())); const failable val = tinycdb::post(id, cadr(params), cdb); if (!hasContent(val)) @@ -55,7 +55,7 @@ const failable post(const list& params, tinycdb::TinyCDB& cdb) { /** * Put an item into the database. */ -const failable put(const list& params, tinycdb::TinyCDB& cdb) { +const failable put(const list& params, const tinycdb::TinyCDB& cdb) { const failable val = tinycdb::put(car(params), cadr(params), cdb); if (!hasContent(val)) return mkfailure(val); @@ -65,7 +65,7 @@ const failable put(const list& params, tinycdb::TinyCDB& cdb) { /** * Delete an item from the database. */ -const failable del(const list& params, tinycdb::TinyCDB& cdb) { +const failable del(const list& params, const tinycdb::TinyCDB& cdb) { const failable val = tinycdb::del(car(params), cdb); if (!hasContent(val)) return mkfailure(val); @@ -73,14 +73,15 @@ const failable del(const list& params, tinycdb::TinyCDB& cdb) { } /** - * Component implementation lambda function. + * Start the component. */ -class applyConstDb { -public: - applyConstDb(tinycdb::TinyCDB& cdb) : cdb(cdb) { - } +const failable start(unused const list& params) { + // Connect to the configured database and table + const value dbname = ((lvvlambda)car(params))(nilListValue); + const tinycdb::TinyCDB& cdb = *(new (gc_new()) tinycdb::TinyCDB(dbname)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda applyConstDb = [cdb](const list& params) -> const value { const value func(car(params)); if (func == "get") return get(cdr(params), cdb); @@ -91,22 +92,8 @@ public: if (func == "delete") return del(cdr(params), cdb); return mkfailure(); - } - -private: - tinycdb::TinyCDB& cdb; -}; - -/** - * Start the component. - */ -const failable start(unused const list& params) { - // Connect to the configured database and table - const value dbname = ((lambda&)>)car(params))(list()); - tinycdb::TinyCDB& cdb = *(new (gc_new()) tinycdb::TinyCDB(dbname)); - - // Return the component implementation lambda function - return value(lambda&)>(applyConstDb(cdb))); + }; + return value(applyConstDb); } } diff --git a/sca-cpp/trunk/components/constdb/tinycdb-test.cpp b/sca-cpp/trunk/components/constdb/tinycdb-test.cpp index b3b4ea7fd7..6cc9e9eabb 100644 --- a/sca-cpp/trunk/components/constdb/tinycdb-test.cpp +++ b/sca-cpp/trunk/components/constdb/tinycdb-test.cpp @@ -32,8 +32,8 @@ namespace tuscany { namespace tinycdb { -bool testTinyCDB() { - TinyCDB cdb("tmp/test.cdb"); +const bool testTinyCDB() { + const TinyCDB cdb("tmp/test.cdb"); const value k = mklist("a"); assert(hasContent(post(k, string("AAA"), cdb))); @@ -46,23 +46,15 @@ bool testTinyCDB() { return true; } -struct getLoop { - const value k; - TinyCDB& cdb; - getLoop(const value& k, TinyCDB& cdb) : k(k), cdb(cdb) { - } - const bool operator()() const { - assert((get(k, cdb)) == value(string("CCC"))); - return true; - } -}; - -bool testGetPerf() { +const bool testGetPerf() { const value k = mklist("c"); - TinyCDB cdb("tmp/test.cdb"); + const TinyCDB cdb("tmp/test.cdb"); assert(hasContent(post(k, string("CCC"), cdb))); - const lambda gl = getLoop(k, cdb); + const blambda gl = [k, cdb]() -> const bool { + assert((get(k, cdb)) == value(string("CCC"))); + return true; + }; cout << "TinyCDB get test " << time(gl, 5, 100000) << " ms" << endl; return true; } diff --git a/sca-cpp/trunk/components/constdb/tinycdb.hpp b/sca-cpp/trunk/components/constdb/tinycdb.hpp index 68be0a09dc..ce1dcbb011 100644 --- a/sca-cpp/trunk/components/constdb/tinycdb.hpp +++ b/sca-cpp/trunk/components/constdb/tinycdb.hpp @@ -41,20 +41,20 @@ namespace tinycdb { */ class buffer { public: - operator void*() const throw() { + operator void* const () const throw() { return buf; } - operator unsigned char*() const throw() { - return (unsigned char*)buf; + operator unsigned char* const () const throw() { + return (unsigned char* const)buf; } - operator char*() const throw() { - return (char*)buf; + operator char* const () const throw() { + return (char* const)buf; } private: - buffer(const unsigned int size, void* buf) : size(size), buf(buf) { + buffer(const unsigned int size, void* const buf) : size(size), buf(buf) { } unsigned int size; @@ -106,48 +106,53 @@ const string absdbname(const string& name) { */ class TinyCDB { public: - TinyCDB() : owner(false), fd(-1) { - st.st_ino = 0; + TinyCDB() : owner(false), h(*(new (gc_new()) handles())) { } - TinyCDB(const string& name) : owner(true), name(absdbname(name)), fd(-1) { + TinyCDB(const string& name) : owner(true), name(absdbname(name)), h(*(new (gc_new()) handles())) { debug(name, "tinycdb::tinycdb::name"); - st.st_ino = 0; } - TinyCDB(const TinyCDB& c) : owner(false), name(c.name), fd(c.fd) { + TinyCDB(const TinyCDB& c) : owner(false), name(c.name), h(c.h) { debug("tinycdb::tinycdb::copy"); - st.st_ino = c.st.st_ino; } - const TinyCDB& operator=(const TinyCDB& c) { - debug("tinycdb::tinycdb::operator="); - if(this == &c) - return *this; - owner = false; - name = c.name; - fd = c.fd; - st.st_ino = c.st.st_ino; - return *this; - } + TinyCDB& operator=(const TinyCDB& c) = delete; ~TinyCDB() { if (!owner) return; - if (fd == -1) + if (h.fd == -1) return; - close(fd); + close(h.fd); } private: + class handles { + public: + handles() : fd(-1) { + st.st_ino = 0; + } + + handles(const handles& c) : fd(c.fd), st(c.st) { + } + + private: + int fd; + struct stat st; + + friend class TinyCDB; + friend const failable cdbopen(const TinyCDB& cdb); + friend const failable cdbclose(const TinyCDB& cdb); + }; + bool owner; string name; - int fd; - struct stat st; + handles& h; friend const string dbname(const TinyCDB& cdb); - friend const failable cdbopen(TinyCDB& cdb); - friend const failable cdbclose(TinyCDB& cdb); + friend const failable cdbopen(const TinyCDB& cdb); + friend const failable cdbclose(const TinyCDB& cdb); }; /** @@ -160,7 +165,7 @@ const string dbname(const TinyCDB& cdb) { /** * Open a database. */ -const failable cdbopen(TinyCDB& cdb) { +const failable cdbopen(const TinyCDB& cdb) { // Get database file serial number struct stat st; @@ -169,51 +174,51 @@ const failable cdbopen(TinyCDB& cdb) { return mkfailure(string("Couldn't tinycdb read database stat: ") + cdb.name); // Open database for the first time - if (cdb.fd == -1) { - cdb.fd = open(c_str(cdb.name), O_RDONLY); - if (cdb.fd == -1) + if (cdb.h.fd == -1) { + cdb.h.fd = open(c_str(cdb.name), O_RDONLY); + if (cdb.h.fd == -1) return mkfailure(string("Couldn't open tinycdb database file: ") + cdb.name); - debug(cdb.fd, "tinycdb::open::fd"); - cdb.st = st; - return cdb.fd; + debug(cdb.h.fd, "tinycdb::open::fd"); + cdb.h.st = st; + return cdb.h.fd; } // Close and reopen database after a change - if (st.st_ino != cdb.st.st_ino) { + if (st.st_ino != cdb.h.st.st_ino) { // Close current fd - close(cdb.fd); + close(cdb.h.fd); // Reopen database const int newfd = open(c_str(cdb.name), O_RDONLY); if (newfd == -1) return mkfailure(string("Couldn't open tinycdb database file: ") + cdb.name); - if (newfd == cdb.fd) { - debug(cdb.fd, "tinycdb::open::fd"); - cdb.st = st; - return cdb.fd; + if (newfd == cdb.h.fd) { + debug(cdb.h.fd, "tinycdb::open::fd"); + cdb.h.st = st; + return cdb.h.fd; } // We got a different fd, dup it to the current fd then close it - if (fcntl(newfd, F_DUPFD, cdb.fd) == -1) + if (fcntl(newfd, F_DUPFD, cdb.h.fd) == -1) return mkfailure(string("Couldn't dup tinycdb database file handle: ") + cdb.name); close(newfd); - debug(cdb.fd, "tinycdb::open::fd"); - cdb.st = st; - return cdb.fd; + debug(cdb.h.fd, "tinycdb::open::fd"); + cdb.h.st = st; + return cdb.h.fd; } // No change, just return the current fd - return cdb.fd; + return cdb.h.fd; } /** * Close a database. */ -const failable cdbclose(TinyCDB& cdb) { - close(cdb.fd); - cdb.fd = -1; +const failable cdbclose(const TinyCDB& cdb) { + close(cdb.h.fd); + cdb.h.fd = -1; return true; } @@ -222,7 +227,7 @@ const failable cdbclose(TinyCDB& cdb) { * can return true to let the entry added to the new db, false to skip the * entry, or a failure. */ -const failable rewrite(const lambda(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda(struct cdb_make&)>& finish, buffer& buf, const int tmpfd, TinyCDB& cdb) { +const failable rewrite(const lambda(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda(struct cdb_make&)>& finish, buffer& buf, const int tmpfd, const TinyCDB& cdb) { // Initialize new db structure struct cdb_make cdbm; @@ -241,7 +246,7 @@ const failable rewrite(const lambda(buffer& buf, const unsi if (::read(fd, buf, 2048) != 2048) return mkfailure("Couldn't read tinycdb database header"); pos += 2048; - unsigned int eod = cdb_unpack(buf); + const unsigned int eod = cdb_unpack(buf); debug(pos, "tinycdb::rewrite::eod"); // Read and add the existing entries @@ -251,9 +256,9 @@ const failable rewrite(const lambda(buffer& buf, const unsi if (::read(fd, buf, 8) != 8) return mkfailure("Couldn't read tinycdb entry header"); pos += 8; - unsigned int klen = cdb_unpack(buf); - unsigned int vlen = cdb_unpack(((unsigned char*)buf) + 4); - unsigned int elen = klen + vlen; + const unsigned int klen = cdb_unpack(buf); + const unsigned int vlen = cdb_unpack(((unsigned char*)buf) + 4); + const unsigned int elen = klen + vlen; // Read existing entry buf = mkbuffer(buf, elen); @@ -264,8 +269,8 @@ const failable rewrite(const lambda(buffer& buf, const unsi pos += elen; // Apply the update function to the entry - debug(string((char*)buf, klen), "tinycdb::rewrite::existing key"); - debug(string(((char*)buf) + klen, vlen), "tinycdb::rewrite::existing value"); + debug(string((const char* const)buf, klen), "tinycdb::rewrite::existing key"); + debug(string(((const char* const)buf) + klen, vlen), "tinycdb::rewrite::existing value"); const failable u = update(buf, klen, vlen); if (!hasContent(u)) return u; @@ -293,11 +298,11 @@ const failable rewrite(const lambda(buffer& buf, const unsi return true; } -const failable rewrite(const lambda(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda(struct cdb_make&)>& finish, TinyCDB& cdb) { +const failable rewrite(const lambda(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda(struct cdb_make&)>& finish, const TinyCDB& cdb) { // Create a new temporary db file - string tmpname = dbname(cdb) + ".XXXXXX"; - int tmpfd = mkstemp(const_cast(c_str(tmpname))); + const string tmpname = dbname(cdb) + ".XXXXXX"; + const int tmpfd = mkstemp(const_cast(c_str(tmpname))); if (tmpfd == -1) return mkfailure("Couldn't create temporary tinycdb database"); @@ -314,7 +319,7 @@ const failable rewrite(const lambda(buffer& buf, const unsi if (rename(c_str(tmpname), c_str(dbname(cdb))) == -1) return mkfailure("Couldn't rename temporary tinycdb database"); cdbclose(cdb); - failable ffd = cdbopen(cdb); + const failable ffd = cdbopen(cdb); if (!hasContent(ffd)) return mkfailure(ffd); @@ -324,42 +329,27 @@ const failable rewrite(const lambda(buffer& buf, const unsi /** * Post a new item to the database. */ -struct postUpdate { - const string ks; - postUpdate(const string& ks) : ks(ks) { - } - const failable operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const { - if (ks == string((char*)buf, klen)) - return mkfailure("Key already exists in tinycdb database"); - return true; - } -}; - -struct postFinish { - const string ks; - const string vs; - postFinish(const string& ks, const string& vs) : ks(ks), vs(vs) { - } - const failable operator()(struct cdb_make& cdbm) const { - if (cdb_make_add(&cdbm, c_str(ks), (unsigned int)length(ks), c_str(vs), (unsigned int)length(vs)) == -1) - return mkfailure(string("Couldn't add tinycdb entry: ") + ks); - return true; - } -}; - -const failable post(const value& key, const value& val, TinyCDB& cdb) { +const failable post(const value& key, const value& val, const TinyCDB& cdb) { debug(key, "tinycdb::post::key"); debug(val, "tinycdb::post::value"); debug(dbname(cdb), "tinycdb::post::dbname"); - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); // Process each entry and detect existing key - const lambda(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = postUpdate(ks); + const lambda(buffer&, const unsigned int, const unsigned int)> update = [ks](buffer& buf, const unsigned int klen, unused const unsigned int vlen) -> const failable { + if (ks == string((char*)buf, klen)) + return mkfailure("Key already exists in tinycdb database"); + return true; + }; // Add the new entry to the db - const lambda(struct cdb_make& cdbm)> finish = postFinish(ks, vs); + const lambda(struct cdb_make&)> finish = [ks, vs](struct cdb_make& cdbm) -> const failable { + if (cdb_make_add(&cdbm, c_str(ks), (unsigned int)length(ks), c_str(vs), (unsigned int)length(vs)) == -1) + return mkfailure(string("Couldn't add tinycdb entry: ") + ks); + return true; + }; // Rewrite the db const failable r = rewrite(update, finish, cdb); @@ -370,42 +360,27 @@ const failable post(const value& key, const value& val, TinyCDB& cdb) { /** * Update an item in the database. If the item doesn't exist it is added. */ -struct putUpdate { - const string ks; - putUpdate(const string& ks) : ks(ks) { - } - const failable operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const { - if (ks == string((char*)buf, klen)) - return false; - return true; - } -}; - -struct putFinish { - const string ks; - const string vs; - putFinish(const string& ks, const string& vs) : ks(ks), vs(vs) { - } - const failable operator()(struct cdb_make& cdbm) const { - if (cdb_make_add(&cdbm, c_str(ks), (unsigned int)length(ks), c_str(vs), (unsigned int)length(vs)) == -1) - return mkfailure(string("Couldn't add tinycdb entry: ") + ks); - return true; - } -}; - -const failable put(const value& key, const value& val, TinyCDB& cdb) { +const failable put(const value& key, const value& val, const TinyCDB& cdb) { debug(key, "tinycdb::put::key"); debug(val, "tinycdb::put::value"); debug(dbname(cdb), "tinycdb::put::dbname"); - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); // Process each entry and skip existing key - const lambda(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = putUpdate(ks); + const lambda(buffer&, const unsigned int, const unsigned int)> update = [ks](buffer& buf, const unsigned int klen, unused const unsigned int vlen) -> const failable { + if (ks == string((char*)buf, klen)) + return false; + return true; + }; // Add the new entry to the db - const lambda(struct cdb_make& cdbm)> finish = putFinish(ks, vs); + const lambda(struct cdb_make&)> finish = [ks, vs](struct cdb_make& cdbm) -> const failable { + if (cdb_make_add(&cdbm, c_str(ks), (unsigned int)length(ks), c_str(vs), (unsigned int)length(vs)) == -1) + return mkfailure(string("Couldn't add tinycdb entry: ") + ks); + return true; + }; // Rewrite the db const failable r = rewrite(update, finish, cdb); @@ -416,7 +391,7 @@ const failable put(const value& key, const value& val, TinyCDB& cdb) { /** * Get an item from the database. */ -const failable get(const value& key, TinyCDB& cdb) { +const failable get(const value& key, const TinyCDB& cdb) { debug(key, "tinycdb::get::key"); debug(dbname(cdb), "tinycdb::get::dbname"); @@ -425,7 +400,7 @@ const failable get(const value& key, TinyCDB& cdb) { return mkfailure(ffd); const int fd = content(ffd); - const string ks(scheme::writeValue(key)); + const string ks(write(content(scheme::writeValue(key)))); cdbi_t vlen; if (cdb_seek(fd, c_str(ks), (unsigned int)length(ks), &vlen) <= 0) { @@ -433,10 +408,10 @@ const failable get(const value& key, TinyCDB& cdb) { os << "Couldn't get tinycdb entry: " << key; return mkfailure(str(os), 404, false); } - char* data = gc_cnew(vlen + 1); + char* const data = gc_cnew(vlen + 1); cdb_bread(fd, data, vlen); data[vlen] = '\0'; - const value val(scheme::readValue(string(data))); + const value val(content(scheme::readValue(string(data)))); debug(val, "tinycdb::get::result"); return val; @@ -445,36 +420,23 @@ const failable get(const value& key, TinyCDB& cdb) { /** * Delete an item from the database */ -struct delUpdate { - const string ks; - delUpdate(const string& ks) : ks(ks) { - } - const failable operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const { - if (ks == string((char*)buf, klen)) - return false; - return true; - } -}; - -struct delFinish { - delFinish() { - } - const failable operator()(unused struct cdb_make& cdbm) const { - return true; - } -}; - -const failable del(const value& key, TinyCDB& cdb) { +const failable del(const value& key, const TinyCDB& cdb) { debug(key, "tinycdb::delete::key"); debug(dbname(cdb), "tinycdb::delete::dbname"); - const string ks(scheme::writeValue(key)); + const string ks(write(content(scheme::writeValue(key)))); // Process each entry and skip existing key - const lambda(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = delUpdate(ks); + const lambda(buffer&, const unsigned int, const unsigned int)> update = [ks](buffer& buf, const unsigned int klen, unused const unsigned int vlen) -> const failable { + if (ks == string((char*)buf, klen)) + return false; + return true; + }; // Nothing to do to finish - const lambda(struct cdb_make& cdbm)> finish = delFinish(); + const lambda(struct cdb_make&)> finish = [](unused struct cdb_make& cdbm) -> const failable { + return true; + }; // Rewrite the db const failable r = rewrite(update, finish, cdb); diff --git a/sca-cpp/trunk/components/filedb/Makefile.am b/sca-cpp/trunk/components/filedb/Makefile.am index c6589a1b7b..e15eb2002e 100644 --- a/sca-cpp/trunk/components/filedb/Makefile.am +++ b/sca-cpp/trunk/components/filedb/Makefile.am @@ -26,15 +26,15 @@ comp_LTLIBRARIES = libfiledb.la noinst_DATA = libfiledb${libsuffix} libfiledb_la_SOURCES = filedb.cpp -libfiledb_la_LDFLAGS = -lxml2 -lmozjs +libfiledb_la_LDFLAGS = -lxml2 -ljansson libfiledb${libsuffix}: ln -s .libs/libfiledb${libsuffix} file_test_SOURCES = file-test.cpp -file_test_LDFLAGS = -lxml2 -lmozjs +file_test_LDFLAGS = -lxml2 -ljansson client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = filedb-test server-test noinst_PROGRAMS = file-test client-test diff --git a/sca-cpp/trunk/components/filedb/client-test.cpp b/sca-cpp/trunk/components/filedb/client-test.cpp index e0f98d8c3b..5694d97522 100644 --- a/sca-cpp/trunk/components/filedb/client-test.cpp +++ b/sca-cpp/trunk/components/filedb/client-test.cpp @@ -38,15 +38,15 @@ namespace filedb { const string uri("http://localhost:8090/filedb"); -bool testFileDB() { - http::CURLSession cs("", "", "", "", 0); - - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testFileDB() { + const http::CURLSession cs("", "", "", "", 0); + + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); const failable id = http::post(a, uri, cs); @@ -59,18 +59,18 @@ bool testFileDB() { assert(content(val) == a); } - const list j = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$3.55"))); - const list b = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list j = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$3.55"))); + const list b = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + j); { const failable r = http::put(b, uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable val = http::get(uri + p, cs); @@ -80,7 +80,7 @@ bool testFileDB() { { const failable r = http::del(uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable val = http::get(uri + p, cs); @@ -90,35 +90,26 @@ bool testFileDB() { return true; } -struct getLoop { - const string path; - const value entry; - http::CURLSession& cs; - getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { - } - const bool operator()() const { - const failable val = http::get(uri + path, cs); - assert(hasContent(val)); - assert(content(val) == entry); - return true; - } -}; - -bool testGetPerf() { - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$4.55"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testGetPerf() { + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$4.55"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", "", 0); + const http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); - const lambda gl = getLoop(p, a, cs); + const blambda gl = [p, a, cs]() -> const bool { + const failable val = http::get(uri + p, cs); + assert(hasContent(val)); + assert(content(val) == a); + return true; + }; cout << "FileDB get test " << time(gl, 5, 200) << " ms" << endl; return true; diff --git a/sca-cpp/trunk/components/filedb/file-test.cpp b/sca-cpp/trunk/components/filedb/file-test.cpp index ff57bd79ce..5270967ccb 100644 --- a/sca-cpp/trunk/components/filedb/file-test.cpp +++ b/sca-cpp/trunk/components/filedb/file-test.cpp @@ -32,12 +32,12 @@ namespace tuscany { namespace filedb { -bool testFileDB(const string& dbname, const string& format) { - FileDB db(dbname, format); +const bool testFileDB(const string& dbname, const string& format) { + const FileDB db(dbname, format); const value k = mklist("a", "b"); - const list a = mklist(list() + "ns1:a" + (list() + "@xmlns:ns1" + string("http://aaa")) + (list() + "text" + string("Hey!"))); - const list b = mklist(list() + "ns1:b" + (list() + "@xmlns:ns1" + string("http://bbb")) + (list() + "text" + string("Hey!"))); + const list a = mklist(nilListValue + "ns1:a" + (nilListValue + "@xmlns:ns1" + string("http://aaa")) + (nilListValue + "text" + string("Hey!"))); + const list b = mklist(nilListValue + "ns1:b" + (nilListValue + "@xmlns:ns1" + string("http://bbb")) + (nilListValue + "text" + string("Hey!"))); assert(hasContent(post(k, a, db))); assert((get(k, db)) == value(a)); @@ -50,27 +50,17 @@ bool testFileDB(const string& dbname, const string& format) { return true; } -struct getLoop { - const value k; - FileDB& db; - const list c; - getLoop(const value& k, FileDB& db) : k(k), db(db), - c(mklist(list() + "ns1:c" + (list() + "@xmlns:ns1" + string("http://ccc")) + (list() + "text" + string("Hey!")))) { - } - const bool operator()() const { - assert((get(k, db)) == value(c)); - return true; - } -}; - -bool testGetPerf(const string& dbname, const string& format) { - FileDB db(dbname, format); +const bool testGetPerf(const string& dbname, const string& format) { + const FileDB db(dbname, format); const value k = mklist("c"); - const list c = mklist(list() + "ns1:c" + (list() + "@xmlns:ns1" + string("http://ccc")) + (list() + "text" + string("Hey!"))); + const list c = mklist(nilListValue + "ns1:c" + (nilListValue + "@xmlns:ns1" + string("http://ccc")) + (nilListValue + "text" + string("Hey!"))); assert(hasContent(post(k, c, db))); - const lambda gl = getLoop(k, db); + const blambda gl = [k, c, db]() -> const bool { + assert((get(k, db)) == value(c)); + return true; + }; cout << "FileDB get test " << time(gl, 5, 5000) << " ms" << endl; return true; } diff --git a/sca-cpp/trunk/components/filedb/filedb.cpp b/sca-cpp/trunk/components/filedb/filedb.cpp index 8644a78574..37cb6c5260 100644 --- a/sca-cpp/trunk/components/filedb/filedb.cpp +++ b/sca-cpp/trunk/components/filedb/filedb.cpp @@ -37,14 +37,14 @@ namespace filedb { /** * Get an item from the database. */ -const failable get(const list& params, filedb::FileDB& db) { +const failable get(const list& params, const filedb::FileDB& db) { return filedb::get(car(params), db); } /** * Post an item to the database. */ -const failable post(const list& params, filedb::FileDB& db) { +const failable post(const list& params, const filedb::FileDB& db) { const value id = append(car(params), mklist(mkuuid())); const failable val = filedb::post(id, cadr(params), db); if (!hasContent(val)) @@ -55,7 +55,7 @@ const failable post(const list& params, filedb::FileDB& db) { /** * Put an item into the database. */ -const failable put(const list& params, filedb::FileDB& db) { +const failable put(const list& params, const filedb::FileDB& db) { const failable val = filedb::put(car(params), cadr(params), db); if (!hasContent(val)) return mkfailure(val); @@ -65,7 +65,7 @@ const failable put(const list& params, filedb::FileDB& db) { /** * Delete an item from the database. */ -const failable del(const list& params, filedb::FileDB& db) { +const failable del(const list& params, const filedb::FileDB& db) { const failable val = filedb::del(car(params), db); if (!hasContent(val)) return mkfailure(val); @@ -73,14 +73,17 @@ const failable del(const list& params, filedb::FileDB& db) { } /** - * Component implementation lambda function. + * Start the component. */ -class applyfiledb { -public: - applyfiledb(filedb::FileDB& db) : db(db) { - } +const failable start(const list& params) { + // Connect to the configured database and table + const value dbname = ((lvvlambda)car(params))(nilListValue); + const value format = ((lvvlambda)cadr(params))(nilListValue); + + const filedb::FileDB& db = *(new (gc_new()) filedb::FileDB(absdbname(dbname), format)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda applyfiledb = [db](const list& params) -> const value { const value func(car(params)); if (func == "get") return get(cdr(params), db); @@ -91,24 +94,8 @@ public: if (func == "delete") return del(cdr(params), db); return mkfailure(); - } - -private: - filedb::FileDB& db; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Connect to the configured database and table - const value dbname = ((lambda&)>)car(params))(list()); - const value format = ((lambda&)>)cadr(params))(list()); - - filedb::FileDB& db = *(new (gc_new()) filedb::FileDB(absdbname(dbname), format)); - - // Return the component implementation lambda function - return value(lambda&)>(applyfiledb(db))); + }; + return value(applyfiledb); } } diff --git a/sca-cpp/trunk/components/filedb/filedb.hpp b/sca-cpp/trunk/components/filedb/filedb.hpp index 9c3017d0d8..2855cebfc6 100644 --- a/sca-cpp/trunk/components/filedb/filedb.hpp +++ b/sca-cpp/trunk/components/filedb/filedb.hpp @@ -32,8 +32,8 @@ #include "monad.hpp" #include "fstream.hpp" #include "element.hpp" -#include "xml.hpp" #include "../../modules/scheme/eval.hpp" +#include "../../modules/xml/xml.hpp" #include "../../modules/json/json.hpp" namespace tuscany { @@ -68,30 +68,22 @@ public: debug("filedb::filedb::copy"); } - const FileDB& operator=(const FileDB& c) { - debug("filedb::filedb::operator="); - if(this == &c) - return *this; - owner = false; - name = c.name; - format = c.format; - return *this; - } + FileDB& operator=(const FileDB& c) = delete; ~FileDB() { } private: - bool owner; - string name; - string format; + const bool owner; + const string name; + const string format; friend const failable write(const value& v, ostream& os, const string& format); friend const failable read(istream& is, const string& format); - friend const failable post(const value& key, const value& val, FileDB& db); - friend const failable put(const value& key, const value& val, FileDB& db); - friend const failable get(const value& key, FileDB& db); - friend const failable del(const value& key, FileDB& db); + friend const failable post(const value& key, const value& val, const FileDB& db); + friend const failable put(const value& key, const value& val, const FileDB& db); + friend const failable get(const value& key, const FileDB& db); + friend const failable del(const value& key, const FileDB& db); }; /** @@ -100,7 +92,7 @@ private: const string filename(const list& path, const string& root) { if (isNil(path)) return root; - const string name = root + "/" + (isString(car(path))? (string)car(path) : scheme::writeValue(car(path))); + const string name = root + "/" + (isString(car(path))? (string)car(path) : write(content(scheme::writeValue(car(path))))); return filename(cdr(path), name); } @@ -116,7 +108,7 @@ const string filename(const value& key, const string& root) { const failable mkdirs(const list& path, const string& root) { if (isNil(cdr(path))) return true; - const string dir = root + "/" + (isString(car(path))? (string)car(path) : scheme::writeValue(car(path))); + const string dir = root + "/" + (isString(car(path))? (string)car(path) : write(content(scheme::writeValue(car(path))))); mkdir(c_str(dir), S_IRWXU); return mkdirs(cdr(path), dir); } @@ -126,20 +118,19 @@ const failable mkdirs(const list& path, const string& root) { */ const failable write(const value& v, ostream& os, const string& format) { if (format == "scheme") { - const string vs(scheme::writeValue(v)); + const string vs(write(content(scheme::writeValue(v)))); os << vs; return true; } if (format == "xml") { - failable > s = writeXML(valuesToElements(v)); + failable > s = xml::writeElements(valuesToElements(v)); if (!hasContent(s)) return mkfailure(s); write(content(s), os); return true; } if (format == "json") { - js::JSContext jscx; - failable > s = json::writeJSON(valuesToElements(v), jscx); + failable > s = json::writeValue(v); if (!hasContent(s)) return mkfailure(s); write(content(s), os); @@ -153,27 +144,25 @@ const failable write(const value& v, ostream& os, const string& format) { */ const failable read(istream& is, const string& format) { if (format == "scheme") { - return scheme::readValue(is); + return scheme::readValue(streamList(is)); } if (format == "xml") { - const value v = elementsToValues(readXML(streamList(is))); - return v; - } - if (format == "json") { - js::JSContext jscx; - const failable > fv = json::readJSON(streamList(is), jscx); + const failable > fv = xml::readElements(streamList(is)); if (!hasContent(fv)) return mkfailure(fv); const value v = elementsToValues(content(fv)); return v; } + if (format == "json") { + return json::readValue(streamList(is)); + } return mkfailure(string("Unsupported database format: ") + format); } /** * Post a new item to the database. */ -const failable post(const value& key, const value& val, FileDB& db) { +const failable post(const value& key, const value& val, const FileDB& db) { debug(key, "filedb::post::key"); debug(val, "filedb::post::value"); debug(db.name, "filedb::post::dbname"); @@ -197,7 +186,7 @@ const failable post(const value& key, const value& val, FileDB& db) { /** * Update an item in the database. If the item doesn't exist it is added. */ -const failable put(const value& key, const value& val, FileDB& db) { +const failable put(const value& key, const value& val, const FileDB& db) { debug(key, "filedb::put::key"); debug(val, "filedb::put::value"); debug(db.name, "filedb::put::dbname"); @@ -221,7 +210,7 @@ const failable put(const value& key, const value& val, FileDB& db) { /** * Get an item from the database. */ -const failable get(const value& key, FileDB& db) { +const failable get(const value& key, const FileDB& db) { debug(key, "filedb::get::key"); debug(db.name, "filedb::get::dbname"); @@ -242,7 +231,7 @@ const failable get(const value& key, FileDB& db) { /** * Delete an item from the database */ -const failable del(const value& key, FileDB& db) { +const failable del(const value& key, const FileDB& db) { debug(key, "filedb::delete::key"); debug(db.name, "filedb::delete::dbname"); diff --git a/sca-cpp/trunk/components/http/Makefile.am b/sca-cpp/trunk/components/http/Makefile.am index 623be12298..078a7eeae6 100644 --- a/sca-cpp/trunk/components/http/Makefile.am +++ b/sca-cpp/trunk/components/http/Makefile.am @@ -23,32 +23,32 @@ comp_LTLIBRARIES = libhttpget.la libhttpdelete.la libhttppost.la libhttpput.la l noinst_DATA = libhttpget${libsuffix} libhttpdelete${libsuffix} libhttppost${libsuffix} libhttpput${libsuffix} libhttppatch${libsuffix} libhttpget_la_SOURCES = httpget.cpp -libhttpget_la_LDFLAGS = -lxml2 -lmozjs -curl +libhttpget_la_LDFLAGS = -lxml2 -ljansson -curl libhttpget${libsuffix}: ln -s .libs/libhttpget${libsuffix} libhttpdelete_la_SOURCES = httpdelete.cpp -libhttpdelete_la_LDFLAGS = -lxml2 -lmozjs -curl +libhttpdelete_la_LDFLAGS = -lxml2 -ljansson -curl libhttpdelete${libsuffix}: ln -s .libs/libhttpdelete${libsuffix} libhttppost_la_SOURCES = httppost.cpp -libhttppost_la_LDFLAGS = -lxml2 -lmozjs -curl +libhttppost_la_LDFLAGS = -lxml2 -ljansson -curl libhttppost${libsuffix}: ln -s .libs/libhttppost${libsuffix} libhttpput_la_SOURCES = httpput.cpp -libhttpput_la_LDFLAGS = -lxml2 -lmozjs -curl +libhttpput_la_LDFLAGS = -lxml2 -ljansson -curl libhttpput${libsuffix}: ln -s .libs/libhttpput${libsuffix} libhttppatch_la_SOURCES = httppatch.cpp -libhttppatch_la_LDFLAGS = -lxml2 -lmozjs -curl +libhttppatch_la_LDFLAGS = -lxml2 -ljansson -curl libhttppatch${libsuffix}: ln -s .libs/libhttppatch${libsuffix} client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = server-test noinst_PROGRAMS = client-test diff --git a/sca-cpp/trunk/components/http/client-test.cpp b/sca-cpp/trunk/components/http/client-test.cpp index bb1918f1f8..42d7cd76c0 100644 --- a/sca-cpp/trunk/components/http/client-test.cpp +++ b/sca-cpp/trunk/components/http/client-test.cpp @@ -41,52 +41,45 @@ const string postURI("http://localhost:8090/httppost"); const string putURI("http://localhost:8090/httpput"); const string deleteURI("http://localhost:8090/httpdelete"); -bool testGet() { - http::CURLSession cs("", "", "", "", 0); +const bool testGet() { + const http::CURLSession cs("", "", "", "", 0); const failable val = http::get(getURI, cs); assert(hasContent(val)); return true; } -struct getLoop { - http::CURLSession& cs; - getLoop(http::CURLSession& cs) : cs(cs) { - } - const bool operator()() const { +const bool testGetPerf() { + const http::CURLSession cs("", "", "", "", 0); + + const blambda gl = [cs]() -> const bool { const failable val = http::get(getURI, cs); assert(hasContent(val)); return true; - } -}; - -bool testGetPerf() { - http::CURLSession cs("", "", "", "", 0); - - const lambda gl = getLoop(cs); + }; cout << "HTTP get test " << time(gl, 5, 200) << " ms" << endl; return true; } -bool testPost() { - http::CURLSession cs("", "", "", "", 0); +const bool testPost() { + const http::CURLSession cs("", "", "", "", 0); const failable val = http::get(postURI, cs); assert(hasContent(val)); return true; } -bool testPut() { - http::CURLSession cs("", "", "", "", 0); +const bool testPut() { + const http::CURLSession cs("", "", "", "", 0); const failable val = http::get(putURI, cs); assert(hasContent(val)); return true; } -bool testDelete() { - http::CURLSession cs("", "", "", "", 0); +const bool testDelete() { + const http::CURLSession cs("", "", "", "", 0); const failable val = http::get(deleteURI, cs); assert(hasContent(val)); diff --git a/sca-cpp/trunk/components/http/httpdelete.cpp b/sca-cpp/trunk/components/http/httpdelete.cpp index c725461ec2..a23d2a411d 100644 --- a/sca-cpp/trunk/components/http/httpdelete.cpp +++ b/sca-cpp/trunk/components/http/httpdelete.cpp @@ -37,58 +37,37 @@ namespace httpdelete { /** * Evaluate an HTTP delete. */ -const failable get(const lambda&)>& url, http::CURLSession& ch) { +const failable get(const lvvlambda& url, const http::CURLSession& ch) { debug("httpdelete::get"); - const value u = url(mklist("get", list())); + const value u = url(mklist("get", nilListValue)); debug(u, "httpdelete::get::url"); return http::del(u, ch); } /** - * Component implementation lambda function. + * Start the component. */ -class applyhttp { -public: - applyhttp(const lambda&)>& url, const perthread_ptr& ch) : url(url), ch(ch) { - } +const failable start(const list& params) { + // Create a CURL session + const lvvlambda timeout = cadr(params); + const gc_pool cp(gc_current_pool()); + const lambda()> newsession = [timeout, cp]() -> const gc_ptr { + const gc_scoped_pool sp(pool(cp)); + const int t = atoi(c_str((string)timeout(nilListValue))); + return new (gc_new()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t); + }; + const perthread_ptr ch = *(new (gc_new >()) perthread_ptr(newsession)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda url = car(params); + const lvvlambda applyhttp = [url, ch](const list& params) -> const value { debug(params, "httpdelete::applyhttp::params"); const value func(car(params)); if (func == "get") return get(url, *ch); return mkfailure(); - } - -private: - const lambda&)> url; - perthread_ptr ch; -}; - -/** - * Create a new CURL session. - */ -class newsession { -public: - newsession(const lambda&)>& timeout) : timeout(timeout) { - } - const gc_ptr operator()() const { - const int t = atoi(c_str((string)timeout(list()))); - return new (gc_new()) http::CURLSession("", "", "", "", t); - } -private: - const lambda&)> timeout; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession(cadr(params)))); - - // Return the component implementation lambda function - return value(lambda&)>(applyhttp(car(params), ch))); + }; + return value(applyhttp); } } diff --git a/sca-cpp/trunk/components/http/httpget.cpp b/sca-cpp/trunk/components/http/httpget.cpp index 884dc1a6ff..b4504d939a 100644 --- a/sca-cpp/trunk/components/http/httpget.cpp +++ b/sca-cpp/trunk/components/http/httpget.cpp @@ -38,59 +38,37 @@ namespace httpget { /** * Evaluate an HTTP get. */ -const failable get(const lambda&)>& url, http::CURLSession& ch) { +const failable get(const lvvlambda& url, const http::CURLSession& ch) { debug("httpget::get"); - const value u = url(mklist("get", list())); + const value u = url(mklist("get", nilListValue)); debug(u, "httpget::get::url"); return http::get(u, ch); } /** - * Component implementation lambda function. + * Start the component. */ -class applyhttp { -public: - applyhttp(const lambda&)>& url, const perthread_ptr& ch) : url(url), ch(ch) { - } +const failable start(const list& params) { + // Create a CURL session + const lvvlambda timeout = cadr(params); + const gc_pool cp(gc_current_pool()); + const lambda()> newsession = [timeout, cp]() -> const gc_ptr { + const gc_scoped_pool sp(pool(cp)); + const int t = atoi(c_str((string)timeout(nilListValue))); + return new (gc_new()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t); + }; + const perthread_ptr ch = *(new (gc_new >()) perthread_ptr(newsession)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda url = car(params); + const lvvlambda applyhttp = [url, ch](const list& params) -> const value { debug(params, "httpget::applyhttp::params"); const value func(car(params)); if (func == "get") return get(url, *ch); return mkfailure(); - } - -private: - const lambda&)> url; - perthread_ptr ch; -}; - - -/** - * Create a new CURL session. - */ -class newsession { -public: - newsession(const lambda&)>& timeout) : timeout(timeout) { - } - const gc_ptr operator()() const { - const int t = atoi(c_str((string)timeout(list()))); - return new (gc_new()) http::CURLSession("", "", "", "", t); - } -private: - const lambda&)> timeout; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession(cadr(params)))); - - // Return the component implementation lambda function - return value(lambda&)>(applyhttp(car(params), ch))); + }; + return value(applyhttp); } } diff --git a/sca-cpp/trunk/components/http/httppatch.cpp b/sca-cpp/trunk/components/http/httppatch.cpp index 051b1e09ac..4d93249fad 100644 --- a/sca-cpp/trunk/components/http/httppatch.cpp +++ b/sca-cpp/trunk/components/http/httppatch.cpp @@ -38,61 +38,40 @@ namespace httppatch { /** * Evaluate an HTTP patch. */ -const failable get(const lambda&)>& url, const lambda&)>& val, http::CURLSession& ch) { +const failable get(const lvvlambda& url, const lvvlambda& val, const http::CURLSession& ch) { debug("httppatch::get"); - const value u = url(mklist("get", list())); - const value v = val(mklist("get", list())); + const value u = url(mklist("get", nilListValue)); + const value v = val(mklist("get", nilListValue)); debug(u, "httppatch::get::url"); debug(v, "httppatch::get::val"); return http::patch(v, u, ch); } /** - * Component implementation lambda function. + * Start the component. */ -class applyhttp { -public: - applyhttp(const lambda&)>& url, const lambda&)>& val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { - } +const failable start(const list& params) { + // Create a CURL session + const lvvlambda timeout = caddr(params); + const gc_pool cp(gc_current_pool()); + const lambda()> newsession = [timeout, cp]() -> const gc_ptr { + const gc_scoped_pool sp(pool(cp)); + const int t = atoi(c_str((string)timeout(nilListValue))); + return new (gc_new()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t); + }; + const perthread_ptr ch = *(new (gc_new >()) perthread_ptr(newsession)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda url = car(params); + const lvvlambda val = cadr(params); + const lvvlambda applyhttp = [url, val, ch](const list& params) -> const value { debug(params, "httppatch::applyhttp::params"); const value func(car(params)); if (func == "get") return get(url, val, *ch); return mkfailure(); - } - -private: - const lambda&)> url; - const lambda&)> val; - perthread_ptr ch; -}; - -/** - * Create a new CURL session. - */ -class newsession { -public: - newsession(const lambda&)>& timeout) : timeout(timeout) { - } - const gc_ptr operator()() const { - const int t = atoi(c_str((string)timeout(list()))); - return new (gc_new()) http::CURLSession("", "", "", "", t); - } -private: - const lambda&)> timeout; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession(caddr(params)))); - - // Return the component implementation lambda function - return value(lambda&)>(applyhttp(car(params), cadr(params), ch))); + }; + return value(applyhttp); } } diff --git a/sca-cpp/trunk/components/http/httppost.cpp b/sca-cpp/trunk/components/http/httppost.cpp index 84fd984e19..99928a2687 100644 --- a/sca-cpp/trunk/components/http/httppost.cpp +++ b/sca-cpp/trunk/components/http/httppost.cpp @@ -38,61 +38,40 @@ namespace httppost { /** * Evaluate an HTTP post. */ -const failable get(const lambda&)>& url, const lambda&)>& val, http::CURLSession& ch) { +const failable get(const lvvlambda& url, const lvvlambda& val, const http::CURLSession& ch) { debug("httppost::get"); - const value u = url(mklist("get", list())); - const value v = val(mklist("get", list())); + const value u = url(mklist("get", nilListValue)); + const value v = val(mklist("get", nilListValue)); debug(u, "httppost::get::url"); debug(v, "httppost::get::val"); return http::post(v, u, ch); } /** - * Component implementation lambda function. + * Start the component. */ -class applyhttp { -public: - applyhttp(const lambda&)>& url, const lambda&)>& val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { - } +const failable start(const list& params) { + // Create a CURL session + const lvvlambda timeout = caddr(params); + const gc_pool cp(gc_current_pool()); + const lambda()> newsession = [timeout, cp]() -> const gc_ptr { + const gc_scoped_pool sp(pool(cp)); + const int t = atoi(c_str((string)timeout(nilListValue))); + return new (gc_new()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t); + }; + const perthread_ptr ch = *(new (gc_new >()) perthread_ptr(newsession)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda url = car(params); + const lvvlambda val = cadr(params); + const lvvlambda applyhttp = [url, val, ch](const list& params) -> const value { debug(params, "httppost::applyhttp::params"); const value func(car(params)); if (func == "get") return get(url, val, *ch); return mkfailure(); - } - -private: - const lambda&)> url; - const lambda&)> val; - perthread_ptr ch; -}; - -/** - * Create a new CURL session. - */ -class newsession { -public: - newsession(const lambda&)>& timeout) : timeout(timeout) { - } - const gc_ptr operator()() const { - const int t = atoi(c_str((string)timeout(list()))); - return new (gc_new()) http::CURLSession("", "", "", "", t); - } -private: - const lambda&)> timeout; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession(caddr(params)))); - - // Return the component implementation lambda function - return value(lambda&)>(applyhttp(car(params), cadr(params), ch))); + }; + return value(applyhttp); } } diff --git a/sca-cpp/trunk/components/http/httpput.cpp b/sca-cpp/trunk/components/http/httpput.cpp index 2ae5da396e..8f8e2bc168 100644 --- a/sca-cpp/trunk/components/http/httpput.cpp +++ b/sca-cpp/trunk/components/http/httpput.cpp @@ -38,61 +38,40 @@ namespace httpput { /** * Evaluate an HTTP put. */ -const failable get(const lambda&)>& url, const lambda&)>& val, http::CURLSession& ch) { +const failable get(const lvvlambda& url, const lvvlambda& val, const http::CURLSession& ch) { debug("httpput::get"); - const value u = url(mklist("get", list())); - const value v = val(mklist("get", list())); + const value u = url(mklist("get", nilListValue)); + const value v = val(mklist("get", nilListValue)); debug(u, "httpput::get::url"); debug(v, "httpput::get::val"); return http::put(v, u, ch); } /** - * Component implementation lambda function. + * Start the component. */ -class applyhttp { -public: - applyhttp(const lambda&)>& url, const lambda&)>& val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { - } +const failable start(const list& params) { + // Create a CURL session + const lvvlambda timeout = caddr(params); + const gc_pool cp(gc_current_pool()); + const lambda()> newsession = [timeout, cp]() -> const gc_ptr { + const gc_scoped_pool sp(pool(cp)); + const int t = atoi(c_str((string)timeout(nilListValue))); + return new (gc_new()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t); + }; + const perthread_ptr ch = *(new (gc_new >()) perthread_ptr(newsession)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda url = car(params); + const lvvlambda val = cadr(params); + const lvvlambda applyhttp = [url, val, ch](const list& params) -> const value { debug(params, "httpput::applyhttp::params"); const value func(car(params)); if (func == "get") return get(url, val, *ch); return mkfailure(); - } - -private: - const lambda&)> url; - const lambda&)> val; - perthread_ptr ch; -}; - -/** - * Create a new CURL session. - */ -class newsession { -public: - newsession(const lambda&)>& timeout) : timeout(timeout) { - } - const gc_ptr operator()() const { - const int t = atoi(c_str((string)timeout(list()))); - return new (gc_new()) http::CURLSession("", "", "", "", t); - } -private: - const lambda&)> timeout; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession(caddr(params)))); - - // Return the component implementation lambda function - return value(lambda&)>(applyhttp(car(params), cadr(params), ch))); + }; + return value(applyhttp); } } diff --git a/sca-cpp/trunk/components/kvdb/Makefile.am b/sca-cpp/trunk/components/kvdb/Makefile.am deleted file mode 100644 index 3212f3f5c8..0000000000 --- a/sca-cpp/trunk/components/kvdb/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -# 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. - -INCLUDES = -I${LEVELDB_INCLUDE} - -incl_HEADERS = *.hpp -incldir = $(prefix)/include/components/kvdb - -dist_comp_SCRIPTS = leveldb -compdir=$(prefix)/components/kvdb - -comp_DATA = leveldb.prefix -leveldb.prefix: $(top_builddir)/config.status - echo ${LEVELDB_PREFIX} >leveldb.prefix - -EXTRA_DIST = kvdb.composite kvdb.componentType - -comp_LTLIBRARIES = libkvdb.la -noinst_DATA = libkvdb${libsuffix} - -libkvdb_la_SOURCES = kvdb.cpp -libkvdb_la_LDFLAGS = -L${LEVELDB_LIB} -R${LEVELDB_LIB} -lleveldb -libkvdb${libsuffix}: - ln -s .libs/libkvdb${libsuffix} - -leveldb_test_SOURCES = leveldb-test.cpp -leveldb_test_LDFLAGS = -L${LEVELDB_LIB} -R${LEVELDB_LIB} -lleveldb - -client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs - -dist_noinst_SCRIPTS = kvdb-test server-test -noinst_PROGRAMS = leveldb-test client-test -TESTS = kvdb-test server-test - diff --git a/sca-cpp/trunk/components/kvdb/client-test.cpp b/sca-cpp/trunk/components/kvdb/client-test.cpp deleted file mode 100644 index 5f0ef21d00..0000000000 --- a/sca-cpp/trunk/components/kvdb/client-test.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 KV (Key-Value) database component. - */ - -#include -#include "stream.hpp" -#include "string.hpp" - -#include "list.hpp" -#include "value.hpp" -#include "monad.hpp" -#include "perf.hpp" -#include "../../modules/http/http.hpp" - -namespace tuscany { -namespace nosqldb { - -const string uri("http://localhost:8090/nosqldb"); - -bool testNoSqlDb() { - http::CURLSession cs("", "", "", ""); - - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) - + i); - - const failable id = http::post(a, uri, cs); - assert(hasContent(id)); - - const string p = path(content(id)); - { - const failable val = http::get(uri + p, cs); - assert(hasContent(val)); - assert(content(val) == a); - } - - const list j = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$3.55"))); - const list b = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) - + j); - - { - const failable r = http::put(b, uri + p, cs); - assert(hasContent(r)); - assert(content(r) == value(true)); - } - { - const failable val = http::get(uri + p, cs); - assert(hasContent(val)); - assert(content(val) == b); - } - { - const failable r = http::del(uri + p, cs); - assert(hasContent(r)); - assert(content(r) == value(true)); - } - { - const failable val = http::get(uri + p, cs); - assert(!hasContent(val)); - } - - return true; -} - -struct getLoop { - const string path; - const value entry; - http::CURLSession& cs; - getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { - } - const bool operator()() const { - const failable val = http::get(uri + path, cs); - assert(hasContent(val)); - assert(content(val) == entry); - return true; - } -}; - -bool testGetPerf() { - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$4.55"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) - + i); - - http::CURLSession cs("", "", "", ""); - const failable id = http::post(a, uri, cs); - assert(hasContent(id)); - const string p = path(content(id)); - - const lambda gl = getLoop(p, a, cs); - cout << "NoSqldb get test " << time(gl, 5, 200) << " ms" << endl; - - return true; -} - -} -} - -int main() { - tuscany::cout << "Testing..." << tuscany::endl; - - tuscany::nosqldb::testNoSqlDb(); - tuscany::nosqldb::testGetPerf(); - - tuscany::cout << "OK" << tuscany::endl; - - return 0; -} diff --git a/sca-cpp/trunk/components/kvdb/kvdb-test b/sca-cpp/trunk/components/kvdb/kvdb-test deleted file mode 100755 index 420b98559c..0000000000 --- a/sca-cpp/trunk/components/kvdb/kvdb-test +++ /dev/null @@ -1,30 +0,0 @@ -#!/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 -rm -rf tmp -mkdir -p tmp -./tinycdb -c -m tmp/test.cdb /dev/null -rc=$? - -# Cleanup -exit $rc diff --git a/sca-cpp/trunk/components/kvdb/kvdb.componentType b/sca-cpp/trunk/components/kvdb/kvdb.componentType deleted file mode 100644 index 1c56ab6807..0000000000 --- a/sca-cpp/trunk/components/kvdb/kvdb.componentType +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - diff --git a/sca-cpp/trunk/components/kvdb/kvdb.composite b/sca-cpp/trunk/components/kvdb/kvdb.composite deleted file mode 100644 index 378f418cfc..0000000000 --- a/sca-cpp/trunk/components/kvdb/kvdb.composite +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - tmp/test.cdb - - - - - - diff --git a/sca-cpp/trunk/components/kvdb/kvdb.cpp b/sca-cpp/trunk/components/kvdb/kvdb.cpp deleted file mode 100644 index 0df8f13882..0000000000 --- a/sca-cpp/trunk/components/kvdb/kvdb.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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$ */ - -/** - * LevelDB-based database component implementation. - */ - -#define WANT_HTTPD_LOG 1 -#include "string.hpp" -#include "function.hpp" -#include "list.hpp" -#include "value.hpp" -#include "monad.hpp" -#include "leveldb.hpp" - -namespace tuscany { -namespace nvdb { - -/** - * Get an item from the database. - */ -const failable get(const list& params, leveldb::LevelDB& cdb) { - return leveldb::get(car(params), cdb); -} - -/** - * Post an item to the database. - */ -const failable post(const list& params, leveldb::LevelDB& cdb) { - const value id = append(car(params), mklist(mkuuid())); - const failable val = leveldb::post(id, cadr(params), cdb); - if (!hasContent(val)) - return mkfailure(val); - return id; -} - -/** - * Put an item into the database. - */ -const failable put(const list& params, leveldb::LevelDB& cdb) { - const failable val = leveldb::put(car(params), cadr(params), cdb); - if (!hasContent(val)) - return mkfailure(val); - return value(content(val)); -} - -/** - * Delete an item from the database. - */ -const failable del(const list& params, leveldb::LevelDB& cdb) { - const failable val = leveldb::del(car(params), cdb); - if (!hasContent(val)) - return mkfailure(val); - return value(content(val)); -} - -/** - * Component implementation lambda function. - */ -class applyNoSqldb { -public: - applyNoSqldb(leveldb::LevelDB& cdb) : cdb(cdb) { - } - - const value operator()(const list& params) const { - const value func(car(params)); - if (func == "get") - return get(cdr(params), cdb); - if (func == "post") - return post(cdr(params), cdb); - if (func == "put") - return put(cdr(params), cdb); - if (func == "delete") - return del(cdr(params), cdb); - return mkfailure(); - } - -private: - leveldb::LevelDB& cdb; -}; - -/** - * Start the component. - */ -const failable start(unused const list& params) { - // Connect to the configured database and table - const value dbname = ((lambda&)>)car(params))(list()); - leveldb::LevelDB& cdb = *(new (gc_new()) leveldb::LevelDB(dbname)); - - // Return the component implementation lambda function - return value(lambda&)>(applyNoSqldb(cdb))); -} - -} -} - -extern "C" { - -const tuscany::value apply(const tuscany::list& params) { - const tuscany::value func(car(params)); - if (func == "start") - return tuscany::nosqldb::start(cdr(params)); - return tuscany::mkfailure(); -} - -} diff --git a/sca-cpp/trunk/components/kvdb/leveldb b/sca-cpp/trunk/components/kvdb/leveldb deleted file mode 100755 index f9c54465f6..0000000000 --- a/sca-cpp/trunk/components/kvdb/leveldb +++ /dev/null @@ -1,24 +0,0 @@ -#!/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. - -here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here` -leveldb_prefix=`cat $here/leveldb.prefix` - -$leveldb_prefix/bin/cdb $* - diff --git a/sca-cpp/trunk/components/kvdb/leveldb-test.cpp b/sca-cpp/trunk/components/kvdb/leveldb-test.cpp deleted file mode 100644 index b3b4ea7fd7..0000000000 --- a/sca-cpp/trunk/components/kvdb/leveldb-test.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 TinyCDB access functions. - */ - -#include -#include "stream.hpp" -#include "string.hpp" -#include "perf.hpp" -#include "tinycdb.hpp" - -namespace tuscany { -namespace tinycdb { - -bool testTinyCDB() { - TinyCDB cdb("tmp/test.cdb"); - const value k = mklist("a"); - - assert(hasContent(post(k, string("AAA"), cdb))); - assert((get(k, cdb)) == value(string("AAA"))); - assert(hasContent(put(k, string("aaa"), cdb))); - assert((get(k, cdb)) == value(string("aaa"))); - assert(hasContent(del(k, cdb))); - assert(!hasContent(get(k, cdb))); - - return true; -} - -struct getLoop { - const value k; - TinyCDB& cdb; - getLoop(const value& k, TinyCDB& cdb) : k(k), cdb(cdb) { - } - const bool operator()() const { - assert((get(k, cdb)) == value(string("CCC"))); - return true; - } -}; - -bool testGetPerf() { - const value k = mklist("c"); - TinyCDB cdb("tmp/test.cdb"); - assert(hasContent(post(k, string("CCC"), cdb))); - - const lambda gl = getLoop(k, cdb); - cout << "TinyCDB get test " << time(gl, 5, 100000) << " ms" << endl; - return true; -} - -} -} - -int main() { - tuscany::cout << "Testing..." << tuscany::endl; - - tuscany::tinycdb::testTinyCDB(); - tuscany::tinycdb::testGetPerf(); - - tuscany::cout << "OK" << tuscany::endl; - - return 0; -} diff --git a/sca-cpp/trunk/components/kvdb/leveldb.hpp b/sca-cpp/trunk/components/kvdb/leveldb.hpp deleted file mode 100644 index 05a89a76f7..0000000000 --- a/sca-cpp/trunk/components/kvdb/leveldb.hpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * 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$ */ - -#ifndef tuscany_leveldb_hpp -#define tuscany_leveldb_hpp - -#include -#include -#include -#include - -#include "string.hpp" -#include "list.hpp" -#include "value.hpp" -#include "monad.hpp" -#include "../../modules/scheme/eval.hpp" - -namespace tuscany { -namespace leveldb { - -/** - * A reallocatable buffer. - */ -class buffer { -public: - operator void*() const throw() { - return buf; - } - - operator unsigned char*() const throw() { - return (unsigned char*)buf; - } - - operator char*() const throw() { - return (char*)buf; - } - -private: - buffer(const unsigned int size, void* buf) : size(size), buf(buf) { - } - - unsigned int size; - void* buf; - - friend const buffer mkbuffer(const unsigned int sz); - friend const buffer mkbuffer(const buffer& b, const unsigned int newsz); - friend const bool free(const buffer& b); -}; - -/** - * Make a new buffer. - */ -const buffer mkbuffer(const unsigned int sz) { - return buffer(sz, malloc(sz)); -} - -/** - * Make a new buffer by reallocating an existing one. - */ -const buffer mkbuffer(const buffer& b, const unsigned int sz) { - if (sz <= b.size) - return b; - return buffer(sz, realloc(b.buf, sz)); -} - -/** - * Free a buffer. - */ -const bool free(const buffer&b) { - ::free(b.buf); - return true; -} - -/** - * Convert a database name to an absolute path. - */ -const string absdbname(const string& name) { - if (length(name) == 0 || c_str(name)[0] == '/') - return name; - char cwd[512]; - if (getcwd(cwd, sizeof(cwd)) == NULL) - return name; - return string(cwd) + "/" + name; -} - -/** - * Represents a LevelDB connection. - */ -class LevelDB { -public: - LevelDB() : owner(false), fd(-1) { - debug("leveldb::leveldb"); - st.st_ino = 0; - } - - LevelDB(const string& name) : owner(true), name(absdbname(name)), fd(-1) { - debug(name, "leveldb::leveldb::name"); - st.st_ino = 0; - } - - LevelDB(const LevelDB& c) : owner(false), name(c.name), fd(c.fd) { - debug("leveldb::leveldb::copy"); - st.st_ino = c.st.st_ino; - } - - const LevelDB& operator=(const LevelDB& c) { - debug("leveldb::leveldb::operator="); - if(this == &c) - return *this; - owner = false; - name = c.name; - fd = c.fd; - st.st_ino = c.st.st_ino; - return *this; - } - - ~LevelDB() { - debug("leveldb::~leveldb"); - if (!owner) - return; - if (fd == -1) - return; - close(fd); - } - -private: - bool owner; - string name; - leveldb::DB* db; - struct stat st; - - friend const string dbname(const LevelDB& db); - friend const failable dbopen(LevelDB& db); - friend const failable dbclose(LevelDB& db); -}; - -/** - * Return the name of the database. - */ -const string dbname(const LevelDB& db) { - return db.name; -} - -/** - * Open a database. - */ -const failable dbopen(LevelDB& db) { - - // Get database file serial number - struct stat st; - const int s = stat(c_str(db.name), &st); - if (s == -1) - return mkfailure(string("Couldn't leveldb read database stat: ") + db.name); - - leveldb::DB* ldb; - leveldb::Options options; - options.create_if_missing = true; - leveldb::Status status = leveldb::DB::Open(options, s, &ldb); - db.db = ldb; -} - -/** - * Close a database. - */ -const failable dbclose(LevelDB& db) { - delete db.db; - db.db = NULL; - return true; -} - - -const failable post(const value& key, const value& val, LevelDB& db) { - debug(key, "leveldb::post::key"); - debug(val, "leveldb::post::value"); - debug(dbname(db), "leveldb::post::dbname"); - - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); - - put(ks, vs, db); - - debug(r, "leveldb::post::result"); - return r; -} - - -const failable put(const value& key, const value& val, LevelDB& db) { - debug(key, "leveldb::put::key"); - debug(val, "leveldb::put::value"); - debug(dbname(db), "leveldb::put::dbname"); - - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); - - debug(r, "leveldb::put::result"); - return r; -} - -/** - * Get an item from the database. - */ -const failable get(const value& key, LevelDB& db) { - debug(key, "leveldb::get::key"); - debug(dbname(db), "leveldb::get::dbname"); - - const string ks(scheme::writeValue(key)); - - std::string data; - db.db->Get(leveldb::ReadOptions(), key, &data); - const value val(scheme::readValue(string(data))); - - debug(val, "leveldb::get::result"); - return val; -} - -/** - * Delete an item from the database - */ -struct delUpdate { - const string ks; - delUpdate(const string& ks) : ks(ks) { - } - const failable operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const { - if (ks == string((char*)buf, klen)) - return false; - return true; - } -}; - -struct delFinish { - delFinish() { - } - const failable operator()(unused struct db_make& dbm) const { - return true; - } -}; - -const failable del(const value& key, LevelDB& db) { - debug(key, "leveldb::delete::key"); - debug(dbname(db), "leveldb::delete::dbname"); - - const string ks(scheme::writeValue(key)); - - leveldb::Status s = db.db->Delete(leveldb::WriteOptions(), key); - - debug(r, "leveldb::delete::result"); - return s.ok(); -} - -} -} - -#endif /* tuscany_leveldb_hpp */ diff --git a/sca-cpp/trunk/components/kvdb/server-test b/sca-cpp/trunk/components/kvdb/server-test deleted file mode 100755 index ebf01b9b4b..0000000000 --- a/sca-cpp/trunk/components/kvdb/server-test +++ /dev/null @@ -1,41 +0,0 @@ -#!/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 -rm -rf tmp -../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs -../../modules/server/server-conf tmp -../../modules/server/scheme-conf tmp -cat >>tmp/conf/httpd.conf </dev/null -rc=$? - -# Cleanup -../../modules/http/httpd-stop tmp -sleep 2 -exit $rc diff --git a/sca-cpp/trunk/components/log/Makefile.am b/sca-cpp/trunk/components/log/Makefile.am index 0e96be5697..45074b11a4 100644 --- a/sca-cpp/trunk/components/log/Makefile.am +++ b/sca-cpp/trunk/components/log/Makefile.am @@ -70,7 +70,7 @@ scribe_status_SOURCES = scribe-status.cpp scribe_status_LDFLAGS = -L${THRIFT_LIB} -R${THRIFT_LIB} -lthrift -L${FB303_LIB} -R${FB303_LIB} -lfb303 -L${SCRIBE_LIB} -R${SCRIBE_LIB} -lscribe client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = scribe-test server-test noinst_PROGRAMS = client-test diff --git a/sca-cpp/trunk/components/log/client-test.cpp b/sca-cpp/trunk/components/log/client-test.cpp index d8cac5ee81..6e0ecaf89e 100644 --- a/sca-cpp/trunk/components/log/client-test.cpp +++ b/sca-cpp/trunk/components/log/client-test.cpp @@ -38,15 +38,15 @@ namespace log { const string uri("http://localhost:8090/log"); -bool testLog() { - http::CURLSession cs("", "", "", "", 0); - - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testLog() { + const http::CURLSession cs("", "", "", "", 0); + + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); const failable id = http::post(a, uri, cs); @@ -55,40 +55,31 @@ bool testLog() { return true; } -struct logLoop { - const value a; - const string uri; - http::CURLSession& cs; - logLoop(const value& a, const string& uri, http::CURLSession& cs) : a(a), uri(uri), cs(cs) { - } - const bool operator()() const { - const failable id = http::post(a, uri, cs); - assert(hasContent(id)); - return true; - } -}; - -bool testLogPerf() { - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testLogPerf() { + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", "", 0); + const http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, uri, cs); assert(hasContent(id)); - const lambda ll = logLoop(a, uri, cs); + const blambda ll = [a, uri, cs]() -> const bool { + const failable id = http::post(a, uri, cs); + assert(hasContent(id)); + return true; + }; cout << "Log test " << time(ll, 5, 200) << " ms" << endl; return true; } -bool testLogger() { - http::CURLSession cs("", "", "", "", 0); +const bool testLogger() { + const http::CURLSession cs("", "", "", "", 0); const failable res = http::evalExpr(mklist(string("sum"), 33, 22), string("http://localhost:8090/client"), cs); assert(hasContent(res)); diff --git a/sca-cpp/trunk/components/log/log.cpp b/sca-cpp/trunk/components/log/log.cpp index f7f7086192..11d24c8da5 100644 --- a/sca-cpp/trunk/components/log/log.cpp +++ b/sca-cpp/trunk/components/log/log.cpp @@ -38,7 +38,7 @@ namespace log { /** * Post an item to the Scribe log. */ -const failable post(const list& params, const value& host, const value& category, scribe::Scribe& sc) { +const failable post(const list& params, const value& host, const value& category, const scribe::Scribe& sc) { debug(cadr(params), "log::post::value"); const failable val = scribe::log(cadr(params), host, category, sc); if (!hasContent(val)) @@ -46,42 +46,27 @@ const failable post(const list& params, const value& host, const v return value(mklist(true)); } -/** - * Component implementation lambda function. - */ -class applyLog { -public: - applyLog(const value& host, const value& category, scribe::Scribe& sc) : host(host), category(category), sc(sc) { - } - - const value operator()(const list& params) const { - const value func(car(params)); - if (func == "post") - return post(cdr(params), host, category, sc); - return mkfailure(); - } - -private: - const value host; - const value category; - scribe::Scribe& sc; -}; - /** * Start the component. */ const failable start(const list& params) { // Connect to Scribe - scribe::Scribe& sc = *(new (gc_new()) scribe::Scribe("localhost", 1464)); + const scribe::Scribe& sc = *(new (gc_new()) scribe::Scribe("localhost", 1464)); // Extract the configured category - const value host = ((lambda&)>)car(params))(list()); - const value category = ((lambda&)>)cadr(params))(list()); + const value host = ((lvvlambda)car(params))(nilListValue); + const value category = ((lvvlambda)cadr(params))(nilListValue); debug(host, "log::start::host"); debug(category, "log::start::category"); // Return the component implementation lambda function - return value(lambda&)>(applyLog(host, category, sc))); + const lvvlambda applyLog = [host, category, sc](const list& params) -> const value { + const value func(car(params)); + if (func == "post") + return post(cdr(params), host, category, sc); + return mkfailure(); + }; + return value(applyLog); } } diff --git a/sca-cpp/trunk/components/log/logger.cpp b/sca-cpp/trunk/components/log/logger.cpp index d7969036ab..46fd1f7cb4 100644 --- a/sca-cpp/trunk/components/log/logger.cpp +++ b/sca-cpp/trunk/components/log/logger.cpp @@ -37,14 +37,21 @@ namespace tuscany { namespace logger { /** - * Component implementation lambda function. + * Start the component. */ -class applyLog { -public: - applyLog(const lambda&)>& relay, const value& host, const value& category, scribe::Scribe& sc) : relay(relay), host(host), category(category), sc(sc) { - } +const failable start(const list& params) { + // Connect to Scribe + const scribe::Scribe& sc = *(new (gc_new()) scribe::Scribe("localhost", 1464)); - const value operator()(const list& params) const { + // Extract the configured relay service and category + const value relay = car(params); + const value host = ((lvvlambda)cadr(params))(nilListValue); + const value category = ((lvvlambda)caddr(params))(nilListValue); + debug(host, "logger::start::host"); + debug(category, "logger::start::category"); + + // Return the component implementation lambda function + const lvvlambda applyLog = [relay, host, category, sc](const list& params) -> const value { // Log the function params debug(params, "logger::apply::params"); scribe::log(params, host, category, sc); @@ -55,31 +62,8 @@ public: // Log the result scribe::log(res, host, category, sc); return res; - } - -private: - const lambda&)> relay; - const value host; - const value category; - scribe::Scribe& sc; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Connect to Scribe - scribe::Scribe& sc = *(new (gc_new()) scribe::Scribe("localhost", 1464)); - - // Extract the configured relay service and category - const value rel = car(params); - const value host = ((lambda&)>)cadr(params))(list()); - const value category = ((lambda&)>)caddr(params))(list()); - debug(host, "logger::start::host"); - debug(category, "logger::start::category"); - - // Return the component implementation lambda function - return value(lambda&)>(applyLog(rel, host, category, sc))); + }; + return value(applyLog); } } diff --git a/sca-cpp/trunk/components/log/scribe-cat.cpp b/sca-cpp/trunk/components/log/scribe-cat.cpp index 254e2167ae..d9a2e44613 100644 --- a/sca-cpp/trunk/components/log/scribe-cat.cpp +++ b/sca-cpp/trunk/components/log/scribe-cat.cpp @@ -36,14 +36,14 @@ namespace tuscany { namespace scribecat { -int cat(const string& host, const string& category, const string& type) { +const int cat(const string& host, const string& category, const string& type) { // Connect to Scribe scribe::Scribe& sc = *(new (gc_new()) scribe::Scribe(host, 1464)); // Read lines from stdin and log them char buf[8193]; for (;;) { - gc_scoped_pool p; + const gc_scoped_pool p; // Write line prefix ostringstream os; @@ -54,7 +54,7 @@ int cat(const string& host, const string& category, const string& type) { strcpy(buf, c_str(prefix)); // Read log line - const char* s = fgets(buf + pl, 8192 - pl, stdin); + const char* const s = fgets(buf + pl, 8192 - pl, stdin); if (s == NULL) return 0; @@ -73,7 +73,7 @@ int cat(const string& host, const string& category, const string& type) { } } -int main(const int argc, const char** argv) { +int main(const int argc, const char** const argv) { return tuscany::scribecat::cat(argc < 2? "localhost" : argv[1], argc < 3? "default" : argv[2], argc < 4? "" : argv[3]); } diff --git a/sca-cpp/trunk/components/log/scribe-status.cpp b/sca-cpp/trunk/components/log/scribe-status.cpp index 79f7572947..7dbf94542b 100644 --- a/sca-cpp/trunk/components/log/scribe-status.cpp +++ b/sca-cpp/trunk/components/log/scribe-status.cpp @@ -60,7 +60,7 @@ const int status(const string& host, const int port) { } } -int main(const int argc, const char** argv) { +int main(const int argc, const char** const argv) { return tuscany::scribestatus::status(argc < 2? "localhost" : argv[1], argc < 3? 1463 : atoi(argv[2])); } diff --git a/sca-cpp/trunk/components/log/scribe.hpp b/sca-cpp/trunk/components/log/scribe.hpp index 0f0570be64..fd18f53bb7 100644 --- a/sca-cpp/trunk/components/log/scribe.hpp +++ b/sca-cpp/trunk/components/log/scribe.hpp @@ -74,21 +74,11 @@ public: init(host, port); } - Scribe(const Scribe& c) : owner(false) { + Scribe(const Scribe& c) : owner(false), client(c.client), transport(c.transport) { debug("scribe::scribe::copy"); - client = c.client; - transport = c.transport; } - const Scribe& operator=(const Scribe& c) { - debug("scribe::scribe::operator="); - if(this == &c) - return *this; - owner = false; - client = c.client; - transport = c.transport; - return *this; - } + Scribe& operator=(const Scribe& c) = delete; ~Scribe() { if (!owner) @@ -102,7 +92,7 @@ public: } private: - bool owner; + const bool owner; ::scribe::thrift::scribeClient* client; boost::shared_ptr transport; @@ -135,8 +125,8 @@ const failable log(const value& val, const string& host, const value& cate debug(category, "scribe::log::category"); const value cat = isString(category)? value(c_str(category)):category; - const string cs(scheme::writeValue(cat)); - const string vs(scheme::writeValue(val)); + const string cs(write(content(scheme::writeValue(cat)))); + const string vs(write(content(scheme::writeValue(val)))); ostringstream os; os << "[" << host << "] " << vs; @@ -147,8 +137,8 @@ const failable log(const value& val, const string& host, const value& cate std::vector< ::scribe::thrift::LogEntry> msgs; msgs.push_back(entry); - int result = sc.client->Log(msgs); - if (result != ::scribe::thrift::OK) + const int result = sc.client->Log(msgs); + if (result != ::scribe::thrift::ResultCode::OK) return mkfailure("Could not log value, retry later"); } catch (const std::exception& e) { return mkfailure(e.what()); @@ -165,24 +155,24 @@ const failable status(const Scribe& sc) { debug("scribe::status"); try { - ::facebook::fb303::fb_status s = sc.client->getStatus(); + ::facebook::fb303::fb_status::type s = sc.client->getStatus(); switch(s) { - case ::facebook::fb303::DEAD: + case ::facebook::fb303::fb_status::DEAD: debug("DEAD", "scribe::status::result"); return string("DEAD"); - case ::facebook::fb303::STARTING: + case ::facebook::fb303::fb_status::STARTING: debug("STARTING", "scribe::status::result"); return string("STARTING"); - case ::facebook::fb303::ALIVE: + case ::facebook::fb303::fb_status::ALIVE: debug("ALIVE", "scribe::status::result"); return string("ALIVE"); - case ::facebook::fb303::STOPPING: + case ::facebook::fb303::fb_status::STOPPING: debug("STOPPING", "scribe::status::result"); return string("STOPPING"); - case ::facebook::fb303::STOPPED: + case ::facebook::fb303::fb_status::STOPPED: debug("STOPPED", "scribe::status::result"); return string("STOPPED"); - case ::facebook::fb303::WARNING: + case ::facebook::fb303::fb_status::WARNING: debug("WARNING", "scribe::status::result"); return string("WARNING"); } diff --git a/sca-cpp/trunk/components/queue/Makefile.am b/sca-cpp/trunk/components/queue/Makefile.am index c44722a523..81a7128b4a 100644 --- a/sca-cpp/trunk/components/queue/Makefile.am +++ b/sca-cpp/trunk/components/queue/Makefile.am @@ -48,7 +48,7 @@ qpid_test_SOURCES = qpid-test.cpp qpid_test_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon +client_test_LDFLAGS = -lxml2 -lcurl -ljansson -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon dist_noinst_SCRIPTS = send-test server-test noinst_PROGRAMS = qpid-test client-test diff --git a/sca-cpp/trunk/components/queue/client-test.cpp b/sca-cpp/trunk/components/queue/client-test.cpp index 30bfe07bf7..f1399bb22c 100644 --- a/sca-cpp/trunk/components/queue/client-test.cpp +++ b/sca-cpp/trunk/components/queue/client-test.cpp @@ -46,15 +46,15 @@ namespace queue { const value key(mklist(string("report"))); const string qname("reportq"); -const list item = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); -const list entry = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const list item = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); +const list entry = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + item); -bool testDeclareQueue() { +const bool testDeclareQueue() { QpidConnection qc; QpidSession qs(qc); const failable r = declareQueue(key, qname, qs); @@ -69,18 +69,18 @@ const bool listener(const value& k, const value& v) { return false; } -bool testListen() { +const bool testListen() { QpidConnection qc; QpidSession qs(qc); QpidSubscription qsub(qs); - const lambda l(listener); + const lambda l(listener); listen(qname, l, qsub); return true; } -bool testPost() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); +const bool testPost() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); const failable id = http::post(entry, "http://localhost:8090/print-sender", ch); assert(hasContent(id)); return true; diff --git a/sca-cpp/trunk/components/queue/qpid-test.cpp b/sca-cpp/trunk/components/queue/qpid-test.cpp index 27db7734b0..87fc39c8bd 100644 --- a/sca-cpp/trunk/components/queue/qpid-test.cpp +++ b/sca-cpp/trunk/components/queue/qpid-test.cpp @@ -45,7 +45,7 @@ namespace queue { const value key(mklist("test")); const string qname("testq"); -bool testDeclareQueue() { +const bool testDeclareQueue() { QpidConnection qc; QpidSession qs(qc); const failable r = declareQueue(key, qname, qs); @@ -53,12 +53,12 @@ bool testDeclareQueue() { return true; } -const list item = list() - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99")); +const list item = nilListValue + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99")); const list entry = mklist(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item); -bool testPost() { +const bool testPost() { QpidConnection qc; QpidSession qs(qc); const failable r = post(key, entry, qs); @@ -72,11 +72,11 @@ const bool listener(const value& k, const value& v) { return false; } -bool testListen() { +const bool testListen() { QpidConnection qc; QpidSession qs(qc); QpidSubscription qsub(qs); - const lambda l(listener); + const lambda l(listener); listen(qname, l, qsub); return true; } diff --git a/sca-cpp/trunk/components/queue/qpid.hpp b/sca-cpp/trunk/components/queue/qpid.hpp index ef53c529e8..77361461c6 100644 --- a/sca-cpp/trunk/components/queue/qpid.hpp +++ b/sca-cpp/trunk/components/queue/qpid.hpp @@ -65,14 +65,7 @@ public: debug("queue::qpidonnection::copy"); } - const QpidConnection& operator=(const QpidConnection& qc) { - debug("queue::qpidonnection::operator="); - if(this == &c) - return *this; - owner = false; - c = qc.c; - return *this; - } + QpidConnection& operator=(const QpidConnection& qc) = delete; ~QpidConnection() { debug("queue::~qpidonnection"); @@ -148,7 +141,7 @@ const failable close(QpidSession& qs) { * Declare a key / AMQP queue pair. */ const failable declareQueue(const value& key, const string& name, QpidSession& qs) { - const string ks(scheme::writeValue(key)); + const string ks(write(content(scheme::writeValue(key)))); try { qs.s.queueDeclare(qpid::client::arg::queue=c_str(name)); qs.s.exchangeBind(qpid::client::arg::exchange="amq.direct", qpid::client::arg::queue=c_str(name), qpid::client::arg::bindingKey=c_str(ks)); @@ -164,8 +157,8 @@ const failable declareQueue(const value& key, const string& name, QpidSess const failable post(const value& key, const value& val, QpidSession& qs) { // Send in a message with the given key. - const string ks(scheme::writeValue(key)); - const string vs(scheme::writeValue(val)); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); try { qpid::client::Message message; message.getDeliveryProperties().setRoutingKey(c_str(ks)); @@ -202,7 +195,7 @@ public: } private: - friend const failable listen(const string& name, const lambda& l, QpidSubscription& qsub); + friend const failable listen(const string& name, const lambda& l, QpidSubscription& qsub); friend const failable stop(QpidSubscription& qsub); const bool owner; @@ -214,14 +207,14 @@ private: */ class Listener : public qpid::client::MessageListener { public: - Listener(const lambda l, qpid::client::SubscriptionManager& subs) : l(l), subs(subs) { + Listener(const lambda l, qpid::client::SubscriptionManager& subs) : l(l), subs(subs) { } virtual void received(qpid::client::Message& msg) { // Call the listener function - const value k(scheme::readValue(msg.getDeliveryProperties().getRoutingKey().c_str())); - const value v(scheme::readValue(msg.getData().c_str())); + const value k(content(scheme::readValue(msg.getDeliveryProperties().getRoutingKey().c_str()))); + const value v(content(scheme::readValue(msg.getData().c_str()))); const bool r = l(k, v); if (!r) { try { @@ -233,12 +226,12 @@ public: } private: - const lambda l; + const lambda l; qpid::client::SubscriptionManager& subs; }; -const failable listen(const string& name, const lambda& l, QpidSubscription& qsub) { +const failable listen(const string& name, const lambda& l, QpidSubscription& qsub) { debug("queue::listen"); Listener listener(l, qsub.subs); try { diff --git a/sca-cpp/trunk/components/queue/queue-listener.cpp b/sca-cpp/trunk/components/queue/queue-listener.cpp index 483d0de65a..f6793ecae7 100644 --- a/sca-cpp/trunk/components/queue/queue-listener.cpp +++ b/sca-cpp/trunk/components/queue/queue-listener.cpp @@ -42,57 +42,45 @@ namespace tuscany { namespace queue { /** - * A relay function that posts the AMQP messages it receives to a relay component reference. + * Start the component. */ -class relay { -public: - relay(const lambda&)>& rel) : rel(rel) { - } +const failable start(const list& params) { + // Extract the relay reference and the AMQP key and queue name + const value rel = car(params); + const value pk = ((lvvlambda)cadr(params))(nilListValue); + const value key = isList(pk)? (list)pk : mklist(pk); + const value qname = ((lvvlambda)caddr(params))(nilListValue); + + // Create an AMQP session + QpidConnection qc(false); + QpidSession qs(qc, false); + + // Declare the configured AMQP key / queue pair + declareQueue(key, qname, qs); - const bool operator()(const value& k, const value& v) const { + // Listen and relay messages in a worker thread + QpidSubscription qsub(qs, false); + const worker w(3); + const lambda rl = [rel](const value& k, const value& v) -> const bool { + // A relay function that posts the AMQP messages it receives to a relay component reference. debug(k, "queue::relay::key"); debug(v, "queue::relay::value"); const value res = rel(mklist("post", isList(k)? (list)k : mklist(k), v)); return true; - } + }; -private: - const lambda&)> rel; -}; - -/** - * Subscribe and listen to an AMQP queue. - */ -class subscribe { -public: - subscribe(const string& qname, const lambda& l, const QpidSubscription& qsub) : qname(qname), l(l), qsub(qsub) { - } - - const failable operator()() const { - gc_pool pool; + // Subscribe and listen to the AMQP queue. + const lambda()> subscribe = [qname, rl, qsub]() -> const failable { + const gc_pool pool; debug(qname, "queue::subscribe::listen"); - const failable r = listen(qname, l, const_cast(qsub)); + const failable r = listen(qname, rl, const_cast(qsub)); debug(qname, "queue::subscribe::stopped"); return r; - } - -private: - const string qname; - const lambda l; - const QpidSubscription qsub; -}; - -/** - * Listener lambda function, responsible for starting an AMQP subscription in a worker thread, and - * apply any function calls to the listener component. The only supported function is stop(), - * called to stop the listener component and shutdown the worker thread. - */ -class listener { -public: - listener(QpidConnection& qc, QpidSession& qs, QpidSubscription& qsub, worker& w) : qc(qc), qs(qs), qsub(qsub), w(w) { - } + }; + submit >(w, subscribe); - const value operator()(const list& params) const { + // Return the listener component lambda function + const lvvlambda listener = [qc, qs, qsub, w](const list& params) -> const value { const tuscany::value func(car(params)); // Stop the component @@ -107,41 +95,9 @@ public: cancel(const_cast(w)); debug("queue::listener::stopped"); - return failable(value(lambda&)>())); - } - -private: - QpidConnection qc; - QpidSession qs; - QpidSubscription qsub; - worker w; -}; - -/** - * Start the component. - */ -const failable start(const list& params) { - // Extract the relay reference and the AMQP key and queue name - const value rel = car(params); - const value pk = ((lambda&)>)cadr(params))(list()); - const value key = isList(pk)? (list)pk : mklist(pk); - const value qname = ((lambda&)>)caddr(params))(list()); - - // Create an AMQP session - QpidConnection qc(false); - QpidSession qs(qc, false); - - // Declare the configured AMQP key / queue pair - declareQueue(key, qname, qs); - - // Listen and relay messages in a worker thread - QpidSubscription qsub(qs, false); - worker w(3); - const lambda rl = relay(rel); - submit >(w, lambda()>(subscribe(qname, rl, qsub))); - - // Return the listener component lambda function - return value(lambda&)>(listener(qc, qs, qsub, w))); + return failable(value(lvvlambda())); + }; + return value(listener); } } diff --git a/sca-cpp/trunk/components/queue/queue-sender.cpp b/sca-cpp/trunk/components/queue/queue-sender.cpp index 202a0e4435..a479f255ce 100644 --- a/sca-cpp/trunk/components/queue/queue-sender.cpp +++ b/sca-cpp/trunk/components/queue/queue-sender.cpp @@ -48,7 +48,7 @@ const failable post(const list& params) { QpidSession qs(qc); // Post the item - const value pk = ((lambda&)>)caddr(params))(list()); + const value pk = ((lvvlambda)caddr(params))(nilListValue); const value key = isList(pk)? append(pk, (list)car(params)) : cons(pk, (list)car(params)); debug(key, "queue::post::key"); debug(cadr(params), "queue::post::value"); diff --git a/sca-cpp/trunk/components/smtp/Makefile.am b/sca-cpp/trunk/components/smtp/Makefile.am index 41fa686b9a..42c0d3347f 100644 --- a/sca-cpp/trunk/components/smtp/Makefile.am +++ b/sca-cpp/trunk/components/smtp/Makefile.am @@ -23,12 +23,12 @@ comp_LTLIBRARIES = libsmtppost.la noinst_DATA = libsmtppost${libsuffix} libsmtppost_la_SOURCES = smtppost.cpp -libsmtppost_la_LDFLAGS = -lxml2 -lmozjs -curl +libsmtppost_la_LDFLAGS = -lxml2 -ljansson -curl libsmtppost${libsuffix}: ln -s .libs/libsmtppost${libsuffix} client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = server-test noinst_PROGRAMS = client-test diff --git a/sca-cpp/trunk/components/smtp/client-test.cpp b/sca-cpp/trunk/components/smtp/client-test.cpp index 10274a6248..4a60b475fc 100644 --- a/sca-cpp/trunk/components/smtp/client-test.cpp +++ b/sca-cpp/trunk/components/smtp/client-test.cpp @@ -38,8 +38,8 @@ namespace smtp { const string postURI("http://localhost:8090/smtppost"); -bool testPost() { - http::CURLSession cs("", "", "", "", 0); +const bool testPost() { + const http::CURLSession cs("", "", "", "", 0); const failable val = http::get(postURI, cs); assert(hasContent(val)); diff --git a/sca-cpp/trunk/components/smtp/smtppost.cpp b/sca-cpp/trunk/components/smtp/smtppost.cpp index 1030ccc223..396b1a0a38 100644 --- a/sca-cpp/trunk/components/smtp/smtppost.cpp +++ b/sca-cpp/trunk/components/smtp/smtppost.cpp @@ -38,7 +38,7 @@ namespace smtppost { /** * Post/send an email message using SMTP. */ -const failable post(const string& url, const string& user, const string& pass, const string& from, const string& to, const string& subject, const value& val, http::CURLSession& cs) { +const failable post(const string& url, const string& user, const string& pass, const string& from, const string& to, const string& subject, const value& val, const http::CURLSession& cs) { // Convert value to a content request const failable > > freq = http::contentRequest(val, url); if (!hasContent(freq)) @@ -52,7 +52,7 @@ const failable post(const string& url, const string& user, const string& http::cleanup(cs); return mkfailure(fch); } - CURL* ch = content(fch); + CURL* const ch = content(fch); curl_easy_setopt(ch, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); // Convert message to a string @@ -88,25 +88,25 @@ const failable post(const string& url, const string& user, const string& } http::cleanup(cs); - return value(true); + return trueValue; } /** * Evaluate an SMTP post/send. */ -const failable get(const lambda&)>& url, - const lambda&)>& user, const lambda&)>& pass, - const lambda&)>& from, const lambda&)>& to, - const lambda&)>& subject, const lambda&)>& val, - http::CURLSession& ch) { +const failable get(const lvvlambda& url, + const lvvlambda& user, const lvvlambda& pass, + const lvvlambda& from, const lvvlambda& to, + const lvvlambda& subject, const lvvlambda& val, + const http::CURLSession& ch) { debug("smtppost::get"); - const value u = url(mklist("get", list())); - const value i = user(mklist("get", list())); - const value p = pass(mklist("get", list())); - const value f = from(mklist("get", list())); - const value t = to(mklist("get", list())); - const value s = subject(mklist("get", list())); - const value v = val(mklist("get", list())); + const value u = url(mklist("get", nilListValue)); + const value i = user(mklist("get", nilListValue)); + const value p = pass(mklist("get", nilListValue)); + const value f = from(mklist("get", nilListValue)); + const value t = to(mklist("get", nilListValue)); + const value s = subject(mklist("get", nilListValue)); + const value v = val(mklist("get", nilListValue)); debug(u, "smtppost::get::url"); debug(i, "smtppost::get::user"); debug(p, "smtppost::get::pass"); @@ -118,53 +118,33 @@ const failable get(const lambda&)>& url, } /** - * Component implementation lambda function. + * Start the component. */ -class applysmtp { -public: - applysmtp(const lambda&)>& url, - const lambda&)>& user, const lambda&)>& pass, - const lambda&)>& from, const lambda&)>& to, - const lambda&)>& subject, const lambda&)>& val, - perthread_ptr& ch) : - url(url), user(user), pass(pass), from(from), to(to), subject(subject), val(val), ch(ch) { - } +const failable start(const list& params) { + // Create a CURL session + const gc_pool cp(gc_current_pool()); + const lambda()> newsession = [cp]() -> const gc_ptr { + const gc_scoped_pool sp(pool(cp)); + return new (gc_new()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, 0); + }; + const perthread_ptr ch = *(new (gc_new >()) perthread_ptr(newsession)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda url = car(params); + const lvvlambda user = cadr(params); + const lvvlambda pass = caddr(params); + const lvvlambda from = cadddr(params); + const lvvlambda to = caddddr(params); + const lvvlambda subject = cadddddr(params); + const lvvlambda val = caddddddr(params); + const lvvlambda applysmtp = [url, user, pass, from, to, subject, val, ch](const list& params) -> const value { debug(params, "smtppost::applysmtp::params"); const value func(car(params)); if (func == "get") return get(url, user, pass, from, to, subject, val, *ch); return mkfailure(); - } - -private: - const lambda&)> url; - const lambda&)> user; - const lambda&)> pass; - const lambda&)> from; - const lambda&)> to; - const lambda&)> subject; - const lambda&)> val; - perthread_ptr ch; -}; - -/** - * Create a new CURL session. - */ -const gc_ptr newsession() { - return new (gc_new()) http::CURLSession("", "", "", "", 0); -} - -/** - * Start the component. - */ -const failable start(const list& params) { - // Create a CURL session - perthread_ptr ch = perthread_ptr(lambda()>(newsession)); - - // Return the component implementation lambda function - return value(lambda&)>(applysmtp(car(params), cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params), caddddddr(params), ch))); + }; + return value(applysmtp); } } diff --git a/sca-cpp/trunk/components/sqldb/Makefile.am b/sca-cpp/trunk/components/sqldb/Makefile.am index 9ce5f26713..988383b4f1 100644 --- a/sca-cpp/trunk/components/sqldb/Makefile.am +++ b/sca-cpp/trunk/components/sqldb/Makefile.am @@ -48,10 +48,10 @@ 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 +client_test_LDFLAGS = -lxml2 -lcurl -ljansson 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 +TESTS = sqldb-test server-test endif diff --git a/sca-cpp/trunk/components/sqldb/client-test.cpp b/sca-cpp/trunk/components/sqldb/client-test.cpp index 0cbcb57363..c9fbb7d5bb 100644 --- a/sca-cpp/trunk/components/sqldb/client-test.cpp +++ b/sca-cpp/trunk/components/sqldb/client-test.cpp @@ -38,15 +38,15 @@ namespace sqldb { const string uri("http://localhost:8090/sqldb"); -bool testSqlDb() { - http::CURLSession cs("", "", "", "", 0); - - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testSqlDb() { + const http::CURLSession cs("", "", "", "", 0); + + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); const failable id = http::post(a, uri, cs); @@ -59,18 +59,18 @@ bool testSqlDb() { assert(content(val) == a); } - const list j = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$3.55"))); - const list b = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list j = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$3.55"))); + const list b = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + j); { const failable r = http::put(b, uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable val = http::get(uri + p, cs); @@ -80,7 +80,7 @@ bool testSqlDb() { { const failable r = http::del(uri + p, cs); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable val = http::get(uri + p, cs); @@ -90,35 +90,26 @@ bool testSqlDb() { return true; } -struct getLoop { - const string path; - const value entry; - http::CURLSession& cs; - getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { - } - const bool operator()() const { - const failable val = http::get(uri + path, cs); - assert(hasContent(val)); - assert(content(val) == entry); - return true; - } -}; - -bool testGetPerf() { - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$4.55"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testGetPerf() { + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$4.55"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", "", 0); + const http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); - const lambda gl = getLoop(p, a, cs); + const blambda gl = [p, a, cs]() -> const bool { + const failable val = http::get(uri + p, cs); + assert(hasContent(val)); + assert(content(val) == a); + return true; + }; cout << "Sqldb get test " << time(gl, 5, 200) << " ms" << endl; return true; diff --git a/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp b/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp index 2cd25f874a..5d73b0d877 100644 --- a/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp +++ b/sca-cpp/trunk/components/sqldb/pgsql-standby-test.cpp @@ -32,7 +32,7 @@ namespace tuscany { namespace pgsql { -bool testPGSql() { +const bool testPGSql() { PGSql wpg("host=localhost port=6432 dbname=db", "test"); PGSql rpg("host=localhost port=6433 dbname=db", "test"); const value k = mklist("a"); @@ -50,25 +50,17 @@ bool testPGSql() { 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 bool testGetPerf() { const value k = mklist("c"); 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); - const lambda gl = getLoop(k, rpg); + const blambda gl = [k, rpg]() -> const bool { + assert((get(k, rpg)) == value(string("CCC"))); + return true; + }; cout << "PGSql get test " << time(gl, 5, 200) << " ms" << endl; return true; } diff --git a/sca-cpp/trunk/components/sqldb/pgsql-test.cpp b/sca-cpp/trunk/components/sqldb/pgsql-test.cpp index d10ab5f4c2..5d7bb98cd8 100644 --- a/sca-cpp/trunk/components/sqldb/pgsql-test.cpp +++ b/sca-cpp/trunk/components/sqldb/pgsql-test.cpp @@ -32,37 +32,38 @@ namespace tuscany { namespace pgsql { -bool testPGSql() { +const bool testPGSql() { PGSql pg("host=localhost port=6432 dbname=db", "test"); const value k = mklist("a"); + const value lk = mklist(mklist("like", "%"), mklist("limit", "2")); + const value rx = mklist(mklist("regex", "a"), mklist("limit", "2")); + const value ts = mklist(mklist("textsearch", "AAA"), mklist("limit", "2")); + const value rxts = mklist(mklist("regex", "a"), mklist("textsearch", "AAA"), mklist("limit", "2")); assert(hasContent(post(k, string("AAA"), pg))); - assert((get(k, pg)) == value(string("AAA"))); + assert(content(get(k, pg)) == value(string("AAA"))); + assert(cadr(car(content(get(lk, pg)))) == value(string("AAA"))); + assert(cadr(car(content(get(rx, pg)))) == value(string("AAA"))); + assert(cadr(car(content(get(ts, pg)))) == value(string("AAA"))); + assert(cadr(car(content(get(rxts, pg)))) == value(string("AAA"))); + assert(hasContent(put(k, string("aaa"), pg))); - assert((get(k, pg)) == value(string("aaa"))); + assert(content(get(k, pg)) == value(string("aaa"))); assert(hasContent(del(k, pg))); assert(!hasContent(get(k, pg))); 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 bool testGetPerf() { const value k = mklist("c"); PGSql pg("host=localhost port=6432 dbname=db", "test"); assert(hasContent(post(k, string("CCC"), pg))); - const lambda gl = getLoop(k, pg); + const blambda gl = [k, pg]() -> const bool { + assert(content(get(k, pg)) == value(string("CCC"))); + return true; + }; cout << "PGSql get test " << time(gl, 5, 200) << " ms" << endl; return true; } diff --git a/sca-cpp/trunk/components/sqldb/pgsql.hpp b/sca-cpp/trunk/components/sqldb/pgsql.hpp index 581cd943e6..620aec4105 100644 --- a/sca-cpp/trunk/components/sqldb/pgsql.hpp +++ b/sca-cpp/trunk/components/sqldb/pgsql.hpp @@ -40,7 +40,7 @@ namespace pgsql { /** * Return and clear a Postgres result failure. */ -const string pgfailure(PGresult* r, PGconn* conn) { +const string pgfailure(PGresult* const r, PGconn* const conn) { const string re = PQresultErrorMessage(r); PQclear(r); if (length(re) != 0) @@ -68,11 +68,12 @@ public: mkfailure(string("Couldn't connect to postgresql database: ") + PQerrorMessage(conn)); return; } + debug(conn, "pgsql::pgsql::conn"); // 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)); + PGresult* const kr = PQexec(conn, c_str(ks)); if (PQresultStatus(kr) != PGRES_TUPLES_OK) { mkfailure(string("Couldn't execute postgresql column select statement: ") + pgfailure(kr, conn)); return; @@ -82,25 +83,16 @@ public: mkfailure(string("Couldn't find postgresql table key and value column names")); return; } - kname = PQgetvalue(kr, 0, 0); - vname = PQgetvalue(kr, 1, 0); + kname = c_str(string(PQgetvalue(kr, 0, 0))); + vname = c_str(string(PQgetvalue(kr, 1, 0))); PQclear(kr); } - PGSql(const PGSql& c) : owner(false), conn(c.conn), conninfo(c.conninfo), table(c.table) { + PGSql(const PGSql& c) : owner(false), conn(c.conn), conninfo(c.conninfo), table(c.table), kname(c.kname), vname(c.vname) { debug("pgsql::pgsql::copy"); } - const PGSql& operator=(const PGSql& c) { - debug("pgsql::pgsql::operator="); - if(this == &c) - return *this; - owner = false; - conn = c.conn; - conninfo = c.conninfo; - table = c.table; - return *this; - } + PGSql& operator=(const PGSql& c) = delete; ~PGSql() { debug("pgsql::~pgsql"); @@ -108,16 +100,17 @@ public: return; if (conn == NULL) return; + debug(conn, "pgsql::~pgsql::conn"); PQfinish(conn); } private: - bool owner; + const bool owner; PGconn *conn; - string conninfo; - string table; - string kname; - string vname; + const string conninfo; + const string table; + const char* kname; + const char* vname; friend const failable setup(const PGSql& pgsql); friend const failable post(const value& key, const value& val, const PGSql& pgsql); @@ -133,7 +126,7 @@ const failable setup(const PGSql& pgsql) { debug("pgsql::setup"); if (PQstatus(pgsql.conn) == CONNECTION_OK) return true; - debug("pgsql::setup::reset"); + debug(pgsql.conn, "pgsql::setup::reset::conn"); PQreset(pgsql.conn); if (PQstatus(pgsql.conn) != CONNECTION_OK) return mkfailure(string("Couldn't reconnect to postgresql database: ") + PQerrorMessage(pgsql.conn)); @@ -150,10 +143,10 @@ const failable post(const value& key, const value& val, const PGSql& pgsql 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 = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); + const char* const params[2] = { c_str(ks), c_str(vs) }; + PGresult* const 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(string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(r, pgsql.conn)); PQclear(r); @@ -172,10 +165,10 @@ const failable put(const value& key, const value& val, const PGSql& pgsql) 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 = 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); + const string ks(write(content(scheme::writeValue(key)))); + const string vs(write(content(scheme::writeValue(val)))); + const char* const params[2] = { c_str(ks), c_str(vs) }; + PGresult* const 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(string("Couldn't execute update postgresql SQL statement: ") + pgfailure(r, pgsql.conn)); const string t = PQcmdTuples(r); @@ -186,7 +179,7 @@ const failable put(const value& key, const value& val, const PGSql& pgsql) } PQclear(r); - PGresult* pr = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0); + PGresult* const 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(string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(pr, pgsql.conn)); PQclear(pr); @@ -196,7 +189,58 @@ const failable put(const value& key, const value& val, const PGSql& pgsql) } /** - * Get an item from the database. + * Convert a key to an item id. + */ +const list keyid(const list& key) { + if (isNil(key)) + return nilListValue; + if (isList(car(key))) + return keyid(cdr(key)); + return cons(car(key), keyid(cdr(key))); +} + +/** + * Convert a key to an param name / value assoc. + */ +const list > keyparams(const list& key) { + if (isNil(key)) + return nilListValue; + if (!isList(car(key))) + return keyparams(cdr(key)); + return cons >((list)car(key), keyparams(cdr(key))); +} + +/** + * Convert a get result to a list of items. + */ +const list getitems(PGresult* const r, const int i, const int n) { + if (i == n) + return nilListValue; + const value key(content(scheme::readValue(string(PQgetvalue(r, i, 0))))); + const value val(content(scheme::readValue(string(PQgetvalue(r, i, 1))))); + return cons(mklist(key, val), getitems(r, i + 1, n)); +} + +/** + * Parse a text search query and translate single quotes to spaces and double + * quotes to single quotes. + */ +ostringstream& tsparse(ostringstream& os, const char* const c) { + if (!*c) + return os; + os << (*c == '\''? ' ' : *c == '"'? '\'' : *c); + return tsparse(os, c + 1); +} +const string tstranslate(const string& ts) { + ostringstream os; + tsparse(os, c_str(ts)); + return str(os); +} + +/** + * Get one item or a collection of items from the database. + * The key is a simple value or a list of simple values plus optional name / value + * pairs to specify regex, like, textsearch limit and offset clause */ const failable get(const value& key, const PGSql& pgsql) { debug(key, "pgsql::get::key"); @@ -204,21 +248,99 @@ const failable get(const value& key, const PGSql& pgsql) { debug(pgsql.table, "pgsql::get::table"); setup(pgsql); - const string ks(scheme::writeValue(key)); - const char* params[1] = { c_str(ks) }; - PGresult* r = PQexecParams(pgsql.conn, c_str(string("select * from ") + pgsql.table + string(" where ") + pgsql.kname + string(" = $1;")), 1, NULL, params, NULL, NULL, 0); + // Get item and id and get parameters from the key + const bool lk = isList(key); + const list > kparams = lk? keyparams(key) : list >(); + const list regex = assoc("regex", kparams); + const list like = assoc("like", kparams); + const list textsearch = assoc("textsearch", kparams); + const list limit = assoc("limit", kparams); + const list offset = assoc("offset", kparams); + const list id = lk? keyid(key) : nilListValue; + const list atable = assoc("table", kparams); + const string table = isNil(atable)? pgsql.table : (string)cadr(atable); + const list akname = assoc("kcolumn", kparams); + const string kname = isNil(akname)? pgsql.kname : (string)cadr(akname); + const list avname = assoc("vcolumn", kparams); + const string vname = isNil(avname)? pgsql.vname : (string)cadr(avname); + + // Build the SQL query + const char* sqlparams[5]; + int p = 0; + int w = 0; + ostringstream sqlos; + sqlos << "select data.*"; + if (!isNil(textsearch)) { + // Text search, setup result ranking + sqlos << ", ts_rank_cd(to_tsvector(data." << vname << "), tsquery, 32) as rank"; + } + sqlos << " from " << table << " data"; + if (!isNil(textsearch)) { + // Text search, define the query + const string ts = tstranslate((string)cadr(textsearch)); + sqlparams[p++] = c_str(ts); + sqlos << ", plainto_tsquery($" << p << ") tsquery"; + } + if (!lk || !isNil(id)) { + // Query of the form key = id + sqlparams[p++] = c_str(write(content(scheme::writeValue(lk? (value)id : key)))); + sqlos << (w == 0? " where" : " and"); + sqlos << " data." << kname << " = $" << p; + w++; + } + if (!isNil(regex)) { + // Query of the form key ~ param + sqlparams[p++] = c_str((string)cadr(regex)); + sqlos << (w == 0? " where" : " and"); + sqlos << " data." << kname << " ~ $" << p; + w++; + } + if (!isNil(like)) { + // Query of the form key like param + sqlparams[p++] = c_str((string)cadr(like)); + sqlos << (w == 0? " where" : " and"); + sqlos << " data." << kname << " like $" << p; + w++; + } + if (!isNil(textsearch)) { + // Text search, apply the query + sqlos << (w == 0? " where" : " and"); + sqlos << " tsquery @@ to_tsvector(data." << vname << ") order by rank desc"; + w++; + } + if (!isNil(offset)) { + // Result pagination offset + sqlos << " offset " << atoi(c_str((string)cadr(offset))); + } + // Result limit count + const int l = isNil(limit)? 1 : atoi(c_str((string)cadr(limit))); + sqlos << " limit " << l << ";"; + + // Execute the query + const string sqls = str(sqlos); + debug(sqls, "pgsql::get::sqls"); + PGresult* r = PQexecParams(pgsql.conn, c_str(sqls), p, NULL, sqlparams, NULL, NULL, 0); if (PQresultStatus(r) != PGRES_TUPLES_OK) return mkfailure(string("Couldn't execute select postgresql SQL statement: ") + pgfailure(r, pgsql.conn)); - if (PQntuples(r) < 1) { + const int n = PQntuples(r); + if (n < 1) { PQclear(r); ostringstream os; os << "Couldn't get postgresql entry: " << key; return mkfailure(str(os), 404, false); } - const char* data = PQgetvalue(r, 0, 1); - const value val(scheme::readValue(string(data))); - PQclear(r); + // Return a collection of key / item pairs + if (l != 1) { + const list lval = getitems(r, 0, n); + PQclear(r); + debug(lval, "pgsql::get::result"); + return (value)lval; + } + + // Return a single item + const value val(content(scheme::readValue(string(PQgetvalue(r, 0, 1))))); + PQclear(r); debug(val, "pgsql::get::result"); return val; } @@ -232,9 +354,9 @@ const failable del(const value& key, const PGSql& pgsql) { debug(pgsql.table, "pgsql::delete::table"); setup(pgsql); - const string ks(scheme::writeValue(key)); - const char* params[1] = { c_str(ks) }; - PGresult* r = PQexecParams(pgsql.conn, c_str(string("delete from ") + pgsql.table + string(" where ") + pgsql.kname + string(" = $1;")), 1, NULL, params, NULL, NULL, 0); + const string ks(write(content(scheme::writeValue(key)))); + const char* const params[1] = { c_str(ks) }; + PGresult* const 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(string("Couldn't execute delete postgresql SQL statement: ") + pgfailure(r, pgsql.conn)); PQclear(r); diff --git a/sca-cpp/trunk/components/sqldb/sqldb.cpp b/sca-cpp/trunk/components/sqldb/sqldb.cpp index 9925897693..1288dd553b 100644 --- a/sca-cpp/trunk/components/sqldb/sqldb.cpp +++ b/sca-cpp/trunk/components/sqldb/sqldb.cpp @@ -38,14 +38,14 @@ namespace sqldb { /** * Get an item from the database. */ -const failable get(const list& params, pgsql::PGSql& pg) { +const failable get(const list& params, const pgsql::PGSql& pg) { return pgsql::get(car(params), pg); } /** * Post an item to the database. */ -const failable post(const list& params, pgsql::PGSql& pg) { +const failable post(const list& params, const pgsql::PGSql& pg) { const value id = append(car(params), mklist(mkuuid())); const failable val = pgsql::post(id, cadr(params), pg); if (!hasContent(val)) @@ -56,7 +56,7 @@ const failable post(const list& params, pgsql::PGSql& pg) { /** * Put an item into the database. */ -const failable put(const list& params, pgsql::PGSql& pg) { +const failable put(const list& params, const pgsql::PGSql& pg) { const failable val = pgsql::put(car(params), cadr(params), pg); if (!hasContent(val)) return mkfailure(val); @@ -66,7 +66,7 @@ const failable put(const list& params, pgsql::PGSql& pg) { /** * Delete an item from the database. */ -const failable del(const list& params, pgsql::PGSql& pg) { +const failable del(const list& params, const pgsql::PGSql& pg) { const failable val = pgsql::del(car(params), pg); if (!hasContent(val)) return mkfailure(val); @@ -74,14 +74,23 @@ const failable del(const list& params, pgsql::PGSql& pg) { } /** - * Component implementation lambda function. + * Start the component. */ -class applySqldb { -public: - applySqldb(const perthread_ptr& pg) : pg(pg) { - } +const failable start(const list& params) { + // Connect to the configured database and table + debug("sqldb::start"); + const gc_pool cp(gc_current_pool()); + const value conninfo = ((lvvlambda)car(params))(nilListValue); + const value table = ((lvvlambda)cadr(params))(nilListValue); + const lambda()> newPGSql = [conninfo, table, cp]() -> const gc_ptr { + debug("sqldb::newPGSql"); + const gc_scoped_pool sp(pool(cp)); + return new (gc_new()) pgsql::PGSql(conninfo, table); + }; + const perthread_ptr pg = *(new (gc_new >()) perthread_ptr(newPGSql)); - const value operator()(const list& params) const { + // Return the component implementation lambda function + const lvvlambda applySqldb = [pg](const list& params) -> const value { const value func(car(params)); if (func == "get") return get(cdr(params), *pg); @@ -92,40 +101,8 @@ public: if (func == "delete") return del(cdr(params), *pg); return mkfailure(); - } - -private: - const perthread_ptr pg; -}; - -/** - * Lambda function that creates a new database connection. - */ -class newPGSql { -public: - newPGSql(const string& conninfo, const string& table) : conninfo(conninfo), table(table) { - } - - const gc_ptr operator()() const { - return new (gc_new()) pgsql::PGSql(conninfo, table); - } - -private: - const string conninfo; - const string table; -}; - -/** - * Start the component. - */ -const failable start(unused const list& params) { - // Connect to the configured database and table - const value conninfo = ((lambda&)>)car(params))(list()); - const value table = ((lambda&)>)cadr(params))(list()); - const perthread_ptr pg(lambda()>(newPGSql(conninfo, table))); - - // Return the component implementation lambda function - return value(lambda&)>(applySqldb(pg))); + }; + return value(applySqldb); } } diff --git a/sca-cpp/trunk/components/webservice/Makefile.am b/sca-cpp/trunk/components/webservice/Makefile.am index 242b97dce8..3b5a53695e 100644 --- a/sca-cpp/trunk/components/webservice/Makefile.am +++ b/sca-cpp/trunk/components/webservice/Makefile.am @@ -62,10 +62,11 @@ axis2_test_SOURCES = axis2-test.cpp axis2_test_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil +client_test_LDFLAGS = -lxml2 -lcurl -ljansson -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil dist_noinst_SCRIPTS = echo-test server-test noinst_PROGRAMS = axiom-test axis2-test client-test -TESTS = axiom-test echo-test server-test +#TESTS = axiom-test echo-test server-test +TESTS = axiom-test endif diff --git a/sca-cpp/trunk/components/webservice/axiom-test.cpp b/sca-cpp/trunk/components/webservice/axiom-test.cpp index 75ce2452fd..eaa9921d1b 100644 --- a/sca-cpp/trunk/components/webservice/axiom-test.cpp +++ b/sca-cpp/trunk/components/webservice/axiom-test.cpp @@ -45,11 +45,11 @@ const string customerElement = "45673000" ""; -const string echo("\n" - " Hello World!\n" +const string echo("" + "Hello World!" ""); -bool testAxiom() { +const bool testAxiom() { const Axis2Context ax; { const failable n = stringToAxiomNode(customerElement, ax); @@ -60,9 +60,9 @@ bool testAxiom() { } { const list arg = mklist( - list() + "ns1:echoString" - + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) - + (list() + "text" + string("Hello World!"))); + nilListValue + "ns1:echoString" + + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + + (nilListValue + "text" + string("Hello World!"))); const failable n = valuesToAxiomNode(arg, ax); assert(hasContent(n)); const failable x = axiomNodeToString(content(n), ax); diff --git a/sca-cpp/trunk/components/webservice/axis2-dispatcher.cpp b/sca-cpp/trunk/components/webservice/axis2-dispatcher.cpp index dafa6fd229..7a0869d20f 100644 --- a/sca-cpp/trunk/components/webservice/axis2-dispatcher.cpp +++ b/sca-cpp/trunk/components/webservice/axis2-dispatcher.cpp @@ -105,7 +105,7 @@ const axis2_module_ops_t dispatchOps = { dispatchFuncMap }; -axis2_module_t * dispatchModule(const axutil_env_t* env) { +axis2_module_t* dispatchModule(const axutil_env_t* env) { axis2_module_t *module = (axis2_module_t*)AXIS2_MALLOC(env->allocator, sizeof(axis2_module_t)); if (module == NULL) return NULL; diff --git a/sca-cpp/trunk/components/webservice/axis2-service.cpp b/sca-cpp/trunk/components/webservice/axis2-service.cpp index 4df0543370..41cce080b5 100644 --- a/sca-cpp/trunk/components/webservice/axis2-service.cpp +++ b/sca-cpp/trunk/components/webservice/axis2-service.cpp @@ -50,7 +50,7 @@ int AXIS2_CALL serviceFree(axis2_svc_skeleton_t* svc_skeleton, const axutil_env_ typedef struct axis2_apache2_out_transport_info { axis2_http_out_transport_info_t out_transport_info; - request_rec *request; + request_rec* request; axis2_char_t *encoding; } axis2_apache2_out_transport_info_t; @@ -66,25 +66,25 @@ axiom_node_t *AXIS2_CALL serviceInvoke(unused axis2_svc_skeleton_t* svc_skeleton // Check that we have an input node if (node == NULL || axiom_node_get_node_type(node, env) != AXIOM_ELEMENT) return NULL; - axiom_element_t *e = (axiom_element_t *) axiom_node_get_data_element(node, env); + axiom_element_t* const e = (axiom_element_t*) axiom_node_get_data_element(node, env); if (e == NULL) return NULL; // Get the function name - const char* func = axiom_element_get_localname(e, env); + const char* const func = axiom_element_get_localname(e, env); if (func == NULL) return NULL; // Get the target endpoint address - const axis2_endpoint_ref_t* epr = axis2_msg_ctx_get_from(msg_ctx, env); + const axis2_endpoint_ref_t* const epr = axis2_msg_ctx_get_from(msg_ctx, env); if (epr == NULL) return NULL; - string address = axis2_endpoint_ref_get_address(epr, env); + unused const string address = axis2_endpoint_ref_get_address(epr, env); // Get the underlying HTTPD request - axis2_out_transport_info_t* tinfo = axis2_msg_ctx_get_out_transport_info(msg_ctx, env); - axis2_apache2_out_transport_info_t* httpinfo = (axis2_apache2_out_transport_info_t*)tinfo; - request_rec* r = httpinfo->request; + axis2_out_transport_info_t* const tinfo = axis2_msg_ctx_get_out_transport_info(msg_ctx, env); + axis2_apache2_out_transport_info_t* const httpinfo = (axis2_apache2_out_transport_info_t*)tinfo; + request_rec* const r = httpinfo->request; debug_httpdRequest(r, "webservice::serviceInvoke"); // Parse the request Axiom node and construct request expression @@ -96,9 +96,9 @@ axiom_node_t *AXIS2_CALL serviceInvoke(unused axis2_svc_skeleton_t* svc_skeleton debug(expr, "webservice::serviceInvoke::expr"); // Retrieve the target lambda function from the HTTPD request and invoke it - const value* rv = const_cast((value*)ap_get_module_config(r->request_config, &axis2_module)); + const value* const rv = const_cast((value*)ap_get_module_config(r->request_config, &axis2_module)); cout << "relay: " << rv << endl; - const lambda&)> relay = *rv; + const lvvlambda relay = *rv; const value res = relay(expr); debug(res, "webservice::serviceInvoke::result"); diff --git a/sca-cpp/trunk/components/webservice/axis2-test.cpp b/sca-cpp/trunk/components/webservice/axis2-test.cpp index d7c2f3b671..69723aa6b3 100644 --- a/sca-cpp/trunk/components/webservice/axis2-test.cpp +++ b/sca-cpp/trunk/components/webservice/axis2-test.cpp @@ -36,22 +36,23 @@ namespace tuscany { namespace webservice { -bool testEval() { +const bool testEval() { const Axis2Context ax; const value func = "http://ws.apache.org/axis2/c/samples/echoString"; const list arg = mklist( - list() + "ns1:echoString" - + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) - + (list() + "text" + string("Hello World!"))); + nilListValue + "ns1:echoString" + + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + + (nilListValue + "text" + string("Hello World!"))); const failable rval = evalExpr(mklist(func, arg, string("http://localhost:9090/axis2/services/echo")), ax); assert(hasContent(rval)); const list r = mklist( - list() + "ns1:echoString" - + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples")) - + (list() + "text" + string("Hello World!"))); + nilListValue + "ns1:echoString" + + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples")) + + (nilListValue + "text" + string("Hello World!"))); + cerr << content(rval) << endl; assert(content(rval) == r); return true; diff --git a/sca-cpp/trunk/components/webservice/axis2.hpp b/sca-cpp/trunk/components/webservice/axis2.hpp index 9bad109ff0..fd4d1f9a02 100644 --- a/sca-cpp/trunk/components/webservice/axis2.hpp +++ b/sca-cpp/trunk/components/webservice/axis2.hpp @@ -46,8 +46,8 @@ #include "sstream.hpp" #include "list.hpp" #include "value.hpp" -#include "xml.hpp" #include "monad.hpp" +#include "../../modules/xml/xml.hpp" namespace tuscany { namespace webservice { @@ -65,16 +65,9 @@ public: debug("webservice::axis2context::copy"); } - const Axis2Context& operator=(const Axis2Context& ax) { - debug("webservice::axis2context::operator="); - if(this == &ax) - return *this; - env = ax.env; - owner = false; - return *this; - } + Axis2Context& operator=(const Axis2Context& ax) = delete; - Axis2Context(const axutil_env_t* env) : env(const_cast(env)), owner(false) { + Axis2Context(const axutil_env_t* const env) : env(const_cast(env)), owner(false) { debug("webservice::axis2context::env"); } @@ -86,13 +79,13 @@ public: } private: - axutil_env_t* env; - bool owner; + axutil_env_t* const env; + const bool owner; - friend const axutil_env_t* env(const Axis2Context& ax); + friend const axutil_env_t* const env(const Axis2Context& ax); }; -const axutil_env_t* env(const Axis2Context& ax) { +const axutil_env_t* const env(const Axis2Context& ax) { return ax.env; } @@ -109,7 +102,7 @@ const string axis2Error(const Axis2Context& ax) { * Convert a string to an Axiom node. */ const failable stringToAxiomNode(const string& s, const Axis2Context& ax) { - axiom_node_t* node = axiom_node_create_from_buffer(env(ax), const_cast(c_str(s))); + axiom_node_t* const node = axiom_node_create_from_buffer(env(ax), const_cast(c_str(s))); if (node == NULL) return mkfailure(string("Couldn't convert XML to Axiom node: ") + axis2Error(ax)); return node; @@ -119,7 +112,7 @@ const failable stringToAxiomNode(const string& s, const Axis2Cont * Convert a list of values representing XML elements to an Axiom node. */ const failable valuesToAxiomNode(const list& l, const Axis2Context& ax) { - const failable > xml = writeXML(valuesToElements(l), false); + const failable > xml = xml::writeElements(valuesToElements(l), false); if (!hasContent(xml)) return mkfailure(xml); ostringstream os; @@ -130,8 +123,8 @@ const failable valuesToAxiomNode(const list& l, const Axis /** * Convert an axiom node to a string. */ -const failable axiomNodeToString(axiom_node_t* node, const Axis2Context& ax) { - const char* c = axiom_node_to_string(node, env(ax)); +const failable axiomNodeToString(axiom_node_t* const node, const Axis2Context& ax) { + const char* const c = axiom_node_to_string(node, env(ax)); if (c == NULL) return mkfailure(string("Couldn't convert Axiom node to XML: ") + axis2Error(ax)); const string s(c); @@ -142,12 +135,12 @@ const failable axiomNodeToString(axiom_node_t* node, const Axis2Co /** * Convert an axiom node to a list of values representing XML elements. */ -const failable > axiomNodeToValues(axiom_node_t* node, const Axis2Context& ax) { +const failable > axiomNodeToValues(axiom_node_t* const node, const Axis2Context& ax) { const failable s = axiomNodeToString(node, ax); if (!hasContent(s)) return mkfailure >(s); istringstream is(content(s)); - const failable > l = readXML(streamList(is)); + const failable > l = content(xml::readElements(streamList(is))); if (!hasContent(l)) return l; return elementsToValues(content(l)); @@ -166,11 +159,11 @@ const failable evalExpr(const value& expr, const Axis2Context& ax) { const value uri(caddr(expr)); // Create Axis2 client - axis2_svc_client_t *client = axis2_svc_client_create(env(ax), getenv("AXIS2C_HOME")); + axis2_svc_client_t* const client = axis2_svc_client_create(env(ax), getenv("AXIS2C_HOME")); if (client == NULL) return mkfailure("Couldn't create Axis2 client: " + axis2Error(ax)); - axis2_endpoint_ref_t *epr = axis2_endpoint_ref_create(env(ax), c_str(uri)); - axis2_options_t *opt = axis2_options_create(env(ax)); + axis2_endpoint_ref_t* const epr = axis2_endpoint_ref_create(env(ax), c_str(uri)); + axis2_options_t* const opt = axis2_options_create(env(ax)); axis2_options_set_to(opt, env(ax), epr); axis2_options_set_action(opt, env(ax), (const axis2_char_t*)c_str(func)); axis2_svc_client_set_options(client, env(ax), opt); @@ -182,7 +175,7 @@ const failable evalExpr(const value& expr, const Axis2Context& ax) { return mkfailure(req); // Call the Web service - axiom_node_t* res = axis2_svc_client_send_receive(client, env(ax), content(req)); + axiom_node_t* const res = axis2_svc_client_send_receive(client, env(ax), content(req)); if (res == NULL) { axis2_svc_client_free(client, env(ax)); return mkfailure("Couldn't invoke Axis2 service: " + axis2Error(ax)); diff --git a/sca-cpp/trunk/components/webservice/client-test.cpp b/sca-cpp/trunk/components/webservice/client-test.cpp index 16dd659b22..ca009b9594 100644 --- a/sca-cpp/trunk/components/webservice/client-test.cpp +++ b/sca-cpp/trunk/components/webservice/client-test.cpp @@ -38,43 +38,43 @@ namespace tuscany { namespace webservice { -bool testModAxis2() { +const bool testModAxis2() { const Axis2Context ax; const value func = "http://ws.apache.org/axis2/c/samples/echoString"; const list arg = mklist( - list() + "ns1:echoString" - + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) - + (list() + "text" + string("Hello World!"))); + nilListValue + "ns1:echoString" + + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + + (nilListValue + "text" + string("Hello World!"))); const failable rval = evalExpr(mklist(func, arg, string("http://localhost:8090/echo-listener")), ax); assert(hasContent(rval)); const list r = mklist( - list() + "ns1:echoString" - + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) - + (list() + "text" + string("Hello World!"))); + nilListValue + "ns1:echoString" + + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + + (nilListValue + "text" + string("Hello World!"))); assert(content(rval) == r); return true; } -bool testEval() { - http::CURLSession cs("", "", "", ""); +const bool testEval() { + const http::CURLSession cs("", "", "", "", 0); const value func = "http://ws.apache.org/axis2/c/samples/echoString"; const list arg = mklist( - list() + "ns1:echoString" - + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) - + (list() + "text" + string("Hello World!"))); + nilListValue + "ns1:echoString" + + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + + (nilListValue + "text" + string("Hello World!"))); const failable rval = http::evalExpr(mklist(func, arg), "http://localhost:8090/echo-client", cs); assert(hasContent(rval)); const list r = mklist( - list() + "ns1:echoString" - + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples")) - + (list() + "text" + string("Hello World!"))); + nilListValue + "ns1:echoString" + + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples")) + + (nilListValue + "text" + string("Hello World!"))); assert(content(rval) == r); return true; } diff --git a/sca-cpp/trunk/components/webservice/echo-test b/sca-cpp/trunk/components/webservice/echo-test index 1056a6c668..a7bc636cab 100755 --- a/sca-cpp/trunk/components/webservice/echo-test +++ b/sca-cpp/trunk/components/webservice/echo-test @@ -20,6 +20,7 @@ # Setup axis2_prefix=`cat axis2c.prefix` export AXIS2C_HOME=$axis2_prefix +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$axis2_prefix/lib axis2="$axis2_prefix/bin/axis2_http_server" pwd=`pwd` cd "$axis2_prefix/bin" diff --git a/sca-cpp/trunk/components/webservice/server-test b/sca-cpp/trunk/components/webservice/server-test index cb12accbfb..5e3b18b376 100755 --- a/sca-cpp/trunk/components/webservice/server-test +++ b/sca-cpp/trunk/components/webservice/server-test @@ -33,6 +33,7 @@ EOF axis2_prefix=`cat axis2c.prefix` export AXIS2C_HOME=$axis2_prefix +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$axis2_prefix/lib axis2="$axis2_prefix/bin/axis2_http_server" pwd=`pwd` cd "$axis2_prefix/bin" diff --git a/sca-cpp/trunk/components/webservice/webservice-client.cpp b/sca-cpp/trunk/components/webservice/webservice-client.cpp index 76d4905bf8..bece0b3b3a 100644 --- a/sca-cpp/trunk/components/webservice/webservice-client.cpp +++ b/sca-cpp/trunk/components/webservice/webservice-client.cpp @@ -42,10 +42,10 @@ const failable apply(const value& func, const list& params) { // Extract parameters const value doc = car(params); - const lambda&)> l = cadr(params); + const lvvlambda l = cadr(params); // Call the URI property lambda function to get the configured URI - const value uri = l(list()); + const value uri = l(nilListValue); // Evaluate using Axis2 return evalExpr(mklist(func, doc, uri), ax); diff --git a/sca-cpp/trunk/components/webservice/webservice-listener.cpp b/sca-cpp/trunk/components/webservice/webservice-listener.cpp index 29ebef4bcb..f9c18f293a 100644 --- a/sca-cpp/trunk/components/webservice/webservice-listener.cpp +++ b/sca-cpp/trunk/components/webservice/webservice-listener.cpp @@ -44,10 +44,10 @@ extern "C" { extern module axis2_module; } -const value redirectToAxis2(const string& uri, request_rec* r, const value& relay) { - const failable nr = httpd::internalRedirectRequest(uri, r); +const failable redirectToAxis2(const string& uri, request_rec* const r, const value& relay) { + const failable nr = httpd::internalRedirectRequest(uri, r); if (!hasContent(nr)) - return value(reason(nr), rcode(nr)); + return mkfailure(reason(nr), rcode(nr)); ap_set_module_config(content(nr)->request_config, &axis2_module, const_cast((const void*)&relay)); return value(httpd::internalRedirect(content(nr))); } @@ -58,7 +58,7 @@ const value redirectToAxis2(const string& uri, request_rec* r, const value& rela const failable handle(const list& params) { // Extract HTTPD request from the params - request_rec* r = httpd::request(car(params)); + request_rec* const r = httpd::request(car(params)); debug_httpdRequest(r, "webservice::handle"); // Extract the relay lambda from the params and store it in the HTTPD request, @@ -67,7 +67,7 @@ const failable handle(const list& params) { cout << "relay: " << &relay << endl; // Redirect HTTPD request to Mod-axis2 - return redirectToAxis2(string("/axis2") + r->uri + r->args != NULL? string("?") + r->args : string(""), r, relay); + return redirectToAxis2(string("/axis2") + r->uri + r->args != NULL? string("?") + r->args : emptyString, r, relay); } } diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac index e3f3de7e61..eb626c710a 100644 --- a/sca-cpp/trunk/configure.ac +++ b/sca-cpp/trunk/configure.ac @@ -119,7 +119,7 @@ AC_ARG_ENABLE(maintainer-mode, [AS_HELP_STRING([--enable-maintainer-mode], [comp if test "${want_maintainer_mode}" = "true"; then cxxflags="${cxxflags} -ggdb -g3 -Werror -Wall -Wextra -Wno-ignored-qualifiers -Wno-strict-aliasing -Winit-self -Wmissing-include-dirs -Wcast-qual -Wcast-align -Wwrite-strings -Wpointer-arith -Waddress -Wredundant-decls -std=c++0x -fmessage-length=0" if test "${cxxtype}" = "clang"; then - cxxflags="${cxxflags} -O1 -stdlib=libc++" + cxxflags="${cxxflags} -O2 -stdlib=libc++ -Qunused-arguments -Wno-return-type-c-linkage" else cxxflags="${cxxflags} -O2 -Wlogical-op -Wconversion" fi @@ -128,7 +128,7 @@ if test "${want_maintainer_mode}" = "true"; then else cxxflags="${cxxflags} -g -std=c++0x -fmessage-length=0" if test "${cxxtype}" = "clang"; then - cxxflags="${cxxflags} -O1 -stdlib=libc++" + cxxflags="${cxxflags} -O2 -stdlib=libc++ -Qunused-arguments" else cxxflags="${cxxflags} -O2" fi @@ -286,28 +286,21 @@ AC_SUBST(LIBXML2_LIB) LIBS="-L${LIBXML2_LIB} ${defaultlibs}" AC_CHECK_LIB([xml2], [xmlInitParser], [], [AC_MSG_ERROR([couldn't find a suitable libxml2, use --with-libxml2=PATH])]) -# Configure path to libmozjs includes and lib. -AC_MSG_CHECKING([for js-include]) -AC_ARG_WITH([js-include], [AC_HELP_STRING([--with-js-include=PATH], [path to installed SpiderMonkey include dir - [default=/usr/include]])], [ - JS_INCLUDE="${withval}" +# Configure path to jansson includes and lib. +AC_MSG_CHECKING([for jansson]) +AC_ARG_WITH([jansson], [AC_HELP_STRING([--with-jansson=PATH], [path to installed jansson [default=/usr]])], [ + JANSSON_INCLUDE="${withval}/include" + JANSSON_LIB="${withval}/lib" AC_MSG_RESULT("${withval}") ], [ - JS_INCLUDE="/usr/include" - AC_MSG_RESULT(/usr/include) -]) -AC_MSG_CHECKING([for js-lib]) -AC_ARG_WITH([js-lib], [AC_HELP_STRING([--with-js-lib=PATH], [path to installed SpiderMonkey lib dir [default=/usr/lib]])], [ - JS_LIB="${withval}" - AC_MSG_RESULT("${withval}") -], [ - JS_LIB="/usr/lib" - AC_MSG_RESULT(/usr/lib) + JANSSON_INCLUDE="/usr/include" + JANSSON_LIB="/usr/lib" + AC_MSG_RESULT(/usr) ]) -AC_SUBST(JS_INCLUDE) -AC_SUBST(JS_LIB) -LIBS="-L${JS_LIB} ${defaultlibs}" -AC_CHECK_LIB([mozjs], [JS_NewContext], [], [AC_MSG_ERROR([couldn't find a suitable libmozjs, use --with-js-lib=PATH])]) +AC_SUBST(JANSSON_INCLUDE) +AC_SUBST(JANSSON_LIB) +LIBS="-L${JANSSON_LIB} ${defaultlibs}" +AC_CHECK_LIB([jansson], [json_loads], [], [AC_MSG_ERROR([couldn't find a suitable libjansson, use --with-jansson=PATH])]) # Configure path to Apache APR and HTTPD includes and libs. AC_MSG_CHECKING([for apr]) @@ -411,9 +404,9 @@ LIBS="-L${TINYCDB_LIB} ${defaultlibs}" AC_CHECK_LIB([cdb], [cdb_make_start], [], [AC_MSG_ERROR([couldn't find a suitable libcdb, use --with-tinycdb=PATH])]) # Configure default includes and ldflags -cxxflags="${cxxflags} ${INCLUDES} -I. -I${TUSCANY_SCACPP}/kernel -I${APR_INCLUDE} -I${APRUTIL_INCLUDE} -I${HTTPD_INCLUDE} -I${LIBXML2_INCLUDE} -I${JS_INCLUDE} -I${LIBCURL_INCLUDE}" +cxxflags="${cxxflags} ${INCLUDES} -I. -I${TUSCANY_SCACPP}/kernel -I${APR_INCLUDE} -I${APRUTIL_INCLUDE} -I${HTTPD_INCLUDE} -I${LIBXML2_INCLUDE} -I${JANSSON_INCLUDE} -I${LIBCURL_INCLUDE}" ldflags="${ldflags} -ldl -L${APR_LIB} -R${APR_LIB} -lapr-1 -L${APRUTIL_LIB} -R${APRUTIL_LIB} -laprutil-1" -ldflags="${ldflags} -L${LIBCURL_LIB} -R${LIBCURL_LIB} -L${JS_LIB} -R${JS_LIB} -L${LIBXML2_LIB} -R${LIBXML2_LIB}" +ldflags="${ldflags} -L${LIBCURL_LIB} -R${LIBCURL_LIB} -L${JANSSON_LIB} -R${JANSSON_LIB} -L${LIBXML2_LIB} -R${LIBXML2_LIB}" # Enable Python support. AC_MSG_CHECKING([whether to enable Python support]) @@ -597,7 +590,7 @@ if test "${want_java}" = "true"; then # IBM J9 VM AC_MSG_NOTICE([checking for J9 Java VM]) JAVA_LIBJVM=`dirname "${JAVA_LIBJVM_SO}"` - JAVA_CHECK_LIB="-L${JAVA_LIBJAVA} -R${JAVA_LIBJAVA} -L${JAVA_LIBJVM} -R${JAVA_LIBJVM}" + JAVA_CHECK_LIB="-L${JAVA_LIBJAVA} -Wl,-R${JAVA_LIBJAVA} -L${JAVA_LIBJVM} -Wl,-R${JAVA_LIBJVM}" LIBS="${JAVA_CHECK_LIB} ${defaultlibs}" AC_CHECK_LIB([java], [JNI_CreateJavaVM], [JAVA_LDFLAGS="${JAVA_CHECK_LIB} -ljava -ljvm -ljsig"], [], [-ljvm -ljsig]) if test "${JAVA_LDFLAGS}" != ""; then @@ -609,7 +602,7 @@ if test "${want_java}" = "true"; then JAVA_LIBJVM_SO=`find ${JAVA_PREFIX}/jre/lib -name libjvm.so | grep server` JAVA_LIBJVM=`dirname "${JAVA_LIBJVM_SO}"` AC_MSG_NOTICE([libjava ${JAVA_LIBJAVA} libjvm ${LIBJVM}]) - JAVA_CHECK_LIB="-L${JAVA_LIBJAVA} -R${JAVA_LIBJAVA} -L${JAVA_LIBJVM} -R${JAVA_LIBJVM}" + JAVA_CHECK_LIB="-L${JAVA_LIBJAVA} -Wl,-R${JAVA_LIBJAVA} -L${JAVA_LIBJVM} -Wl,-R${JAVA_LIBJVM}" LIBS="${JAVA_CHECK_LIB} ${defaultlibs}" AC_CHECK_LIB([java], [JNI_CreateJavaVM], [JAVA_LDFLAGS="${JAVA_CHECK_LIB} -ljava -ljvm -lverify"], [], [-ljvm -lverify]) if test "${JAVA_LDFLAGS}" != ""; then @@ -623,7 +616,7 @@ if test "${want_java}" = "true"; then JAVA_LIBHARMONYVM=`dirname "${JAVA_LIBHARMONYVM_SO}"` JAVA_LIBJAVA=`dirname "${JAVA_LIBHARMONYVM}"` AC_MSG_NOTICE([checking for Apache Harmony Java VM]) - JAVA_CHECK_LIB="-L${JAVA_LIBJAVA} -R${JAVA_LIBJAVA} -L${JAVA_LIBHARMONYVM} -R${JAVA_LIBHARMONYVM}" + JAVA_CHECK_LIB="-L${JAVA_LIBJAVA} -Wl,-R${JAVA_LIBJAVA} -L${JAVA_LIBHARMONYVM} -Wl,-R${JAVA_LIBHARMONYVM}" LIBS="${JAVA_CHECK_LIB} ${defaultlibs}" AC_CHECK_LIB([harmonyvm], [JNI_CreateJavaVM], [JAVA_LDFLAGS="${JAVA_CHECK_LIB} -lharmonyvm -lhythr -licuuc -lch ${JAVA_LIBHARMONYVM}/libicudata.so.34"], [], [-lhythr -licuuc -lch ${JAVA_LIBHARMONYVM}/libicudata.so.34]) if test "${JAVA_LDFLAGS}" != ""; then @@ -1006,7 +999,7 @@ if test "${want_chat}" = "true"; then AC_MSG_RESULT(${HOME}/vysper-1.0.0) ]) AC_SUBST(VYSPER_PREFIX) - AC_CHECK_FILE([${VYSPER_PREFIX}/lib/vysper-core-0.5.jar], [want_vysper=true], []) + AC_CHECK_FILE([${VYSPER_PREFIX}/lib/vysper-core-0.6.jar], [want_vysper=true], []) if test "${want_vysper}" = "true"; then AM_CONDITIONAL([WANT_VYSPER], true) else @@ -1117,6 +1110,7 @@ AC_CONFIG_FILES([Makefile modules/openid/Makefile modules/oauth/Makefile modules/wsgi/Makefile + modules/xml/Makefile components/Makefile components/cache/Makefile components/log/Makefile diff --git a/sca-cpp/trunk/hosting/server/client-test.cpp b/sca-cpp/trunk/hosting/server/client-test.cpp index c0a01b5237..7295556e08 100644 --- a/sca-cpp/trunk/hosting/server/client-test.cpp +++ b/sca-cpp/trunk/hosting/server/client-test.cpp @@ -27,7 +27,7 @@ #include "string.hpp" #include "client-test.hpp" -int main(const int argc, const char** argv) { +int main(const int argc, const char** const argv) { tuscany::cout << "Testing..." << tuscany::endl; tuscany::server::testURI = argc > 1? argv[1] : "https://jane:jane@www.example.com:8453"; diff --git a/sca-cpp/trunk/hosting/server/client-test.hpp b/sca-cpp/trunk/hosting/server/client-test.hpp index 7d85fc99a6..9d887e0558 100644 --- a/sca-cpp/trunk/hosting/server/client-test.hpp +++ b/sca-cpp/trunk/hosting/server/client-test.hpp @@ -36,7 +36,7 @@ namespace tuscany { namespace server { -string testURI = "http://localhost:8090"; +gc_mutable_ref testURI = (string)"http://localhost:8090"; bool testBlobs = true; ostream* curlWriter(const string& s, ostream* os) { @@ -45,8 +45,8 @@ ostream* curlWriter(const string& s, ostream* os) { } const bool testGetDoc() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); { ostringstream os; const failable > r = http::get(curlWriter, &os, testURI + "/", ch); @@ -62,201 +62,139 @@ const bool testGetDoc() { return true; } -struct getDocLoop { - http::CURLSession& ch; - getDocLoop(http::CURLSession& ch) : ch(ch) { - } - const bool operator()() const { +const bool testGetDocPerf() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda gl = [ch]() -> const bool { const failable r = http::getcontent(testURI + "/", ch); assert(hasContent(r)); assert(contains(car(list(content(r))), "")); return true; - } -}; - -const bool testGetDocPerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda gl = getDocLoop(ch); + }; cout << "GET doc test " << time(gl, 10, 50) << " ms" << endl; return true; } -struct getCompositeLoop { - http::CURLSession& ch; - getCompositeLoop(http::CURLSession& ch) : ch(ch) { - } - const bool operator()() const { +const bool testGetCompositePerf() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda gl = [ch]() -> const bool { const failable r = http::getcontent(testURI + "/r/Editor/composites/test", ch); assert(hasContent(r)); return true; - } -}; - -const bool testGetCompositePerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda gl = getCompositeLoop(ch); + }; cout << "GET composite test " << time(gl, 10, 50) << " ms" << endl; return true; } -struct getPageLoop { - http::CURLSession& ch; - getPageLoop(http::CURLSession& ch) : ch(ch) { - } - const bool operator()() const { +const bool testGetPagePerf() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda gl = [ch]() -> const bool { const failable r = http::getcontent(testURI + "/r/Editor/pages/test", ch); assert(hasContent(r)); return true; - } -}; - -const bool testGetPagePerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda gl = getPageLoop(ch); + }; cout << "GET page test " << time(gl, 10, 50) << " ms" << endl; return true; } -struct getAppLoop { - http::CURLSession& ch; - getAppLoop(http::CURLSession& ch) : ch(ch) { - } - const bool operator()() const { +const bool testGetAppPerf() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda gl = [ch]() -> const bool { const failable r = http::getcontent(testURI + "/r/Editor/apps/test", ch); assert(hasContent(r)); return true; - } -}; - -const bool testGetAppPerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda gl = getAppLoop(ch); + }; cout << "GET app test " << time(gl, 10, 50) << " ms" << endl; return true; } const bool testEval() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); const failable r = http::evalExpr(mklist(string("echo"), string("Hello")), testURI, ch); assert(hasContent(r)); assert(content(r) == string("Hello")); return true; } -struct evalLoop { - const string uri; - http::CURLSession& ch; - evalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { - } - const bool operator()() const { - const failable r = http::evalExpr(mklist(string("echo"), string("Hello")), uri, ch); - assert(hasContent(r)); - assert(content(r) == string("Hello")); - return true; - } -}; - const value blob(string(2048, 'A')); const list blobs = mklist(blob, blob); -struct blobEvalLoop { - const string uri; - http::CURLSession& ch; - blobEvalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { - } - const bool operator()() const { - const failable r = content(http::evalExpr(mklist(string("echo"), blobs), uri, ch)); +const bool testEvalPerf() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda el = [ch]() -> const bool { + const failable r = http::evalExpr(mklist(string("echo"), string("Hello")), testURI, ch); assert(hasContent(r)); - assert(content(r) == blobs); + assert(content(r) == string("Hello")); return true; - } -}; - -const bool testEvalPerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda el = evalLoop(testURI, ch); + }; cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl; if (testBlobs) { - const lambda bel = blobEvalLoop(testURI, ch); + const blambda bel = [ch]() -> const bool { + const failable r = content(http::evalExpr(mklist(string("echo"), blobs), testURI, ch)); + assert(hasContent(r)); + assert(content(r) == blobs); + return true; + }; cout << "JSON-RPC eval blob test " << time(bel, 5, 200) << " ms" << endl; } return true; } -bool testPost() { - gc_scoped_pool pool; - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testPost() { + const gc_scoped_pool pool; + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession ch("", "", "", "", 0); + const http::CURLSession ch("", "", "", "", 0); const failable id = http::post(a, testURI, ch); assert(hasContent(id)); return true; } -struct postLoop { - const string uri; - const value val; - http::CURLSession& ch; - postLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { - } - const bool operator()() const { - const failable id = http::post(val, uri, ch); - assert(hasContent(id)); - return true; - } -}; - -struct postBlobLoop { - const string uri; - const value val; - http::CURLSession& ch; - postBlobLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { - } - const bool operator()() const { - gc_scoped_pool pool; - const failable id = http::post(val, uri, ch); - assert(hasContent(id)); - return true; - } -}; - const bool testPostPerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); { - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list val = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list val = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - const lambda pl = postLoop(testURI, val, ch); + const blambda pl = [val, ch]() -> const bool { + const failable id = http::post(val, testURI, ch); + assert(hasContent(id)); + return true; + }; cout << "ATOMPub POST small test " << time(pl, 5, 200) << " ms" << endl; } if (testBlobs) { - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "blob1" + blob) - + (list() + "blob2" + blob) - + (list() + "price" + string("$2.99"))); - const list val = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "blob1" + blob) + + (nilListValue + "blob2" + blob) + + (nilListValue + "price" + string("$2.99"))); + const list val = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - const lambda pl = postBlobLoop(testURI, val, ch); + const blambda pl = [val, ch]() -> const bool { + const gc_scoped_pool pool; + const failable id = http::post(val, testURI, ch); + assert(hasContent(id)); + return true; + }; cout << "ATOMPub POST blob test " << time(pl, 5, 200) << " ms" << endl; } return true; @@ -264,15 +202,19 @@ const bool testPostPerf() { #ifdef WANT_THREADS -const bool postThread(const string& uri, const int count, const value& val) { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda pl = postLoop(uri, val, ch); +const bool postThread(const int count, const value& val) { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda pl = [val, ch]() -> const bool { + const failable id = http::post(val, testURI, ch); + assert(hasContent(id)); + return true; + }; time(pl, 0, count); return true; } -const list > startPost(worker& w, const int threads, const lambda& l) { +const list > startPost(const worker& w, const int threads, const blambda& l) { if (threads == 0) return list >(); return cons(submit(w, l), startPost(w, threads - 1, l)); @@ -285,36 +227,27 @@ const bool checkPost(const list >& r) { return checkPost(cdr(r)); } -struct postThreadLoop { - const lambda l; - worker& w; - const int threads; - postThreadLoop(const lambda& l, worker& w, const int threads) : l(l), w(w), threads(threads) { - } - const bool operator()() const { - list > r = startPost(w, threads, l); - checkPost(r); - return true; - } -}; - const bool testPostThreadPerf() { - gc_scoped_pool pool; + const gc_scoped_pool pool; const int count = 50; const int threads = 10; - worker w(threads); - - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const value val = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const worker w(threads); + + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const value val = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - const lambda pl= curry(lambda(postThread), testURI, count, val); - const lambda ptl = postThreadLoop(pl, w, threads); - double t = time(ptl, 0, 1) / (threads * count); + const blambda pl= curry(lambda(postThread), count, val); + const blambda ptl = [pl, w, threads]() -> const bool { + list > r = startPost(w, threads, pl); + checkPost(r); + return true; + }; + const double t = time(ptl, 0, 1) / (threads * count); cout << "ATOMPub POST thread test " << t << " ms" << endl; return true; @@ -323,17 +256,21 @@ const bool testPostThreadPerf() { #else const bool postProc(const string& uri, const int count, const value& val) { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda pl = postLoop(uri, val, ch); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda pl = [val, ch]() -> const bool { + const failable id = http::post(val, testURI, ch); + assert(hasContent(id)); + return true; + }; time(pl, 0, count); return true; } -const list startPost(const int procs, const lambda& l) { +const list startPost(const int procs, const blambda& l) { if (procs == 0) return list(); - pid_t pid = fork(); + const pid_t pid = fork(); if (pid == 0) { assert(l() == true); exit(0); @@ -350,34 +287,26 @@ const bool checkPost(const list& r) { return checkPost(cdr(r)); } -struct postForkLoop { - const lambda l; - const int procs; - postForkLoop(const lambda& l, const int procs) : l(l), procs(procs) { - } - const bool operator()() const { - list r = startPost(procs, l); - checkPost(r); - return true; - } -}; - const bool testPostForkPerf() { - gc_scoped_pool pool; + const gc_scoped_pool pool; const int count = 50; const int procs = 10; - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const value val = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const value val = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - const lambda pl= curry(lambda(postProc), testURI, count, val); - const lambda ptl = postForkLoop(pl, procs); - double t = time(ptl, 0, 1) / (procs * count); + const blambda pl= curry(lambda(postProc), testURI, count, val); + const blambda ptl = [pl, procs]() -> const bool { + list r = startPost(procs, pl); + checkPost(r); + return true; + }; + const double t = time(ptl, 0, 1) / (procs * count); cout << "ATOMPub POST fork test " << t << " ms" << endl; return true; @@ -386,25 +315,25 @@ const bool testPostForkPerf() { #endif const bool testPut() { - gc_scoped_pool pool; - const list i = list() + "content" + (list() + "item" - + (list() + "name" + string("Apple")) - + (list() + "price" + string("$2.99"))); - const list a = list() + (list() + "entry" - + (list() + "title" + string("item")) - + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const gc_scoped_pool pool; + const list i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession ch("", "", "", "", 0); - value rc = content(http::put(a, testURI + "/111", ch)); - assert(rc == value(true)); + const http::CURLSession ch("", "", "", "", 0); + const value rc = content(http::put(a, testURI + "/111", ch)); + assert(rc == trueValue); return true; } const bool testDel() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - value rc = content(http::del(testURI + "/111", ch)); - assert(rc == value(true)); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const value rc = content(http::del(testURI + "/111", ch)); + assert(rc == trueValue); return true; } diff --git a/sca-cpp/trunk/patches/scribe-2.2.patch b/sca-cpp/trunk/patches/scribe-2.2.patch index 16c2e3871e..2f6b096719 100644 --- a/sca-cpp/trunk/patches/scribe-2.2.patch +++ b/sca-cpp/trunk/patches/scribe-2.2.patch @@ -10,6 +10,23 @@ #include #include +--- src/conn_pool.cpp ++++ src/conn_pool.cpp +@@ -271,11 +271,11 @@ + ++iter) { + msgs.push_back(**iter); + } +- ResultCode result = TRY_LATER; ++ ResultCode::type result = ResultCode::TRY_LATER; + try { + result = resendClient->Log(msgs); + +- if (result == OK) { ++ if (result == ResultCode::OK) { + if (g_Handler) { + g_Handler->incrementCounter("sent", size); + } + --- src/file.cpp +++ src/file.cpp @@ -74,9 +74,21 @@ @@ -56,6 +73,32 @@ LOG_OPER("Starting scribe server on port %lu", g_Handler->port); fflush(stderr); +@@ -409,13 +411,13 @@ + } + + +-ResultCode scribeHandler::Log(const vector& messages) { +- ResultCode result; ++ResultCode::type scribeHandler::Log(const vector& messages) { ++ ResultCode::type result; + + scribeHandlerLock.acquireRead(); + + if (throttleRequest(messages)) { +- result = TRY_LATER; ++ result = ResultCode::TRY_LATER; + goto end; + } + +@@ -463,7 +465,7 @@ + addMessage(*msg_iter, store_list); + } + +- result = OK; ++ result = ResultCode::OK; + + end: + scribeHandlerLock.release(); @@ -583,6 +585,8 @@ throw runtime_error("No port number configured"); } @@ -68,6 +111,15 @@ --- src/scribe_server.h +++ src/scribe_server.h +@@ -42,7 +42,7 @@ + void initialize(); + void reinitialize(); + +- scribe::thrift::ResultCode Log(const std::vector& messages); ++ scribe::thrift::ResultCode::type Log(const std::vector& messages); + + void getVersion(std::string& _return) {_return = "2.2";} + facebook::fb303::fb_status getStatus(); @@ -51,6 +51,7 @@ void setStatusDetails(const std::string& new_status_details); @@ -76,3 +128,4 @@ // number of threads processing new Thrift connections size_t numThriftServerThreads; + diff --git a/sca-cpp/trunk/patches/thrift-0.2.0.patch b/sca-cpp/trunk/patches/thrift-0.2.0.patch deleted file mode 100644 index a834faca02..0000000000 --- a/sca-cpp/trunk/patches/thrift-0.2.0.patch +++ /dev/null @@ -1,39 +0,0 @@ ---- lib/cpp/src/server/TNonblockingServer.cpp -+++ lib/cpp/src/server/TNonblockingServer.cpp -@@ -622,8 +622,8 @@ - hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; - sprintf(port, "%d", port_); - -- // Wildcard address -- error = getaddrinfo(NULL, port, &hints, &res0); -+ // Wildcard or specified address -+ error = getaddrinfo(host_ == "" || host_ =="*"? NULL : host_.c_str(), port, &hints, &res0); - if (error) { - string errStr = "TNonblockingServer::serve() getaddrinfo " + string(gai_strerror(error)); - GlobalOutput(errStr.c_str()); - ---- lib/cpp/src/server/TNonblockingServer.h -+++ lib/cpp/src/server/TNonblockingServer.h -@@ -65,6 +65,9 @@ - // Server socket file descriptor - int serverSocket_; - -+ // Host server runs on -+ std::string host_; -+ - // Port server runs on - int port_; - -@@ -117,10 +120,12 @@ - - TNonblockingServer(boost::shared_ptr processor, - boost::shared_ptr protocolFactory, -+ std::string host, - int port, - boost::shared_ptr threadManager = boost::shared_ptr()) : - TServer(processor), - serverSocket_(-1), -+ host_(host), - port_(port), - threadManager_(threadManager), - eventBase_(NULL), diff --git a/sca-cpp/trunk/patches/thrift-0.8.0.patch b/sca-cpp/trunk/patches/thrift-0.8.0.patch new file mode 100644 index 0000000000..09b4412c3a --- /dev/null +++ b/sca-cpp/trunk/patches/thrift-0.8.0.patch @@ -0,0 +1,41 @@ +--- lib/cpp/src/server/TNonblockingServer.cpp ++++ lib/cpp/src/server/TNonblockingServer.cpp +@@ -989,8 +989,8 @@ + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + sprintf(port, "%d", port_); + +- // Wildcard address +- error = getaddrinfo(NULL, port, &hints, &res0); ++ // Wildcard or specified address ++ error = getaddrinfo(host_ == "" || host_ =="*"? NULL : host_.c_str(), port, &hints, &res0); + if (error) { + string errStr = "TNonblockingServer::serve() getaddrinfo " + string(gai_strerror(error)); + GlobalOutput(errStr.c_str()); + +--- lib/cpp/src/server/TNonblockingServer.h ++++ lib/cpp/src/server/TNonblockingServer.h +@@ -126,6 +126,9 @@ + /// Server socket file descriptor + int serverSocket_; + ++ /// Host server runs on ++ std::string host_; ++ + /// Port server runs on + int port_; + +@@ -294,11 +297,13 @@ + TNonblockingServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& protocolFactory, ++ const std::string host, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : +- TServer(processor) { ++ TServer(processor), ++ host_(host) { + + init(port); + diff --git a/sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp b/sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp index 9907650316..16f01cd85c 100644 --- a/sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp +++ b/sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp @@ -35,27 +35,19 @@ namespace store { /** * Returns the catalog. */ -struct convert { - const lambda&)> converter; - const string currency; - convert(const lambda&)>& converter, const string& currency) : converter(converter), currency(currency) { - } - const value operator()(const value& price) const { - return converter(mklist("convert", string("USD"), currency, price)); - } -}; - const list mkfruit(const string& name, const string& code, const string& symbol, const double price) { - return list() + + return nilListValue + mklist("name", name) + mklist("currencyCode", code) + mklist("currencySymbol", symbol) + mklist("price", price); } -const failable items(const lambda&)>& converter, const lambda&)>& currencyCode) { - const string currency(currencyCode(list())); +const failable items(const lvvlambda& converter, const lvvlambda& currencyCode) { + const string currency(currencyCode(nilListValue)); const string symbol(converter(mklist("symbol", currency))); - const lambda conv(convert(converter, currency)); + const vvlambda conv = [converter, currency](const value& price) -> const value { + return converter(mklist("convert", string("USD"), currency, price)); + }; - return value(list() + + return value(nilListValue + mkfruit("Apple", currency, symbol, conv(2.99)) + mkfruit("Orange", currency, symbol, conv(3.55)) + mkfruit("Pear", currency, symbol, conv(1.55))); diff --git a/sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp b/sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp index 2771d7cd9c..e65aa0d392 100644 --- a/sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp +++ b/sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp @@ -38,7 +38,7 @@ const string cartId("1234"); * Get the shopping cart from the cache. Return an empty * cart if not found. */ -const list getcart(const value& id, const lambda&)>& cache) { +const list getcart(const value& id, const lvvlambda& cache) { const value cart = cache(mklist("get", mklist(id))); cerr << "cart value: " << cart << "\n"; const failable fcart = cart; @@ -46,14 +46,14 @@ const list getcart(const value& id, const lambda& cerr << "cart content: " << content(fcart) << "\n"; cerr << "cart reason: " << reason(fcart) << "\n"; if (isNil(cart)) - return value(list()); + return value(nilListValue); return (list)cart; } /** * Post a new item to the cart. Create a new cart if necessary. */ -const failable post(unused const list& collection, const value& item, const lambda&)>& cache) { +const failable post(unused const list& collection, const value& item, const lvvlambda& cache) { const value id(mkuuid()); const list newItem(mklist("entry", cadr(car(item)), mklist("id", id), cadddr(car(item)))); const list cart(cons(newItem, getcart(cartId, cache))); @@ -75,7 +75,7 @@ const value find(const value& id, const list& cart) { /** * Return items from the cart. */ -const failable get(const list& id, const lambda&)>& cache) { +const failable get(const list& id, const lvvlambda& cache) { if (isNil(id)) return value(mklist(append(mklist("feed", mklist("title", string("Your Cart")), mklist("id", cartId)), getcart(cartId, cache)))); return find(car(id), getcart(cartId, cache)); @@ -84,10 +84,10 @@ const failable get(const list& id, const lambda del(const list& id, unused const lambda&)>& cache) { +const failable del(const list& id, unused const lvvlambda& cache) { if (isNil(id)) return cache(mklist("delete", mklist(cartId))); - return value(true); + return trueValue; } /** @@ -109,7 +109,7 @@ const double sum(const list& items) { /** * Return the total price of the items in the cart. */ -const failable total(const lambda&)>& cache) { +const failable total(const lvvlambda& cache) { const list cart(getcart(cartId, cache)); return value(sum(cart)); } diff --git a/sca-cpp/trunk/samples/store-java/Makefile.am b/sca-cpp/trunk/samples/store-java/Makefile.am index f32ae72812..3db20ac390 100644 --- a/sca-cpp/trunk/samples/store-java/Makefile.am +++ b/sca-cpp/trunk/samples/store-java/Makefile.am @@ -22,11 +22,16 @@ if WANT_JAVA dist_sample_SCRIPTS = start stop ssl-start sampledir=$(prefix)/samples/store-java -AM_JAVACFLAGS = -cp ${top_builddir}/modules/java/libmod-tuscany-java-${PACKAGE_VERSION}.jar:${JAVAROOT} dist_sample_JAVA = store/*.java + +SUFFIXES = .class +AM_JAVACFLAGS = -cp ${top_builddir}/modules/java/libmod-tuscany-java-${PACKAGE_VERSION}.jar:${JAVAROOT} +.java.class: + ${JAVAC} ${AM_JAVACFLAGS} store/*.java + CLEANFILES = *.stamp store/*.class -nobase_dist_sample_DATA = store.composite htdocs/*.html store/*.* +nobase_dist_sample_DATA = store.composite htdocs/*.html store/*.java store/CurrencyConverterImpl.class store/CurrencyConverter.class store/FruitsCatalogImpl.class store/ShoppingCartImpl.class dist_noinst_SCRIPTS = server-test TESTS = server-test diff --git a/sca-cpp/trunk/samples/store-scheme/Makefile.am b/sca-cpp/trunk/samples/store-scheme/Makefile.am index 2330d45422..36aa8ecb2d 100644 --- a/sca-cpp/trunk/samples/store-scheme/Makefile.am +++ b/sca-cpp/trunk/samples/store-scheme/Makefile.am @@ -25,6 +25,6 @@ EXTRA_DIST = script-test.scm dist_noinst_SCRIPTS = server-test noinst_PROGRAMS = script-test script_test_SOURCES = script-test.cpp -script_test_LDFLAGS = -lxml2 -lmozjs +script_test_LDFLAGS = -lxml2 -ljansson TESTS = script-test server-test diff --git a/sca-cpp/trunk/samples/store-scheme/script-test.cpp b/sca-cpp/trunk/samples/store-scheme/script-test.cpp index 0d5a9ccf9d..676865e771 100644 --- a/sca-cpp/trunk/samples/store-scheme/script-test.cpp +++ b/sca-cpp/trunk/samples/store-scheme/script-test.cpp @@ -28,16 +28,16 @@ #include "stream.hpp" #include "string.hpp" #include "list.hpp" -#include "xml.hpp" -#include "../../modules/scheme/driver.hpp" +#include "../../modules/xml/xml.hpp" #include "../../modules/json/json.hpp" +#include "../../modules/scheme/driver.hpp" namespace store { using namespace tuscany; -bool testScript() { - gc_scoped_pool pool; +const bool testScript() { + const gc_scoped_pool pool; ifstream is("script-test.scm"); ostringstream os; @@ -49,9 +49,9 @@ bool testScript() { return true; } -bool testEval() { +const bool testEval() { { - gc_scoped_pool pool; + const gc_scoped_pool pool; ifstream is("script-test.scm"); ostringstream os; scheme::setupDisplay(os); @@ -65,7 +65,7 @@ bool testEval() { } { - gc_scoped_pool pool; + const gc_scoped_pool pool; ifstream is("script-test.scm"); ostringstream os; scheme::setupDisplay(os); diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/Makefile.am b/sca-cpp/trunk/unmaintained/components/kvdb/Makefile.am new file mode 100644 index 0000000000..3212f3f5c8 --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/Makefile.am @@ -0,0 +1,49 @@ +# 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. + +INCLUDES = -I${LEVELDB_INCLUDE} + +incl_HEADERS = *.hpp +incldir = $(prefix)/include/components/kvdb + +dist_comp_SCRIPTS = leveldb +compdir=$(prefix)/components/kvdb + +comp_DATA = leveldb.prefix +leveldb.prefix: $(top_builddir)/config.status + echo ${LEVELDB_PREFIX} >leveldb.prefix + +EXTRA_DIST = kvdb.composite kvdb.componentType + +comp_LTLIBRARIES = libkvdb.la +noinst_DATA = libkvdb${libsuffix} + +libkvdb_la_SOURCES = kvdb.cpp +libkvdb_la_LDFLAGS = -L${LEVELDB_LIB} -R${LEVELDB_LIB} -lleveldb +libkvdb${libsuffix}: + ln -s .libs/libkvdb${libsuffix} + +leveldb_test_SOURCES = leveldb-test.cpp +leveldb_test_LDFLAGS = -L${LEVELDB_LIB} -R${LEVELDB_LIB} -lleveldb + +client_test_SOURCES = client-test.cpp +client_test_LDFLAGS = -lxml2 -lcurl -lmozjs + +dist_noinst_SCRIPTS = kvdb-test server-test +noinst_PROGRAMS = leveldb-test client-test +TESTS = kvdb-test server-test + diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/client-test.cpp b/sca-cpp/trunk/unmaintained/components/kvdb/client-test.cpp new file mode 100644 index 0000000000..5f0ef21d00 --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/client-test.cpp @@ -0,0 +1,139 @@ +/* + * 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 KV (Key-Value) database component. + */ + +#include +#include "stream.hpp" +#include "string.hpp" + +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "perf.hpp" +#include "../../modules/http/http.hpp" + +namespace tuscany { +namespace nosqldb { + +const string uri("http://localhost:8090/nosqldb"); + +bool testNoSqlDb() { + http::CURLSession cs("", "", "", ""); + + const list i = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "price" + string("$2.99"))); + const list a = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + + i); + + const failable id = http::post(a, uri, cs); + assert(hasContent(id)); + + const string p = path(content(id)); + { + const failable val = http::get(uri + p, cs); + assert(hasContent(val)); + assert(content(val) == a); + } + + const list j = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "price" + string("$3.55"))); + const list b = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + + j); + + { + const failable r = http::put(b, uri + p, cs); + assert(hasContent(r)); + assert(content(r) == value(true)); + } + { + const failable val = http::get(uri + p, cs); + assert(hasContent(val)); + assert(content(val) == b); + } + { + const failable r = http::del(uri + p, cs); + assert(hasContent(r)); + assert(content(r) == value(true)); + } + { + const failable val = http::get(uri + p, cs); + assert(!hasContent(val)); + } + + return true; +} + +struct getLoop { + const string path; + const value entry; + http::CURLSession& cs; + getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { + } + const bool operator()() const { + const failable val = http::get(uri + path, cs); + assert(hasContent(val)); + assert(content(val) == entry); + return true; + } +}; + +bool testGetPerf() { + const list i = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "price" + string("$4.55"))); + const list a = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + + i); + + http::CURLSession cs("", "", "", ""); + const failable id = http::post(a, uri, cs); + assert(hasContent(id)); + const string p = path(content(id)); + + const lambda gl = getLoop(p, a, cs); + cout << "NoSqldb get test " << time(gl, 5, 200) << " ms" << endl; + + return true; +} + +} +} + +int main() { + tuscany::cout << "Testing..." << tuscany::endl; + + tuscany::nosqldb::testNoSqlDb(); + tuscany::nosqldb::testGetPerf(); + + tuscany::cout << "OK" << tuscany::endl; + + return 0; +} diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/kvdb-test b/sca-cpp/trunk/unmaintained/components/kvdb/kvdb-test new file mode 100755 index 0000000000..420b98559c --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/kvdb-test @@ -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. + +# Setup +rm -rf tmp +mkdir -p tmp +./tinycdb -c -m tmp/test.cdb /dev/null +rc=$? + +# Cleanup +exit $rc diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.componentType b/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.componentType new file mode 100644 index 0000000000..1c56ab6807 --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.componentType @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.composite b/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.composite new file mode 100644 index 0000000000..378f418cfc --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.composite @@ -0,0 +1,32 @@ + + + + + + + tmp/test.cdb + + + + + + diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.cpp b/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.cpp new file mode 100644 index 0000000000..0df8f13882 --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/kvdb.cpp @@ -0,0 +1,124 @@ +/* + * 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$ */ + +/** + * LevelDB-based database component implementation. + */ + +#define WANT_HTTPD_LOG 1 +#include "string.hpp" +#include "function.hpp" +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "leveldb.hpp" + +namespace tuscany { +namespace nvdb { + +/** + * Get an item from the database. + */ +const failable get(const list& params, leveldb::LevelDB& cdb) { + return leveldb::get(car(params), cdb); +} + +/** + * Post an item to the database. + */ +const failable post(const list& params, leveldb::LevelDB& cdb) { + const value id = append(car(params), mklist(mkuuid())); + const failable val = leveldb::post(id, cadr(params), cdb); + if (!hasContent(val)) + return mkfailure(val); + return id; +} + +/** + * Put an item into the database. + */ +const failable put(const list& params, leveldb::LevelDB& cdb) { + const failable val = leveldb::put(car(params), cadr(params), cdb); + if (!hasContent(val)) + return mkfailure(val); + return value(content(val)); +} + +/** + * Delete an item from the database. + */ +const failable del(const list& params, leveldb::LevelDB& cdb) { + const failable val = leveldb::del(car(params), cdb); + if (!hasContent(val)) + return mkfailure(val); + return value(content(val)); +} + +/** + * Component implementation lambda function. + */ +class applyNoSqldb { +public: + applyNoSqldb(leveldb::LevelDB& cdb) : cdb(cdb) { + } + + const value operator()(const list& params) const { + const value func(car(params)); + if (func == "get") + return get(cdr(params), cdb); + if (func == "post") + return post(cdr(params), cdb); + if (func == "put") + return put(cdr(params), cdb); + if (func == "delete") + return del(cdr(params), cdb); + return mkfailure(); + } + +private: + leveldb::LevelDB& cdb; +}; + +/** + * Start the component. + */ +const failable start(unused const list& params) { + // Connect to the configured database and table + const value dbname = ((lambda&)>)car(params))(list()); + leveldb::LevelDB& cdb = *(new (gc_new()) leveldb::LevelDB(dbname)); + + // Return the component implementation lambda function + return value(lambda&)>(applyNoSqldb(cdb))); +} + +} +} + +extern "C" { + +const tuscany::value apply(const tuscany::list& params) { + const tuscany::value func(car(params)); + if (func == "start") + return tuscany::nosqldb::start(cdr(params)); + return tuscany::mkfailure(); +} + +} diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/leveldb b/sca-cpp/trunk/unmaintained/components/kvdb/leveldb new file mode 100755 index 0000000000..f9c54465f6 --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/leveldb @@ -0,0 +1,24 @@ +#!/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. + +here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here` +leveldb_prefix=`cat $here/leveldb.prefix` + +$leveldb_prefix/bin/cdb $* + diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/leveldb-test.cpp b/sca-cpp/trunk/unmaintained/components/kvdb/leveldb-test.cpp new file mode 100644 index 0000000000..b3b4ea7fd7 --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/leveldb-test.cpp @@ -0,0 +1,82 @@ +/* + * 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 TinyCDB access functions. + */ + +#include +#include "stream.hpp" +#include "string.hpp" +#include "perf.hpp" +#include "tinycdb.hpp" + +namespace tuscany { +namespace tinycdb { + +bool testTinyCDB() { + TinyCDB cdb("tmp/test.cdb"); + const value k = mklist("a"); + + assert(hasContent(post(k, string("AAA"), cdb))); + assert((get(k, cdb)) == value(string("AAA"))); + assert(hasContent(put(k, string("aaa"), cdb))); + assert((get(k, cdb)) == value(string("aaa"))); + assert(hasContent(del(k, cdb))); + assert(!hasContent(get(k, cdb))); + + return true; +} + +struct getLoop { + const value k; + TinyCDB& cdb; + getLoop(const value& k, TinyCDB& cdb) : k(k), cdb(cdb) { + } + const bool operator()() const { + assert((get(k, cdb)) == value(string("CCC"))); + return true; + } +}; + +bool testGetPerf() { + const value k = mklist("c"); + TinyCDB cdb("tmp/test.cdb"); + assert(hasContent(post(k, string("CCC"), cdb))); + + const lambda gl = getLoop(k, cdb); + cout << "TinyCDB get test " << time(gl, 5, 100000) << " ms" << endl; + return true; +} + +} +} + +int main() { + tuscany::cout << "Testing..." << tuscany::endl; + + tuscany::tinycdb::testTinyCDB(); + tuscany::tinycdb::testGetPerf(); + + tuscany::cout << "OK" << tuscany::endl; + + return 0; +} diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/leveldb.hpp b/sca-cpp/trunk/unmaintained/components/kvdb/leveldb.hpp new file mode 100644 index 0000000000..05a89a76f7 --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/leveldb.hpp @@ -0,0 +1,271 @@ +/* + * 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$ */ + +#ifndef tuscany_leveldb_hpp +#define tuscany_leveldb_hpp + +#include +#include +#include +#include + +#include "string.hpp" +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "../../modules/scheme/eval.hpp" + +namespace tuscany { +namespace leveldb { + +/** + * A reallocatable buffer. + */ +class buffer { +public: + operator void*() const throw() { + return buf; + } + + operator unsigned char*() const throw() { + return (unsigned char*)buf; + } + + operator char*() const throw() { + return (char*)buf; + } + +private: + buffer(const unsigned int size, void* buf) : size(size), buf(buf) { + } + + unsigned int size; + void* buf; + + friend const buffer mkbuffer(const unsigned int sz); + friend const buffer mkbuffer(const buffer& b, const unsigned int newsz); + friend const bool free(const buffer& b); +}; + +/** + * Make a new buffer. + */ +const buffer mkbuffer(const unsigned int sz) { + return buffer(sz, malloc(sz)); +} + +/** + * Make a new buffer by reallocating an existing one. + */ +const buffer mkbuffer(const buffer& b, const unsigned int sz) { + if (sz <= b.size) + return b; + return buffer(sz, realloc(b.buf, sz)); +} + +/** + * Free a buffer. + */ +const bool free(const buffer&b) { + ::free(b.buf); + return true; +} + +/** + * Convert a database name to an absolute path. + */ +const string absdbname(const string& name) { + if (length(name) == 0 || c_str(name)[0] == '/') + return name; + char cwd[512]; + if (getcwd(cwd, sizeof(cwd)) == NULL) + return name; + return string(cwd) + "/" + name; +} + +/** + * Represents a LevelDB connection. + */ +class LevelDB { +public: + LevelDB() : owner(false), fd(-1) { + debug("leveldb::leveldb"); + st.st_ino = 0; + } + + LevelDB(const string& name) : owner(true), name(absdbname(name)), fd(-1) { + debug(name, "leveldb::leveldb::name"); + st.st_ino = 0; + } + + LevelDB(const LevelDB& c) : owner(false), name(c.name), fd(c.fd) { + debug("leveldb::leveldb::copy"); + st.st_ino = c.st.st_ino; + } + + const LevelDB& operator=(const LevelDB& c) { + debug("leveldb::leveldb::operator="); + if(this == &c) + return *this; + owner = false; + name = c.name; + fd = c.fd; + st.st_ino = c.st.st_ino; + return *this; + } + + ~LevelDB() { + debug("leveldb::~leveldb"); + if (!owner) + return; + if (fd == -1) + return; + close(fd); + } + +private: + bool owner; + string name; + leveldb::DB* db; + struct stat st; + + friend const string dbname(const LevelDB& db); + friend const failable dbopen(LevelDB& db); + friend const failable dbclose(LevelDB& db); +}; + +/** + * Return the name of the database. + */ +const string dbname(const LevelDB& db) { + return db.name; +} + +/** + * Open a database. + */ +const failable dbopen(LevelDB& db) { + + // Get database file serial number + struct stat st; + const int s = stat(c_str(db.name), &st); + if (s == -1) + return mkfailure(string("Couldn't leveldb read database stat: ") + db.name); + + leveldb::DB* ldb; + leveldb::Options options; + options.create_if_missing = true; + leveldb::Status status = leveldb::DB::Open(options, s, &ldb); + db.db = ldb; +} + +/** + * Close a database. + */ +const failable dbclose(LevelDB& db) { + delete db.db; + db.db = NULL; + return true; +} + + +const failable post(const value& key, const value& val, LevelDB& db) { + debug(key, "leveldb::post::key"); + debug(val, "leveldb::post::value"); + debug(dbname(db), "leveldb::post::dbname"); + + const string ks(scheme::writeValue(key)); + const string vs(scheme::writeValue(val)); + + put(ks, vs, db); + + debug(r, "leveldb::post::result"); + return r; +} + + +const failable put(const value& key, const value& val, LevelDB& db) { + debug(key, "leveldb::put::key"); + debug(val, "leveldb::put::value"); + debug(dbname(db), "leveldb::put::dbname"); + + const string ks(scheme::writeValue(key)); + const string vs(scheme::writeValue(val)); + + debug(r, "leveldb::put::result"); + return r; +} + +/** + * Get an item from the database. + */ +const failable get(const value& key, LevelDB& db) { + debug(key, "leveldb::get::key"); + debug(dbname(db), "leveldb::get::dbname"); + + const string ks(scheme::writeValue(key)); + + std::string data; + db.db->Get(leveldb::ReadOptions(), key, &data); + const value val(scheme::readValue(string(data))); + + debug(val, "leveldb::get::result"); + return val; +} + +/** + * Delete an item from the database + */ +struct delUpdate { + const string ks; + delUpdate(const string& ks) : ks(ks) { + } + const failable operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const { + if (ks == string((char*)buf, klen)) + return false; + return true; + } +}; + +struct delFinish { + delFinish() { + } + const failable operator()(unused struct db_make& dbm) const { + return true; + } +}; + +const failable del(const value& key, LevelDB& db) { + debug(key, "leveldb::delete::key"); + debug(dbname(db), "leveldb::delete::dbname"); + + const string ks(scheme::writeValue(key)); + + leveldb::Status s = db.db->Delete(leveldb::WriteOptions(), key); + + debug(r, "leveldb::delete::result"); + return s.ok(); +} + +} +} + +#endif /* tuscany_leveldb_hpp */ diff --git a/sca-cpp/trunk/unmaintained/components/kvdb/server-test b/sca-cpp/trunk/unmaintained/components/kvdb/server-test new file mode 100755 index 0000000000..ebf01b9b4b --- /dev/null +++ b/sca-cpp/trunk/unmaintained/components/kvdb/server-test @@ -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. + +# Setup +rm -rf tmp +../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs +../../modules/server/server-conf tmp +../../modules/server/scheme-conf tmp +cat >>tmp/conf/httpd.conf </dev/null +rc=$? + +# Cleanup +../../modules/http/httpd-stop tmp +sleep 2 +exit $rc -- cgit v1.2.3