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
This commit is contained in:
jsdelfino 2012-12-11 06:13:02 +00:00
commit 36adc76235
90 changed files with 1428 additions and 1813 deletions

View file

@ -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 \

View file

@ -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
|

View file

@ -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

View file

@ -81,7 +81,7 @@
<service name="selector">
<binding.http uri="selector"/>
</service>
</component>
</component>
<component name="partition1">
<implementation.scheme script="partition1-test.scm"/>

View file

@ -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 bool testCache(const string& uri) {
const http::CURLSession cs("", "", "", "", 0);
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> a = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ i);
const failable<value> id = http::post(a, uri, cs);
@ -63,18 +63,18 @@ bool testCache(const string& uri) {
assert(content(val) == a);
}
const list<value> j = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55")));
const list<value> b = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> j = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$3.55")));
const list<value> b = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
assert(content(r) == trueValue);
}
{
const failable<value> val = http::get(uri + p, cs);
@ -84,7 +84,7 @@ bool testCache(const string& uri) {
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
assert(content(r) == trueValue);
}
{
const failable<value> 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<value> res = http::evalExpr(mklist<value>(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<value> 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<value> val = http::get(memcacheuri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const bool testGetPerf() {
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$4.55")));
const list<value> 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<value> id = http::post(a, memcacheuri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
const blambda gl = [p, a, cs]() -> const bool {
const failable<value> 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;

View file

@ -44,7 +44,7 @@ namespace datacache {
/**
* Get an item from the cache.
*/
const failable<value> get(const value& key, const lambda<value(const list<value>&)>& rcache1, const lambda<value(const list<value>&)>& wcache1, const lambda<value(const list<value>&)>& rcache2, unused const lambda<value(const list<value>&)>& wcache2) {
const failable<value> 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<value>("get", key));
@ -68,7 +68,7 @@ const failable<value> get(const value& key, const lambda<value(const list<value>
/**
* Post an item to the cache.
*/
const failable<value> post(const value& key, const value& val, unused const lambda<value(const list<value>&)>& rcache1, const lambda<value(const list<value>&)>& wcache1, unused const lambda<value(const list<value>&)>& rcache2, const lambda<value(const list<value>&)>& wcache2) {
const failable<value> 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<value>(key, mklist(mkuuid()));
// Update level1 cache
@ -83,7 +83,7 @@ const failable<value> post(const value& key, const value& val, unused const lamb
/**
* Put an item into the cache.
*/
const failable<value> put(const value& key, const value& val, unused const lambda<value(const list<value>&)>& rcache1, const lambda<value(const list<value>&)>& wcache1, unused const lambda<value(const list<value>&)>& rcache2, const lambda<value(const list<value>&)>& wcache2) {
const failable<value> 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<value>("put", key, val));
@ -91,13 +91,13 @@ const failable<value> put(const value& key, const value& val, unused const lambd
// Update level2 cache
wcache2(mklist<value>("put", key, val));
return value(true);
return trueValue;
}
/**
* Delete an item from the cache.
*/
const failable<value> del(const value& key, unused const lambda<value(const list<value>&)>& rcache1, const lambda<value(const list<value>&)>& wcache1, unused const lambda<value(const list<value>&)>& rcache2, const lambda<value(const list<value>&)>& wcache2) {
const failable<value> del(const value& key, unused const lvvlambda& rcache1, const lvvlambda& wcache1, unused const lvvlambda& rcache2, const lvvlambda& wcache2) {
// Delete from level1 cache
wcache1(mklist<value>("delete", key));
@ -105,7 +105,7 @@ const failable<value> del(const value& key, unused const lambda<value(const list
// Delete from level2 cache
wcache2(mklist<value>("delete", key));
return value(true);
return trueValue;
}
}

View file

@ -33,7 +33,7 @@ namespace tuscany {
namespace memcache {
bool testMemCached() {
MemCached ch(mklist<string>("localhost:11211", "localhost:11212", "localhost:11213"));
const MemCached ch(mklist<string>("localhost:11211", "localhost:11212", "localhost:11213"));
const value k = mklist<value>("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<value>("c");
MemCached ch(mklist<string>("localhost:11211", "localhost:11212", "localhost:11213"));
const MemCached ch(mklist<string>("localhost:11211", "localhost:11212", "localhost:11213"));
assert(hasContent(post(k, string("CCC"), ch)));
const lambda<bool()> 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();

View file

@ -37,14 +37,14 @@ namespace cache {
/**
* Get an item from the cache.
*/
const failable<value> get(const list<value>& params, memcache::MemCached& ch) {
const failable<value> get(const list<value>& params, const memcache::MemCached& ch) {
return memcache::get(car(params), ch);
}
/**
* Post an item to the cache.
*/
const failable<value> post(const list<value>& params, memcache::MemCached& ch) {
const failable<value> post(const list<value>& params, const memcache::MemCached& ch) {
const value id = append<value>(car(params), mklist(mkuuid()));
const failable<bool> val = memcache::post(id, cadr(params), ch);
if (!hasContent(val))
@ -55,7 +55,7 @@ const failable<value> post(const list<value>& params, memcache::MemCached& ch) {
/**
* Put an item into the cache.
*/
const failable<value> put(const list<value>& params, memcache::MemCached& ch) {
const failable<value> put(const list<value>& params, const memcache::MemCached& ch) {
const failable<bool> val = memcache::put(car(params), cadr(params), ch);
if (!hasContent(val))
return mkfailure<value>(val);
@ -65,7 +65,7 @@ const failable<value> put(const list<value>& params, memcache::MemCached& ch) {
/**
* Delete an item from the cache.
*/
const failable<value> del(const list<value>& params, memcache::MemCached& ch) {
const failable<value> del(const list<value>& params, const memcache::MemCached& ch) {
const failable<bool> val = memcache::del(car(params), ch);
if (!hasContent(val))
return mkfailure<value>(val);
@ -73,14 +73,24 @@ const failable<value> del(const list<value>& params, memcache::MemCached& ch) {
}
/**
* Component implementation lambda function.
* Convert a list of properties to a list of server addresses.
*/
class applyCache {
public:
applyCache(memcache::MemCached& ch) : ch(ch) {
}
const list<string> servers(const list<value>& params) {
if (isNil(params))
return list<string>();
const value s = ((lvvlambda)car(params))(nilListValue);
return cons<string>(s, servers(cdr(params)));
}
const value operator()(const list<value>& params) const {
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Connect to memcached
const memcache::MemCached& ch = *(new (gc_new<memcache::MemCached>()) memcache::MemCached(servers(params)));
// Return the component implementation lambda function
const lvvlambda applyCache = [ch](const list<value>& params) -> const value {
const value func(car(params));
if (func == "get")
return get(cdr(params), ch);
@ -91,31 +101,8 @@ public:
if (func == "delete")
return del(cdr(params), ch);
return mkfailure<value>();
}
private:
memcache::MemCached& ch;
};
/**
* Convert a list of properties to a list of server addresses.
*/
const list<string> servers(const list<value>& params) {
if (isNil(params))
return list<string>();
const value s = ((lambda<value(const list<value>&)>)car(params))(list<value>());
return cons<string>(s, servers(cdr(params)));
}
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Connect to memcached
memcache::MemCached& ch = *(new (gc_new<memcache::MemCached>()) memcache::MemCached(servers(params)));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyCache(ch)));
};
return value(applyCache);
}
}

View file

@ -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<string>& 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<string>& 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<bool> post(const value& key, const value& val, const MemCached& cache);
friend const failable<bool> put(const value& key, const value& val, const MemCached& cache);
@ -94,7 +79,7 @@ private:
/**
* Add servers to the memcached context.
*/
const failable<bool> addServer(const string& host, const int port) {
const failable<bool> 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<bool>(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<bool>("Couldn't add memcached server");
return true;
}
const failable<bool> addServers(const list<string>& servers) {
const failable<bool> addServers(apr_memcache_t* const m, const list<string>& servers) {
if (isNil(servers))
return true;
const list<string> toks = tokenize(":", car(servers));
const failable<bool> r = addServer(car(toks), isNil(cdr(toks))? 11211 : atoi(c_str(cadr(toks))));
const failable<bool> 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<string>& 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<char*>(s);
for (; *c; c++)
if (*c == ' ')
@ -137,8 +143,8 @@ const failable<bool> 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<char*>(c_str(vs)), length(vs), 0, 27);
if (rc != APR_SUCCESS) {
ostringstream os;
@ -157,8 +163,8 @@ const failable<bool> 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<char*>(c_str(vs)), length(vs), 0, 27);
if (rc != APR_SUCCESS) {
ostringstream os;
@ -176,17 +182,17 @@ const failable<bool> put(const value& key, const value& val, const MemCached& ca
const failable<value> 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<value>(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<value> get(const value& key, const MemCached& cache) {
const failable<bool> 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;

View file

@ -42,7 +42,7 @@ namespace memocache {
/**
* Memoize the value of a function application in a cache.
*/
const failable<value> memoize(const list<value>& params, const lambda<value(const list<value>&)>& relay, const lambda<value(const list<value>&)>& cache) {
const failable<value> memoize(const list<value>& params, const lvvlambda& relay, const lvvlambda& cache) {
debug(params, "memocache::memoize::params");
// Lookup memoized value from cache

View file

@ -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<lambda<value(const list<value>&)> > partition(const value& key, const lambda<value(const list<value>&)>& selector, const list<value>& partitions) {
const failable<list<value> > partition(const value& key, const lvvlambda& selector, const list<value>& 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<value>("get", key, partitions));
if (isNil(p)) {
ostringstream os;
os << "Couldn't get partition number: " << key;
return mkfailure<lambda<value(const list<value>&)> >(str(os), -1, false);
os << "Couldn't get partition: " << key;
return mkfailure<list<value> >(str(os), -1, false);
}
return (const lambda<value(const list<value>&)>)p;
return (list<value>)p;
}
/**
* Get lists of items from a list of partitions.
*/
const failable<list<value> > getlist(const value& key, const list<value>& partitions) {
if (isNil(partitions))
return nilListValue;
const lvvlambda l = car(partitions);
const value val = l(mklist<value>("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<list<value> >(str(os), 500, false);
}
const failable<list<value> > cdrval = getlist(key, cdr(partitions));
if (!hasContent(cdrval))
return cdrval;
return append<value>((list<value>)val, content(cdrval));
}
/**
* Get an item from a partition.
*/
const failable<value> get(const value& key, const lambda<value(const list<value>&)>& selector, const list<value>& partitions) {
const failable<value> get(const value& key, const lvvlambda& selector, const list<value>& partitions) {
// Select partition
const failable<lambda<value(const list<value>&)> > p = partition(key, selector, partitions);
if (!hasContent(p))
return mkfailure<value>(p);
const failable<list<value> > fp = partition(key, selector, partitions);
if (!hasContent(fp))
return mkfailure<value>(fp);
const list<value> p = content(fp);
// Get from selected partition
const value val = content(p)(mklist<value>("get", key));
if (isNil(val)) {
ostringstream os;
os << "Couldn't get entry from partition: " << key;
return mkfailure<value>(str(os), 404, false);
// Get a single item from the selected partition
if (length(p) == 1) {
const lvvlambda l = car(p);
const value val = l(mklist<value>("get", key));
if (isNil(val)) {
ostringstream os;
os << "Couldn't get entry from partition: " << key;
return mkfailure<value>(str(os), 404, false);
}
return val;
}
return val;
// Get list of items from the list of selected partitions
const failable<list<value> > val = getlist(key, p);
if (!hasContent(val))
return mkfailure<value>(val);
return (value)content(val);
}
/**
* Post an item to a partition.
*/
const failable<value> post(const value& key, const value& val, const lambda<value(const list<value>&)>& selector, const list<value>& partitions) {
const failable<value> post(const value& key, const value& val, const lvvlambda& selector, const list<value>& partitions) {
const value id = append<value>(key, mklist(mkuuid()));
// Select partition
const failable<lambda<value(const list<value>&)> > p = partition(id, selector, partitions);
const failable<list<value> > p = partition(id, selector, partitions);
if (!hasContent(p))
return mkfailure<value>(p);
// Put into select partition
content(p)(mklist<value>("put", id, val));
const lvvlambda l = car(content(p));
l(mklist<value>("post", id, val));
return id;
}
@ -93,33 +128,35 @@ const failable<value> post(const value& key, const value& val, const lambda<valu
/**
* Put an item into a partition.
*/
const failable<value> put(const value& key, const value& val, const lambda<value(const list<value>&)>& selector, const list<value>& partitions) {
const failable<value> put(const value& key, const value& val, const lvvlambda& selector, const list<value>& partitions) {
// Select partition
const failable<lambda<value(const list<value>&)> > p = partition(key, selector, partitions);
const failable<list<value> > p = partition(key, selector, partitions);
if (!hasContent(p))
return mkfailure<value>(p);
// Put into selected partition
content(p)(mklist<value>("put", key, val));
const lvvlambda l = car(content(p));
l(mklist<value>("put", key, val));
return value(true);
return trueValue;
}
/**
* Delete an item from a partition.
*/
const failable<value> del(const value& key, const lambda<value(const list<value>&)>& selector, const list<value>& partitions) {
const failable<value> del(const value& key, const lvvlambda& selector, const list<value>& partitions) {
// Select partition
const failable<lambda<value(const list<value>&)> > p = partition(key, selector, partitions);
const failable<list<value> > p = partition(key, selector, partitions);
if (!hasContent(p))
return mkfailure<value>(p);
// Delete from selected partition
content(p)(mklist<value>("delete", key));
const lvvlambda l = car(content(p));
l(mklist<value>("delete", key));
return value(true);
return trueValue;
}
}

View file

@ -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))))

View file

@ -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

View file

@ -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<bool> 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;
}

View file

@ -51,45 +51,38 @@ const failable<value> post(const list<value>& params, XMPPClient& xc) {
}
/**
* Subscribe and listen to an XMPP session.
* Start the component.
*/
class noop {
public:
noop() {
}
const failable<value> start(const list<value>& params) {
// Extract the the XMPP JID and password
const list<value> props = params;
const value jid = ((lvvlambda)car(props))(nilListValue);
const value pass = ((lvvlambda)cadr(props))(nilListValue);
const failable<bool> operator()(unused const value& jid, unused const value& val, unused XMPPClient& xc) const {
return true;
}
};
// Create an XMPP client session
XMPPClient xc(jid, pass, false);
const failable<bool> r = connect(xc);
if (!hasContent(r))
return mkfailure<value>(r);
class subscribe {
public:
subscribe(XMPPClient& xc) : xc(xc) {
}
const failable<bool> operator()() const {
gc_pool pool;
// Subscribe and listen to XMPP session
const lambda<const failable<bool>()> subscribe = [xc]() -> const failable<bool> {
const gc_pool pool;
debug("chat::subscribe::listen");
const failable<bool> r = listen(noop(), const_cast<XMPPClient&>(xc));
const lambda<const failable<bool>(const value&, const value&, XMPPClient&)> noop = [](unused const value& jid, unused const value& val, unused XMPPClient& xc) -> const failable<bool> {
return true;
};
const failable<bool> r = listen(noop, const_cast<XMPPClient&>(xc));
debug("chat::subscribe::stopped");
return r;
}
};
private:
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l;
XMPPClient xc;
};
// Listen and relay messages in a worker thread
worker w(3);
submit<failable<bool> >(w, subscribe);
/**
* Chatter component lambda function
*/
class chatSender {
public:
chatSender(XMPPClient& xc, worker& w) : xc(xc), w(w) {
}
const value operator()(const list<value>& params) const {
// Return the chat sender component lambda function
const lvvlambda chatSender = [xc, w](const list<value>& params) -> const value {
const tuscany::value func(car(params));
if (func == "post")
return post(cdr(params), const_cast<XMPPClient&>(xc));
@ -104,35 +97,9 @@ public:
cancel(const_cast<worker&>(w));
debug("chat::sender::stopped");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
const XMPPClient xc;
worker w;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Extract the the XMPP JID and password
const list<value> props = params;
const value jid = ((lambda<value(const list<value>&)>)car(props))(list<value>());
const value pass = ((lambda<value(const list<value>&)>)cadr(props))(list<value>());
// Create an XMPP client session
XMPPClient xc(jid, pass, false);
const failable<bool> r = connect(xc);
if (!hasContent(r))
return mkfailure<value>(r);
// Listen and relay messages in a worker thread
worker w(3);
submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(xc)));
// Return the chat sender component lambda function
return value(lambda<value(const list<value>&)>(chatSender(xc, w)));
return failable<value>(value(lvvlambda()));
};
return value(chatSender);
}
}

View file

@ -41,7 +41,7 @@ namespace sender {
/**
* Post an item to an XMPP JID.
*/
const failable<value> post(const lambda<value(const list<value>&)>& jid, const lambda<value(const list<value>&)>& pass, const lambda<value(const list<value>&)>& to, const lambda<value(const list<value>&)>& msg, const list<value>& params) {
const failable<value> post(const lvvlambda& jid, const lvvlambda& pass, const lvvlambda& to, const lvvlambda& msg, const list<value>& params) {
const value vjid = jid(mklist<value>("get", params));
const value vpass = pass(mklist<value>("get", params));
@ -65,14 +65,16 @@ const failable<value> post(const lambda<value(const list<value>&)>& jid, const l
}
/**
* Chat sender component lambda function
* Start the component.
*/
class chatSender {
public:
chatSender(const lambda<value(const list<value>&)>& jid, const lambda<value(const list<value>&)>& pass, const lambda<value(const list<value>&)>& to, const lambda<value(const list<value>&)>& msg) : jid(jid), pass(pass), to(to), msg(msg) {
}
const failable<value> start(const list<value>& params) {
const value operator()(const list<value>& 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<value>& 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<value>();
debug("chat::sender::stop");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
const lambda<value(const list<value>&)> jid;
const lambda<value(const list<value>&)> pass;
const lambda<value(const list<value>&)> to;
const lambda<value(const list<value>&)> msg;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Return the chat sender component lambda function
return value(lambda<value(const list<value>&)>(chatSender(car(params), cadr(params), caddr(params), cadddr(params))));
return failable<value>(value(lvvlambda()));
};
return value(sender);
}
}

View file

@ -51,56 +51,46 @@ const failable<value> post(const list<value>& 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<value(const list<value>&)>& rel) : rel(rel) {
}
const failable<value> start(const list<value>& 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<value> props = hasRelay? cdr(params) : params;
const value jid = ((lvvlambda)car(props))(nilListValue);
const value pass = ((lvvlambda)cadr(props))(nilListValue);
const failable<bool> operator()(const value& jid, const value& val, unused XMPPClient& xc) const {
// Create an XMPP client session
XMPPClient xc(jid, pass, false);
const failable<bool> r = connect(xc);
if (!hasContent(r))
return mkfailure<value>(r);
// Listen and relay messages in a worker thread
worker w(3);
const lambda<const failable<bool>(const value&, const value&, XMPPClient&)> rl = [rel](const value& jid, const value& val, unused XMPPClient& xc) -> const failable<bool> {
// 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<value>("post", mklist<value>(jid), val));
return true;
}
};
private:
const lambda<value(const list<value>&)> rel;
};
/**
* Subscribe and listen to an XMPP session.
*/
class subscribe {
public:
subscribe(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& l, XMPPClient& xc) : l(l), xc(xc) {
}
const failable<bool> operator()() const {
gc_pool pool;
// Subscribe and listen to the XMPP session.
const lambda<const failable<bool>()> subscribe = [rl, xc]() -> const failable<bool> {
const gc_pool pool;
debug("chat::subscribe::listen");
const failable<bool> r = listen(l, const_cast<XMPPClient&>(xc));
const failable<bool> r = listen(rl, const_cast<XMPPClient&>(xc));
debug("chat::subscribe::stopped");
return r;
}
};
submit<failable<bool> >(w, subscribe);
private:
const lambda<failable<bool>(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) {
}
const value operator()(const list<value>& params) const {
// Return the chat sender/receiver component lambda function
const lvvlambda senderReceiver = [xc, w](const list<value>& params) -> const value {
const tuscany::value func(car(params));
if (func == "post")
return post(cdr(params), const_cast<XMPPClient&>(xc));
@ -115,38 +105,9 @@ public:
cancel(const_cast<worker&>(w));
debug("chat::sendreceiver::stopped");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
const XMPPClient xc;
worker w;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& 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<value(const list<value>&)>());
const list<value> props = hasRelay? cdr(params) : params;
const value jid = ((lambda<value(const list<value>&)>)car(props))(list<value>());
const value pass = ((lambda<value(const list<value>&)>)cadr(props))(list<value>());
// Create an XMPP client session
XMPPClient xc(jid, pass, false);
const failable<bool> r = connect(xc);
if (!hasContent(r))
return mkfailure<value>(r);
// Listen and relay messages in a worker thread
worker w(3);
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> rl = relay(rel);
submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(rl, xc)));
// Return the chat sender/receiver component lambda function
return value(lambda<value(const list<value>&)>(chatSenderReceiver(xc, w)));
return failable<value>(value(lvvlambda()));
};
return value(senderReceiver);
}
}

View file

@ -45,12 +45,12 @@ const value pass2("sca2");
const value jid3("sca3@localhost");
const value pass3("sca3");
const list<value> item = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> entry = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> item = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> 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<bool> listener(const value& from, const value& val, unused XMPPCl
return false;
}
struct subscribe {
XMPPClient& xc;
subscribe(XMPPClient& xc) : xc(xc) {
}
const failable<bool> operator()() const {
const lambda<failable<bool>(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>()) XMPPClient(jid3, pass3));
const failable<bool> c = connect(xc);
assert(hasContent(c));
const lambda<failable<bool>()> subs = subscribe(xc);
const lambda<const failable<bool>()> subs = [&xc]() -> const failable<bool> {
const lambda<const failable<bool>(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<value> 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;

View file

@ -52,28 +52,21 @@ const failable<bool> listener(const value& from, const value& val, unused XMPPCl
return false;
}
struct subscribe {
XMPPClient& xc;
subscribe(XMPPClient& xc) : xc(xc) {
}
const failable<bool> operator()() const {
const lambda<failable<bool>(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>()) XMPPClient(jid2, pass2));
const failable<bool> c = connect(xc);
assert(hasContent(c));
const lambda<failable<bool>()> subs = subscribe(xc);
const lambda<const failable<bool>()> subs = [&xc]() -> const failable<bool> {
const lambda<const failable<bool>(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<bool> 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;

View file

@ -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<size_t> send(xmpp_stanza_t* const stanza, XMPPClient& xc);
friend const failable<bool> post(const value& to, const value& val, XMPPClient& xc);
friend const failable<bool> disconnect(XMPPClient& xc);
friend const failable<bool> listen(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc);
friend const failable<bool> listen(const lambda<const failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc);
bool owner;
const bool owner;
xmpp_ctx_t* ctx;
xmpp_conn_t* conn;
lambda<failable<bool>(const value&, const value&, XMPPClient&)> listener;
gc_mutable_ref<lambda<const failable<bool>(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 failable<bool>(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<bool> r = xc.listener(value(string(from)), val, xc);
const lambda<const failable<bool>(const value&, const value&, XMPPClient&)> listener = xc.listener;
const failable<bool> r = listener(value(string(from)), val, xc);
if (!hasContent(r) || !content(r)) {
// Stop listening
xc.listener = lambda<failable<bool>(const value&, const value&, XMPPClient&)>();
xc.listener = lambda<const failable<bool>(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 <presence/> 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<bool> connect(XMPPClient& xc) {
/**
* Send a buffer on an XMPP session.
*/
const failable<size_t> send(const char* data, const size_t len, XMPPClient& xc) {
const failable<size_t> 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<size_t> send(const string& data, XMPPClient& xc) {
* Send a stanza on an XMPP session.
*/
const failable<size_t> 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<bool> 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<bool> disconnect(XMPPClient& xc) {
/**
* Listen to messages received by an XMPP client.
*/
const failable<bool> listen(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc) {
const failable<bool> listen(const lambda<const failable<bool>(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 failable<bool>(const value&, const value&, XMPPClient&)>)xc.listener) && xc.ctx->loop_status == XMPP_LOOP_RUNNING)
xmpp_run_once(xc.ctx, 1000L);
return true;
}

View file

@ -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

View file

@ -38,15 +38,15 @@ namespace constdb {
const string uri("http://localhost:8090/constdb");
bool testConstDb() {
http::CURLSession cs("", "", "", "", 0);
const bool testConstDb() {
const http::CURLSession cs("", "", "", "", 0);
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> a = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ i);
const failable<value> id = http::post(a, uri, cs);
@ -59,18 +59,18 @@ bool testConstDb() {
assert(content(val) == a);
}
const list<value> j = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55")));
const list<value> b = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> j = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$3.55")));
const list<value> b = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
assert(content(r) == trueValue);
}
{
const failable<value> val = http::get(uri + p, cs);
@ -80,7 +80,7 @@ bool testConstDb() {
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
assert(content(r) == trueValue);
}
{
const failable<value> 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<value> val = http::get(uri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const bool testGetPerf() {
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$4.55")));
const list<value> 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<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
const blambda gl = [p, a, cs]() -> const bool {
const failable<value> 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;

View file

@ -37,14 +37,14 @@ namespace constdb {
/**
* Get an item from the database.
*/
const failable<value> get(const list<value>& params, tinycdb::TinyCDB& cdb) {
const failable<value> get(const list<value>& params, const tinycdb::TinyCDB& cdb) {
return tinycdb::get(car(params), cdb);
}
/**
* Post an item to the database.
*/
const failable<value> post(const list<value>& params, tinycdb::TinyCDB& cdb) {
const failable<value> post(const list<value>& params, const tinycdb::TinyCDB& cdb) {
const value id = append<value>(car(params), mklist(mkuuid()));
const failable<bool> val = tinycdb::post(id, cadr(params), cdb);
if (!hasContent(val))
@ -55,7 +55,7 @@ const failable<value> post(const list<value>& params, tinycdb::TinyCDB& cdb) {
/**
* Put an item into the database.
*/
const failable<value> put(const list<value>& params, tinycdb::TinyCDB& cdb) {
const failable<value> put(const list<value>& params, const tinycdb::TinyCDB& cdb) {
const failable<bool> val = tinycdb::put(car(params), cadr(params), cdb);
if (!hasContent(val))
return mkfailure<value>(val);
@ -65,7 +65,7 @@ const failable<value> put(const list<value>& params, tinycdb::TinyCDB& cdb) {
/**
* Delete an item from the database.
*/
const failable<value> del(const list<value>& params, tinycdb::TinyCDB& cdb) {
const failable<value> del(const list<value>& params, const tinycdb::TinyCDB& cdb) {
const failable<bool> val = tinycdb::del(car(params), cdb);
if (!hasContent(val))
return mkfailure<value>(val);
@ -73,14 +73,15 @@ const failable<value> del(const list<value>& params, tinycdb::TinyCDB& cdb) {
}
/**
* Component implementation lambda function.
* Start the component.
*/
class applyConstDb {
public:
applyConstDb(tinycdb::TinyCDB& cdb) : cdb(cdb) {
}
const failable<value> start(unused const list<value>& params) {
// Connect to the configured database and table
const value dbname = ((lvvlambda)car(params))(nilListValue);
const tinycdb::TinyCDB& cdb = *(new (gc_new<tinycdb::TinyCDB>()) tinycdb::TinyCDB(dbname));
const value operator()(const list<value>& params) const {
// Return the component implementation lambda function
const lvvlambda applyConstDb = [cdb](const list<value>& 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<value>();
}
private:
tinycdb::TinyCDB& cdb;
};
/**
* Start the component.
*/
const failable<value> start(unused const list<value>& params) {
// Connect to the configured database and table
const value dbname = ((lambda<value(const list<value>&)>)car(params))(list<value>());
tinycdb::TinyCDB& cdb = *(new (gc_new<tinycdb::TinyCDB>()) tinycdb::TinyCDB(dbname));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyConstDb(cdb)));
};
return value(applyConstDb);
}
}

View file

@ -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<value>("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<value>("c");
TinyCDB cdb("tmp/test.cdb");
const TinyCDB cdb("tmp/test.cdb");
assert(hasContent(post(k, string("CCC"), cdb)));
const lambda<bool()> 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;
}

View file

@ -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>()) 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>()) 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<int> cdbopen(const TinyCDB& cdb);
friend const failable<bool> 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<int> cdbopen(TinyCDB& cdb);
friend const failable<bool> cdbclose(TinyCDB& cdb);
friend const failable<int> cdbopen(const TinyCDB& cdb);
friend const failable<bool> cdbclose(const TinyCDB& cdb);
};
/**
@ -160,7 +165,7 @@ const string dbname(const TinyCDB& cdb) {
/**
* Open a database.
*/
const failable<int> cdbopen(TinyCDB& cdb) {
const failable<int> cdbopen(const TinyCDB& cdb) {
// Get database file serial number
struct stat st;
@ -169,51 +174,51 @@ const failable<int> cdbopen(TinyCDB& cdb) {
return mkfailure<int>(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<int>(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<int>(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<int>(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<bool> cdbclose(TinyCDB& cdb) {
close(cdb.fd);
cdb.fd = -1;
const failable<bool> cdbclose(const TinyCDB& cdb) {
close(cdb.h.fd);
cdb.h.fd = -1;
return true;
}
@ -222,7 +227,7 @@ const failable<bool> 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<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda<failable<bool>(struct cdb_make&)>& finish, buffer& buf, const int tmpfd, TinyCDB& cdb) {
const failable<bool> rewrite(const lambda<const failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda<const failable<bool>(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<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsi
if (::read(fd, buf, 2048) != 2048)
return mkfailure<bool>("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<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsi
if (::read(fd, buf, 8) != 8)
return mkfailure<bool>("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<bool> rewrite(const lambda<failable<bool>(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<bool> u = update(buf, klen, vlen);
if (!hasContent(u))
return u;
@ -293,11 +298,11 @@ const failable<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsi
return true;
}
const failable<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda<failable<bool>(struct cdb_make&)>& finish, TinyCDB& cdb) {
const failable<bool> rewrite(const lambda<const failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda<const failable<bool>(struct cdb_make&)>& finish, const TinyCDB& cdb) {
// Create a new temporary db file
string tmpname = dbname(cdb) + ".XXXXXX";
int tmpfd = mkstemp(const_cast<char*>(c_str(tmpname)));
const string tmpname = dbname(cdb) + ".XXXXXX";
const int tmpfd = mkstemp(const_cast<char*>(c_str(tmpname)));
if (tmpfd == -1)
return mkfailure<bool>("Couldn't create temporary tinycdb database");
@ -314,7 +319,7 @@ const failable<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsi
if (rename(c_str(tmpname), c_str(dbname(cdb))) == -1)
return mkfailure<bool>("Couldn't rename temporary tinycdb database");
cdbclose(cdb);
failable<int> ffd = cdbopen(cdb);
const failable<int> ffd = cdbopen(cdb);
if (!hasContent(ffd))
return mkfailure<bool>(ffd);
@ -324,42 +329,27 @@ const failable<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsi
/**
* Post a new item to the database.
*/
struct postUpdate {
const string ks;
postUpdate(const string& ks) : ks(ks) {
}
const failable<bool> operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const {
if (ks == string((char*)buf, klen))
return mkfailure<bool>("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<bool> 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<bool>(string("Couldn't add tinycdb entry: ") + ks);
return true;
}
};
const failable<bool> post(const value& key, const value& val, TinyCDB& cdb) {
const failable<bool> 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<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = postUpdate(ks);
const lambda<const failable<bool>(buffer&, const unsigned int, const unsigned int)> update = [ks](buffer& buf, const unsigned int klen, unused const unsigned int vlen) -> const failable<bool> {
if (ks == string((char*)buf, klen))
return mkfailure<bool>("Key already exists in tinycdb database");
return true;
};
// Add the new entry to the db
const lambda<failable<bool>(struct cdb_make& cdbm)> finish = postFinish(ks, vs);
const lambda<const failable<bool>(struct cdb_make&)> finish = [ks, vs](struct cdb_make& cdbm) -> const failable<bool> {
if (cdb_make_add(&cdbm, c_str(ks), (unsigned int)length(ks), c_str(vs), (unsigned int)length(vs)) == -1)
return mkfailure<bool>(string("Couldn't add tinycdb entry: ") + ks);
return true;
};
// Rewrite the db
const failable<bool> r = rewrite(update, finish, cdb);
@ -370,42 +360,27 @@ const failable<bool> 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<bool> 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<bool> 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<bool>(string("Couldn't add tinycdb entry: ") + ks);
return true;
}
};
const failable<bool> put(const value& key, const value& val, TinyCDB& cdb) {
const failable<bool> 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<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = putUpdate(ks);
const lambda<const failable<bool>(buffer&, const unsigned int, const unsigned int)> update = [ks](buffer& buf, const unsigned int klen, unused const unsigned int vlen) -> const failable<bool> {
if (ks == string((char*)buf, klen))
return false;
return true;
};
// Add the new entry to the db
const lambda<failable<bool>(struct cdb_make& cdbm)> finish = putFinish(ks, vs);
const lambda<const failable<bool>(struct cdb_make&)> finish = [ks, vs](struct cdb_make& cdbm) -> const failable<bool> {
if (cdb_make_add(&cdbm, c_str(ks), (unsigned int)length(ks), c_str(vs), (unsigned int)length(vs)) == -1)
return mkfailure<bool>(string("Couldn't add tinycdb entry: ") + ks);
return true;
};
// Rewrite the db
const failable<bool> r = rewrite(update, finish, cdb);
@ -416,7 +391,7 @@ const failable<bool> put(const value& key, const value& val, TinyCDB& cdb) {
/**
* Get an item from the database.
*/
const failable<value> get(const value& key, TinyCDB& cdb) {
const failable<value> get(const value& key, const TinyCDB& cdb) {
debug(key, "tinycdb::get::key");
debug(dbname(cdb), "tinycdb::get::dbname");
@ -425,7 +400,7 @@ const failable<value> get(const value& key, TinyCDB& cdb) {
return mkfailure<value>(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<value> get(const value& key, TinyCDB& cdb) {
os << "Couldn't get tinycdb entry: " << key;
return mkfailure<value>(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<value> 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<bool> 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<bool> operator()(unused struct cdb_make& cdbm) const {
return true;
}
};
const failable<bool> del(const value& key, TinyCDB& cdb) {
const failable<bool> 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<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = delUpdate(ks);
const lambda<const failable<bool>(buffer&, const unsigned int, const unsigned int)> update = [ks](buffer& buf, const unsigned int klen, unused const unsigned int vlen) -> const failable<bool> {
if (ks == string((char*)buf, klen))
return false;
return true;
};
// Nothing to do to finish
const lambda<failable<bool>(struct cdb_make& cdbm)> finish = delFinish();
const lambda<const failable<bool>(struct cdb_make&)> finish = [](unused struct cdb_make& cdbm) -> const failable<bool> {
return true;
};
// Rewrite the db
const failable<bool> r = rewrite(update, finish, cdb);

View file

@ -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

View file

@ -38,15 +38,15 @@ namespace filedb {
const string uri("http://localhost:8090/filedb");
bool testFileDB() {
http::CURLSession cs("", "", "", "", 0);
const bool testFileDB() {
const http::CURLSession cs("", "", "", "", 0);
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> a = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ i);
const failable<value> id = http::post(a, uri, cs);
@ -59,18 +59,18 @@ bool testFileDB() {
assert(content(val) == a);
}
const list<value> j = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55")));
const list<value> b = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> j = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$3.55")));
const list<value> b = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
assert(content(r) == trueValue);
}
{
const failable<value> val = http::get(uri + p, cs);
@ -80,7 +80,7 @@ bool testFileDB() {
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
assert(content(r) == trueValue);
}
{
const failable<value> 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<value> val = http::get(uri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const bool testGetPerf() {
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$4.55")));
const list<value> 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<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
const blambda gl = [p, a, cs]() -> const bool {
const failable<value> 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;

View file

@ -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<value>("a", "b");
const list<value> a = mklist<value>(list<value>() + "ns1:a" + (list<value>() + "@xmlns:ns1" + string("http://aaa")) + (list<value>() + "text" + string("Hey!")));
const list<value> b = mklist<value>(list<value>() + "ns1:b" + (list<value>() + "@xmlns:ns1" + string("http://bbb")) + (list<value>() + "text" + string("Hey!")));
const list<value> a = mklist<value>(nilListValue + "ns1:a" + (nilListValue + "@xmlns:ns1" + string("http://aaa")) + (nilListValue + "text" + string("Hey!")));
const list<value> b = mklist<value>(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<value> c;
getLoop(const value& k, FileDB& db) : k(k), db(db),
c(mklist<value>(list<value>() + "ns1:c" + (list<value>() + "@xmlns:ns1" + string("http://ccc")) + (list<value>() + "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<value>("c");
const list<value> c = mklist<value>(list<value>() + "ns1:c" + (list<value>() + "@xmlns:ns1" + string("http://ccc")) + (list<value>() + "text" + string("Hey!")));
const list<value> c = mklist<value>(nilListValue + "ns1:c" + (nilListValue + "@xmlns:ns1" + string("http://ccc")) + (nilListValue + "text" + string("Hey!")));
assert(hasContent(post(k, c, db)));
const lambda<bool()> 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;
}

View file

@ -37,14 +37,14 @@ namespace filedb {
/**
* Get an item from the database.
*/
const failable<value> get(const list<value>& params, filedb::FileDB& db) {
const failable<value> get(const list<value>& params, const filedb::FileDB& db) {
return filedb::get(car(params), db);
}
/**
* Post an item to the database.
*/
const failable<value> post(const list<value>& params, filedb::FileDB& db) {
const failable<value> post(const list<value>& params, const filedb::FileDB& db) {
const value id = append<value>(car(params), mklist(mkuuid()));
const failable<bool> val = filedb::post(id, cadr(params), db);
if (!hasContent(val))
@ -55,7 +55,7 @@ const failable<value> post(const list<value>& params, filedb::FileDB& db) {
/**
* Put an item into the database.
*/
const failable<value> put(const list<value>& params, filedb::FileDB& db) {
const failable<value> put(const list<value>& params, const filedb::FileDB& db) {
const failable<bool> val = filedb::put(car(params), cadr(params), db);
if (!hasContent(val))
return mkfailure<value>(val);
@ -65,7 +65,7 @@ const failable<value> put(const list<value>& params, filedb::FileDB& db) {
/**
* Delete an item from the database.
*/
const failable<value> del(const list<value>& params, filedb::FileDB& db) {
const failable<value> del(const list<value>& params, const filedb::FileDB& db) {
const failable<bool> val = filedb::del(car(params), db);
if (!hasContent(val))
return mkfailure<value>(val);
@ -73,14 +73,17 @@ const failable<value> del(const list<value>& params, filedb::FileDB& db) {
}
/**
* Component implementation lambda function.
* Start the component.
*/
class applyfiledb {
public:
applyfiledb(filedb::FileDB& db) : db(db) {
}
const failable<value> start(const list<value>& params) {
// Connect to the configured database and table
const value dbname = ((lvvlambda)car(params))(nilListValue);
const value format = ((lvvlambda)cadr(params))(nilListValue);
const value operator()(const list<value>& params) const {
const filedb::FileDB& db = *(new (gc_new<filedb::FileDB>()) filedb::FileDB(absdbname(dbname), format));
// Return the component implementation lambda function
const lvvlambda applyfiledb = [db](const list<value>& 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<value>();
}
private:
filedb::FileDB& db;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Connect to the configured database and table
const value dbname = ((lambda<value(const list<value>&)>)car(params))(list<value>());
const value format = ((lambda<value(const list<value>&)>)cadr(params))(list<value>());
filedb::FileDB& db = *(new (gc_new<filedb::FileDB>()) filedb::FileDB(absdbname(dbname), format));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyfiledb(db)));
};
return value(applyfiledb);
}
}

View file

@ -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<bool> write(const value& v, ostream& os, const string& format);
friend const failable<value> read(istream& is, const string& format);
friend const failable<bool> post(const value& key, const value& val, FileDB& db);
friend const failable<bool> put(const value& key, const value& val, FileDB& db);
friend const failable<value> get(const value& key, FileDB& db);
friend const failable<bool> del(const value& key, FileDB& db);
friend const failable<bool> post(const value& key, const value& val, const FileDB& db);
friend const failable<bool> put(const value& key, const value& val, const FileDB& db);
friend const failable<value> get(const value& key, const FileDB& db);
friend const failable<bool> del(const value& key, const FileDB& db);
};
/**
@ -100,7 +92,7 @@ private:
const string filename(const list<value>& 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<bool> mkdirs(const list<value>& 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<bool> mkdirs(const list<value>& path, const string& root) {
*/
const failable<bool> 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<list<string> > s = writeXML(valuesToElements(v));
failable<list<string> > s = xml::writeElements(valuesToElements(v));
if (!hasContent(s))
return mkfailure<bool>(s);
write(content(s), os);
return true;
}
if (format == "json") {
js::JSContext jscx;
failable<list<string> > s = json::writeJSON(valuesToElements(v), jscx);
failable<list<string> > s = json::writeValue(v);
if (!hasContent(s))
return mkfailure<bool>(s);
write(content(s), os);
@ -153,27 +144,25 @@ const failable<bool> write(const value& v, ostream& os, const string& format) {
*/
const failable<value> 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<list<value> > fv = json::readJSON(streamList(is), jscx);
const failable<list<value> > fv = xml::readElements(streamList(is));
if (!hasContent(fv))
return mkfailure<value>(fv);
const value v = elementsToValues(content(fv));
return v;
}
if (format == "json") {
return json::readValue(streamList(is));
}
return mkfailure<value>(string("Unsupported database format: ") + format);
}
/**
* Post a new item to the database.
*/
const failable<bool> post(const value& key, const value& val, FileDB& db) {
const failable<bool> 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<bool> 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<bool> put(const value& key, const value& val, FileDB& db) {
const failable<bool> 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<bool> put(const value& key, const value& val, FileDB& db) {
/**
* Get an item from the database.
*/
const failable<value> get(const value& key, FileDB& db) {
const failable<value> get(const value& key, const FileDB& db) {
debug(key, "filedb::get::key");
debug(db.name, "filedb::get::dbname");
@ -242,7 +231,7 @@ const failable<value> get(const value& key, FileDB& db) {
/**
* Delete an item from the database
*/
const failable<bool> del(const value& key, FileDB& db) {
const failable<bool> del(const value& key, const FileDB& db) {
debug(key, "filedb::delete::key");
debug(db.name, "filedb::delete::dbname");

View file

@ -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

View file

@ -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<value> 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<value> val = http::get(getURI, cs);
assert(hasContent(val));
return true;
}
};
bool testGetPerf() {
http::CURLSession cs("", "", "", "", 0);
const lambda<bool()> 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<value> 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<value> 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<value> val = http::get(deleteURI, cs);
assert(hasContent(val));

View file

@ -37,58 +37,37 @@ namespace httpdelete {
/**
* Evaluate an HTTP delete.
*/
const failable<value> get(const lambda<value(const list<value>&)>& url, http::CURLSession& ch) {
const failable<value> get(const lvvlambda& url, const http::CURLSession& ch) {
debug("httpdelete::get");
const value u = url(mklist<value>("get", list<value>()));
const value u = url(mklist<value>("get", nilListValue));
debug(u, "httpdelete::get::url");
return http::del(u, ch);
}
/**
* Component implementation lambda function.
*/
class applyhttp {
public:
applyhttp(const lambda<value(const list<value>&)>& url, const perthread_ptr<http::CURLSession>& ch) : url(url), ch(ch) {
}
const value operator()(const list<value>& params) const {
debug(params, "httpdelete::applyhttp::params");
const value func(car(params));
if (func == "get")
return get(url, *ch);
return mkfailure<value>();
}
private:
const lambda<value(const list<value>&)> url;
perthread_ptr<http::CURLSession> ch;
};
/**
* Create a new CURL session.
*/
class newsession {
public:
newsession(const lambda<value(const list<value>&)>& timeout) : timeout(timeout) {
}
const gc_ptr<http::CURLSession> operator()() const {
const int t = atoi(c_str((string)timeout(list<value>())));
return new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "", t);
}
private:
const lambda<value(const list<value>&)> timeout;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Create a CURL session
const perthread_ptr<http::CURLSession> ch = perthread_ptr<http::CURLSession>(lambda<gc_ptr<http::CURLSession>()>(newsession(cadr(params))));
const lvvlambda timeout = cadr(params);
const gc_pool cp(gc_current_pool());
const lambda<const gc_ptr<http::CURLSession>()> newsession = [timeout, cp]() -> const gc_ptr<http::CURLSession> {
const gc_scoped_pool sp(pool(cp));
const int t = atoi(c_str((string)timeout(nilListValue)));
return new (gc_new<http::CURLSession>()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t);
};
const perthread_ptr<http::CURLSession> ch = *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<http::CURLSession>(newsession));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyhttp(car(params), ch)));
const lvvlambda url = car(params);
const lvvlambda applyhttp = [url, ch](const list<value>& params) -> const value {
debug(params, "httpdelete::applyhttp::params");
const value func(car(params));
if (func == "get")
return get(url, *ch);
return mkfailure<value>();
};
return value(applyhttp);
}
}

View file

@ -38,59 +38,37 @@ namespace httpget {
/**
* Evaluate an HTTP get.
*/
const failable<value> get(const lambda<value(const list<value>&)>& url, http::CURLSession& ch) {
const failable<value> get(const lvvlambda& url, const http::CURLSession& ch) {
debug("httpget::get");
const value u = url(mklist<value>("get", list<value>()));
const value u = url(mklist<value>("get", nilListValue));
debug(u, "httpget::get::url");
return http::get(u, ch);
}
/**
* Component implementation lambda function.
*/
class applyhttp {
public:
applyhttp(const lambda<value(const list<value>&)>& url, const perthread_ptr<http::CURLSession>& ch) : url(url), ch(ch) {
}
const value operator()(const list<value>& params) const {
debug(params, "httpget::applyhttp::params");
const value func(car(params));
if (func == "get")
return get(url, *ch);
return mkfailure<value>();
}
private:
const lambda<value(const list<value>&)> url;
perthread_ptr<http::CURLSession> ch;
};
/**
* Create a new CURL session.
*/
class newsession {
public:
newsession(const lambda<value(const list<value>&)>& timeout) : timeout(timeout) {
}
const gc_ptr<http::CURLSession> operator()() const {
const int t = atoi(c_str((string)timeout(list<value>())));
return new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "", t);
}
private:
const lambda<value(const list<value>&)> timeout;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Create a CURL session
const perthread_ptr<http::CURLSession> ch = perthread_ptr<http::CURLSession>(lambda<gc_ptr<http::CURLSession>()>(newsession(cadr(params))));
const lvvlambda timeout = cadr(params);
const gc_pool cp(gc_current_pool());
const lambda<const gc_ptr<http::CURLSession>()> newsession = [timeout, cp]() -> const gc_ptr<http::CURLSession> {
const gc_scoped_pool sp(pool(cp));
const int t = atoi(c_str((string)timeout(nilListValue)));
return new (gc_new<http::CURLSession>()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t);
};
const perthread_ptr<http::CURLSession> ch = *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<http::CURLSession>(newsession));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyhttp(car(params), ch)));
const lvvlambda url = car(params);
const lvvlambda applyhttp = [url, ch](const list<value>& params) -> const value {
debug(params, "httpget::applyhttp::params");
const value func(car(params));
if (func == "get")
return get(url, *ch);
return mkfailure<value>();
};
return value(applyhttp);
}
}

View file

@ -38,61 +38,40 @@ namespace httppatch {
/**
* Evaluate an HTTP patch.
*/
const failable<value> get(const lambda<value(const list<value>&)>& url, const lambda<value(const list<value>&)>& val, http::CURLSession& ch) {
const failable<value> get(const lvvlambda& url, const lvvlambda& val, const http::CURLSession& ch) {
debug("httppatch::get");
const value u = url(mklist<value>("get", list<value>()));
const value v = val(mklist<value>("get", list<value>()));
const value u = url(mklist<value>("get", nilListValue));
const value v = val(mklist<value>("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<value(const list<value>&)>& url, const lambda<value(const list<value>&)>& val, const perthread_ptr<http::CURLSession>& ch) : url(url), val(val), ch(ch) {
}
const failable<value> start(const list<value>& params) {
// Create a CURL session
const lvvlambda timeout = caddr(params);
const gc_pool cp(gc_current_pool());
const lambda<const gc_ptr<http::CURLSession>()> newsession = [timeout, cp]() -> const gc_ptr<http::CURLSession> {
const gc_scoped_pool sp(pool(cp));
const int t = atoi(c_str((string)timeout(nilListValue)));
return new (gc_new<http::CURLSession>()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t);
};
const perthread_ptr<http::CURLSession> ch = *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<http::CURLSession>(newsession));
const value operator()(const list<value>& 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<value>& params) -> const value {
debug(params, "httppatch::applyhttp::params");
const value func(car(params));
if (func == "get")
return get(url, val, *ch);
return mkfailure<value>();
}
private:
const lambda<value(const list<value>&)> url;
const lambda<value(const list<value>&)> val;
perthread_ptr<http::CURLSession> ch;
};
/**
* Create a new CURL session.
*/
class newsession {
public:
newsession(const lambda<value(const list<value>&)>& timeout) : timeout(timeout) {
}
const gc_ptr<http::CURLSession> operator()() const {
const int t = atoi(c_str((string)timeout(list<value>())));
return new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "", t);
}
private:
const lambda<value(const list<value>&)> timeout;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Create a CURL session
const perthread_ptr<http::CURLSession> ch = perthread_ptr<http::CURLSession>(lambda<gc_ptr<http::CURLSession>()>(newsession(caddr(params))));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyhttp(car(params), cadr(params), ch)));
};
return value(applyhttp);
}
}

View file

@ -38,61 +38,40 @@ namespace httppost {
/**
* Evaluate an HTTP post.
*/
const failable<value> get(const lambda<value(const list<value>&)>& url, const lambda<value(const list<value>&)>& val, http::CURLSession& ch) {
const failable<value> get(const lvvlambda& url, const lvvlambda& val, const http::CURLSession& ch) {
debug("httppost::get");
const value u = url(mklist<value>("get", list<value>()));
const value v = val(mklist<value>("get", list<value>()));
const value u = url(mklist<value>("get", nilListValue));
const value v = val(mklist<value>("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<value(const list<value>&)>& url, const lambda<value(const list<value>&)>& val, const perthread_ptr<http::CURLSession>& ch) : url(url), val(val), ch(ch) {
}
const failable<value> start(const list<value>& params) {
// Create a CURL session
const lvvlambda timeout = caddr(params);
const gc_pool cp(gc_current_pool());
const lambda<const gc_ptr<http::CURLSession>()> newsession = [timeout, cp]() -> const gc_ptr<http::CURLSession> {
const gc_scoped_pool sp(pool(cp));
const int t = atoi(c_str((string)timeout(nilListValue)));
return new (gc_new<http::CURLSession>()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t);
};
const perthread_ptr<http::CURLSession> ch = *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<http::CURLSession>(newsession));
const value operator()(const list<value>& 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<value>& params) -> const value {
debug(params, "httppost::applyhttp::params");
const value func(car(params));
if (func == "get")
return get(url, val, *ch);
return mkfailure<value>();
}
private:
const lambda<value(const list<value>&)> url;
const lambda<value(const list<value>&)> val;
perthread_ptr<http::CURLSession> ch;
};
/**
* Create a new CURL session.
*/
class newsession {
public:
newsession(const lambda<value(const list<value>&)>& timeout) : timeout(timeout) {
}
const gc_ptr<http::CURLSession> operator()() const {
const int t = atoi(c_str((string)timeout(list<value>())));
return new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "", t);
}
private:
const lambda<const value(const list<value>&)> timeout;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Create a CURL session
const perthread_ptr<http::CURLSession> ch = perthread_ptr<http::CURLSession>(lambda<gc_ptr<http::CURLSession>()>(newsession(caddr(params))));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyhttp(car(params), cadr(params), ch)));
};
return value(applyhttp);
}
}

View file

@ -38,61 +38,40 @@ namespace httpput {
/**
* Evaluate an HTTP put.
*/
const failable<value> get(const lambda<value(const list<value>&)>& url, const lambda<value(const list<value>&)>& val, http::CURLSession& ch) {
const failable<value> get(const lvvlambda& url, const lvvlambda& val, const http::CURLSession& ch) {
debug("httpput::get");
const value u = url(mklist<value>("get", list<value>()));
const value v = val(mklist<value>("get", list<value>()));
const value u = url(mklist<value>("get", nilListValue));
const value v = val(mklist<value>("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<value(const list<value>&)>& url, const lambda<value(const list<value>&)>& val, const perthread_ptr<http::CURLSession>& ch) : url(url), val(val), ch(ch) {
}
const failable<value> start(const list<value>& params) {
// Create a CURL session
const lvvlambda timeout = caddr(params);
const gc_pool cp(gc_current_pool());
const lambda<const gc_ptr<http::CURLSession>()> newsession = [timeout, cp]() -> const gc_ptr<http::CURLSession> {
const gc_scoped_pool sp(pool(cp));
const int t = atoi(c_str((string)timeout(nilListValue)));
return new (gc_new<http::CURLSession>()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, t);
};
const perthread_ptr<http::CURLSession> ch = *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<http::CURLSession>(newsession));
const value operator()(const list<value>& 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<value>& params) -> const value {
debug(params, "httpput::applyhttp::params");
const value func(car(params));
if (func == "get")
return get(url, val, *ch);
return mkfailure<value>();
}
private:
const lambda<value(const list<value>&)> url;
const lambda<value(const list<value>&)> val;
perthread_ptr<http::CURLSession> ch;
};
/**
* Create a new CURL session.
*/
class newsession {
public:
newsession(const lambda<value(const list<value>&)>& timeout) : timeout(timeout) {
}
const gc_ptr<http::CURLSession> operator()() const {
const int t = atoi(c_str((string)timeout(list<value>())));
return new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "", t);
}
private:
const lambda<value(const list<value>&)> timeout;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Create a CURL session
const perthread_ptr<http::CURLSession> ch = perthread_ptr<http::CURLSession>(lambda<gc_ptr<http::CURLSession>()>(newsession(caddr(params))));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyhttp(car(params), cadr(params), ch)));
};
return value(applyhttp);
}
}

View file

@ -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

View file

@ -38,15 +38,15 @@ namespace log {
const string uri("http://localhost:8090/log");
bool testLog() {
http::CURLSession cs("", "", "", "", 0);
const bool testLog() {
const http::CURLSession cs("", "", "", "", 0);
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> a = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ i);
const failable<value> 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<value> id = http::post(a, uri, cs);
assert(hasContent(id));
return true;
}
};
bool testLogPerf() {
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const bool testLogPerf() {
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> 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<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const lambda<bool()> ll = logLoop(a, uri, cs);
const blambda ll = [a, uri, cs]() -> const bool {
const failable<value> 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<value> res = http::evalExpr(mklist<value>(string("sum"), 33, 22), string("http://localhost:8090/client"), cs);
assert(hasContent(res));

View file

@ -38,7 +38,7 @@ namespace log {
/**
* Post an item to the Scribe log.
*/
const failable<value> post(const list<value>& params, const value& host, const value& category, scribe::Scribe& sc) {
const failable<value> post(const list<value>& params, const value& host, const value& category, const scribe::Scribe& sc) {
debug(cadr(params), "log::post::value");
const failable<bool> val = scribe::log(cadr(params), host, category, sc);
if (!hasContent(val))
@ -46,42 +46,27 @@ const failable<value> post(const list<value>& params, const value& host, const v
return value(mklist<value>(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<value>& params) const {
const value func(car(params));
if (func == "post")
return post(cdr(params), host, category, sc);
return mkfailure<value>();
}
private:
const value host;
const value category;
scribe::Scribe& sc;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Connect to Scribe
scribe::Scribe& sc = *(new (gc_new<scribe::Scribe>()) scribe::Scribe("localhost", 1464));
const scribe::Scribe& sc = *(new (gc_new<scribe::Scribe>()) scribe::Scribe("localhost", 1464));
// Extract the configured category
const value host = ((lambda<value(const list<value>&)>)car(params))(list<value>());
const value category = ((lambda<value(const list<value>&)>)cadr(params))(list<value>());
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<value(const list<value>&)>(applyLog(host, category, sc)));
const lvvlambda applyLog = [host, category, sc](const list<value>& params) -> const value {
const value func(car(params));
if (func == "post")
return post(cdr(params), host, category, sc);
return mkfailure<value>();
};
return value(applyLog);
}
}

View file

@ -37,14 +37,21 @@ namespace tuscany {
namespace logger {
/**
* Component implementation lambda function.
* Start the component.
*/
class applyLog {
public:
applyLog(const lambda<value(const list<value>&)>& relay, const value& host, const value& category, scribe::Scribe& sc) : relay(relay), host(host), category(category), sc(sc) {
}
const failable<value> start(const list<value>& params) {
// Connect to Scribe
const scribe::Scribe& sc = *(new (gc_new<scribe::Scribe>()) scribe::Scribe("localhost", 1464));
const value operator()(const list<value>& 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<value>& 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<value(const list<value>&)> relay;
const value host;
const value category;
scribe::Scribe& sc;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Connect to Scribe
scribe::Scribe& sc = *(new (gc_new<scribe::Scribe>()) scribe::Scribe("localhost", 1464));
// Extract the configured relay service and category
const value rel = car(params);
const value host = ((lambda<value(const list<value>&)>)cadr(params))(list<value>());
const value category = ((lambda<value(const list<value>&)>)caddr(params))(list<value>());
debug(host, "logger::start::host");
debug(category, "logger::start::category");
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyLog(rel, host, category, sc)));
};
return value(applyLog);
}
}

View file

@ -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>()) 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]);
}

View file

@ -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]));
}

View file

@ -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<apache::thrift::transport::TTransport> transport;
@ -135,8 +125,8 @@ const failable<bool> 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<bool> 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<bool>("Could not log value, retry later");
} catch (const std::exception& e) {
return mkfailure<bool>(e.what());
@ -165,24 +155,24 @@ const failable<string> 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");
}

View file

@ -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

View file

@ -46,15 +46,15 @@ namespace queue {
const value key(mklist<value>(string("report")));
const string qname("reportq");
const list<value> item = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> entry = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> item = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> 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<bool> 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<bool(const value&, const value&)> l(listener);
const lambda<const bool(const value&, const value&)> 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<value> id = http::post(entry, "http://localhost:8090/print-sender", ch);
assert(hasContent(id));
return true;

View file

@ -45,7 +45,7 @@ namespace queue {
const value key(mklist<value>("test"));
const string qname("testq");
bool testDeclareQueue() {
const bool testDeclareQueue() {
QpidConnection qc;
QpidSession qs(qc);
const failable<bool> r = declareQueue(key, qname, qs);
@ -53,12 +53,12 @@ bool testDeclareQueue() {
return true;
}
const list<value> item = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> item = nilListValue
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99"));
const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
bool testPost() {
const bool testPost() {
QpidConnection qc;
QpidSession qs(qc);
const failable<bool> 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<bool(const value&, const value&)> l(listener);
const lambda<const bool(const value&, const value&)> l(listener);
listen(qname, l, qsub);
return true;
}

View file

@ -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<bool> close(QpidSession& qs) {
* Declare a key / AMQP queue pair.
*/
const failable<bool> 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<bool> declareQueue(const value& key, const string& name, QpidSess
const failable<bool> 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<bool> listen(const string& name, const lambda<bool(const value&, const value&)>& l, QpidSubscription& qsub);
friend const failable<bool> listen(const string& name, const lambda<const bool(const value&, const value&)>& l, QpidSubscription& qsub);
friend const failable<bool> stop(QpidSubscription& qsub);
const bool owner;
@ -214,14 +207,14 @@ private:
*/
class Listener : public qpid::client::MessageListener {
public:
Listener(const lambda<bool(const value&, const value&)> l, qpid::client::SubscriptionManager& subs) : l(l), subs(subs) {
Listener(const lambda<const bool(const value&, const value&)> 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<bool(const value&, const value&)> l;
const lambda<const bool(const value&, const value&)> l;
qpid::client::SubscriptionManager& subs;
};
const failable<bool> listen(const string& name, const lambda<bool(const value&, const value&)>& l, QpidSubscription& qsub) {
const failable<bool> listen(const string& name, const lambda<const bool(const value&, const value&)>& l, QpidSubscription& qsub) {
debug("queue::listen");
Listener listener(l, qsub.subs);
try {

View file

@ -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<value(const list<value>&)>& rel) : rel(rel) {
}
const failable<value> start(const list<value>& 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<value>)pk : mklist<value>(pk);
const value qname = ((lvvlambda)caddr(params))(nilListValue);
const bool operator()(const value& k, const value& v) const {
// 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);
const worker w(3);
const lambda<const bool(const value&, const value&)> 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<value>("post", isList(k)? (list<value>)k : mklist<value>(k), v));
return true;
}
};
private:
const lambda<value(const list<value>&)> rel;
};
/**
* Subscribe and listen to an AMQP queue.
*/
class subscribe {
public:
subscribe(const string& qname, const lambda<bool(const value&, const value&)>& l, const QpidSubscription& qsub) : qname(qname), l(l), qsub(qsub) {
}
const failable<bool> operator()() const {
gc_pool pool;
// Subscribe and listen to the AMQP queue.
const lambda<const failable<bool>()> subscribe = [qname, rl, qsub]() -> const failable<bool> {
const gc_pool pool;
debug(qname, "queue::subscribe::listen");
const failable<bool> r = listen(qname, l, const_cast<QpidSubscription&>(qsub));
const failable<bool> r = listen(qname, rl, const_cast<QpidSubscription&>(qsub));
debug(qname, "queue::subscribe::stopped");
return r;
}
};
submit<failable<bool> >(w, subscribe);
private:
const string qname;
const lambda<bool(const value&, const value&)> 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) {
}
const value operator()(const list<value>& params) const {
// Return the listener component lambda function
const lvvlambda listener = [qc, qs, qsub, w](const list<value>& params) -> const value {
const tuscany::value func(car(params));
// Stop the component
@ -107,41 +95,9 @@ public:
cancel(const_cast<worker&>(w));
debug("queue::listener::stopped");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
QpidConnection qc;
QpidSession qs;
QpidSubscription qsub;
worker w;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Extract the relay reference and the AMQP key and queue name
const value rel = car(params);
const value pk = ((lambda<value(const list<value>&)>)cadr(params))(list<value>());
const value key = isList(pk)? (list<value>)pk : mklist<value>(pk);
const value qname = ((lambda<value(const list<value>&)>)caddr(params))(list<value>());
// 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<bool(const value&, const value&)> rl = relay(rel);
submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(qname, rl, qsub)));
// Return the listener component lambda function
return value(lambda<value(const list<value>&)>(listener(qc, qs, qsub, w)));
return failable<value>(value(lvvlambda()));
};
return value(listener);
}
}

View file

@ -48,7 +48,7 @@ const failable<value> post(const list<value>& params) {
QpidSession qs(qc);
// Post the item
const value pk = ((lambda<value(const list<value>&)>)caddr(params))(list<value>());
const value pk = ((lvvlambda)caddr(params))(nilListValue);
const value key = isList(pk)? append<value>(pk, (list<value>)car(params)) : cons<value>(pk, (list<value>)car(params));
debug(key, "queue::post::key");
debug(cadr(params), "queue::post::value");

View file

@ -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

View file

@ -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<value> val = http::get(postURI, cs);
assert(hasContent(val));

View file

@ -38,7 +38,7 @@ namespace smtppost {
/**
* Post/send an email message using SMTP.
*/
const failable<value> 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<value> 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<list<list<string> > > freq = http::contentRequest(val, url);
if (!hasContent(freq))
@ -52,7 +52,7 @@ const failable<value> post(const string& url, const string& user, const string&
http::cleanup(cs);
return mkfailure<value>(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<value> post(const string& url, const string& user, const string&
}
http::cleanup(cs);
return value(true);
return trueValue;
}
/**
* Evaluate an SMTP post/send.
*/
const failable<value> get(const lambda<value(const list<value>&)>& url,
const lambda<value(const list<value>&)>& user, const lambda<value(const list<value>&)>& pass,
const lambda<value(const list<value>&)>& from, const lambda<value(const list<value>&)>& to,
const lambda<value(const list<value>&)>& subject, const lambda<value(const list<value>&)>& val,
http::CURLSession& ch) {
const failable<value> 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<value>("get", list<value>()));
const value i = user(mklist<value>("get", list<value>()));
const value p = pass(mklist<value>("get", list<value>()));
const value f = from(mklist<value>("get", list<value>()));
const value t = to(mklist<value>("get", list<value>()));
const value s = subject(mklist<value>("get", list<value>()));
const value v = val(mklist<value>("get", list<value>()));
const value u = url(mklist<value>("get", nilListValue));
const value i = user(mklist<value>("get", nilListValue));
const value p = pass(mklist<value>("get", nilListValue));
const value f = from(mklist<value>("get", nilListValue));
const value t = to(mklist<value>("get", nilListValue));
const value s = subject(mklist<value>("get", nilListValue));
const value v = val(mklist<value>("get", nilListValue));
debug(u, "smtppost::get::url");
debug(i, "smtppost::get::user");
debug(p, "smtppost::get::pass");
@ -118,53 +118,33 @@ const failable<value> get(const lambda<value(const list<value>&)>& url,
}
/**
* Component implementation lambda function.
* Start the component.
*/
class applysmtp {
public:
applysmtp(const lambda<value(const list<value>&)>& url,
const lambda<value(const list<value>&)>& user, const lambda<value(const list<value>&)>& pass,
const lambda<value(const list<value>&)>& from, const lambda<value(const list<value>&)>& to,
const lambda<value(const list<value>&)>& subject, const lambda<value(const list<value>&)>& val,
perthread_ptr<http::CURLSession>& ch) :
url(url), user(user), pass(pass), from(from), to(to), subject(subject), val(val), ch(ch) {
}
const failable<value> start(const list<value>& params) {
// Create a CURL session
const gc_pool cp(gc_current_pool());
const lambda<const gc_ptr<http::CURLSession>()> newsession = [cp]() -> const gc_ptr<http::CURLSession> {
const gc_scoped_pool sp(pool(cp));
return new (gc_new<http::CURLSession>()) http::CURLSession(emptyString, emptyString, emptyString, emptyString, 0);
};
const perthread_ptr<http::CURLSession> ch = *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<http::CURLSession>(newsession));
const value operator()(const list<value>& 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<value>& 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<value>();
}
private:
const lambda<value(const list<value>&)> url;
const lambda<value(const list<value>&)> user;
const lambda<value(const list<value>&)> pass;
const lambda<value(const list<value>&)> from;
const lambda<value(const list<value>&)> to;
const lambda<value(const list<value>&)> subject;
const lambda<value(const list<value>&)> val;
perthread_ptr<http::CURLSession> ch;
};
/**
* Create a new CURL session.
*/
const gc_ptr<http::CURLSession> newsession() {
return new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "", 0);
}
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Create a CURL session
perthread_ptr<http::CURLSession> ch = perthread_ptr<http::CURLSession>(lambda<gc_ptr<http::CURLSession>()>(newsession));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applysmtp(car(params), cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params), caddddddr(params), ch)));
};
return value(applysmtp);
}
}

View file

@ -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

View file

@ -38,15 +38,15 @@ namespace sqldb {
const string uri("http://localhost:8090/sqldb");
bool testSqlDb() {
http::CURLSession cs("", "", "", "", 0);
const bool testSqlDb() {
const http::CURLSession cs("", "", "", "", 0);
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> a = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ i);
const failable<value> id = http::post(a, uri, cs);
@ -59,18 +59,18 @@ bool testSqlDb() {
assert(content(val) == a);
}
const list<value> j = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55")));
const list<value> b = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> j = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$3.55")));
const list<value> b = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
assert(content(r) == trueValue);
}
{
const failable<value> val = http::get(uri + p, cs);
@ -80,7 +80,7 @@ bool testSqlDb() {
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
assert(content(r) == trueValue);
}
{
const failable<value> 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<value> val = http::get(uri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const bool testGetPerf() {
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$4.55")));
const list<value> 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<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
const blambda gl = [p, a, cs]() -> const bool {
const failable<value> 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;

View file

@ -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<value>("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<value>("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<bool()> 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;
}

View file

@ -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<value>("a");
const value lk = mklist<value>(mklist<value>("like", "%"), mklist<value>("limit", "2"));
const value rx = mklist<value>(mklist<value>("regex", "a"), mklist<value>("limit", "2"));
const value ts = mklist<value>(mklist<value>("textsearch", "AAA"), mklist<value>("limit", "2"));
const value rxts = mklist<value>(mklist<value>("regex", "a"), mklist<value>("textsearch", "AAA"), mklist<value>("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<value>(car<value>(content(get(lk, pg)))) == value(string("AAA")));
assert(cadr<value>(car<value>(content(get(rx, pg)))) == value(string("AAA")));
assert(cadr<value>(car<value>(content(get(ts, pg)))) == value(string("AAA")));
assert(cadr<value>(car<value>(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<value>("c");
PGSql pg("host=localhost port=6432 dbname=db", "test");
assert(hasContent(post(k, string("CCC"), pg)));
const lambda<bool()> 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;
}

View file

@ -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<bool>(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<bool>(string("Couldn't execute postgresql column select statement: ") + pgfailure(kr, conn));
return;
@ -82,25 +83,16 @@ public:
mkfailure<bool>(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<bool> setup(const PGSql& pgsql);
friend const failable<bool> post(const value& key, const value& val, const PGSql& pgsql);
@ -133,7 +126,7 @@ const failable<bool> 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<bool>(string("Couldn't reconnect to postgresql database: ") + PQerrorMessage(pgsql.conn));
@ -150,10 +143,10 @@ const failable<bool> 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<bool>(string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
PQclear(r);
@ -172,10 +165,10 @@ const failable<bool> 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<bool>(string("Couldn't execute update postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
const string t = PQcmdTuples(r);
@ -186,7 +179,7 @@ const failable<bool> 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<bool>(string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(pr, pgsql.conn));
PQclear(pr);
@ -196,7 +189,58 @@ const failable<bool> 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<value> keyid(const list<value>& key) {
if (isNil(key))
return nilListValue;
if (isList(car(key)))
return keyid(cdr(key));
return cons<value>(car(key), keyid(cdr(key)));
}
/**
* Convert a key to an param name / value assoc.
*/
const list<list<value> > keyparams(const list<value>& key) {
if (isNil(key))
return nilListValue;
if (!isList(car(key)))
return keyparams(cdr(key));
return cons<list<value> >((list<value>)car(key), keyparams(cdr(key)));
}
/**
* Convert a get result to a list of items.
*/
const list<value> 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<value>(mklist<value>(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<value> get(const value& key, const PGSql& pgsql) {
debug(key, "pgsql::get::key");
@ -204,21 +248,99 @@ const failable<value> 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<list<value> > kparams = lk? keyparams(key) : list<list<value> >();
const list<value> regex = assoc<value>("regex", kparams);
const list<value> like = assoc<value>("like", kparams);
const list<value> textsearch = assoc<value>("textsearch", kparams);
const list<value> limit = assoc<value>("limit", kparams);
const list<value> offset = assoc<value>("offset", kparams);
const list<value> id = lk? keyid(key) : nilListValue;
const list<value> atable = assoc<value>("table", kparams);
const string table = isNil(atable)? pgsql.table : (string)cadr(atable);
const list<value> akname = assoc<value>("kcolumn", kparams);
const string kname = isNil(akname)? pgsql.kname : (string)cadr(akname);
const list<value> avname = assoc<value>("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<value>(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<value>(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<value> 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<bool> 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<bool>(string("Couldn't execute delete postgresql SQL statement: ") + pgfailure(r, pgsql.conn));
PQclear(r);

View file

@ -38,14 +38,14 @@ namespace sqldb {
/**
* Get an item from the database.
*/
const failable<value> get(const list<value>& params, pgsql::PGSql& pg) {
const failable<value> get(const list<value>& params, const pgsql::PGSql& pg) {
return pgsql::get(car(params), pg);
}
/**
* Post an item to the database.
*/
const failable<value> post(const list<value>& params, pgsql::PGSql& pg) {
const failable<value> post(const list<value>& params, const pgsql::PGSql& pg) {
const value id = append<value>(car(params), mklist(mkuuid()));
const failable<bool> val = pgsql::post(id, cadr(params), pg);
if (!hasContent(val))
@ -56,7 +56,7 @@ const failable<value> post(const list<value>& params, pgsql::PGSql& pg) {
/**
* Put an item into the database.
*/
const failable<value> put(const list<value>& params, pgsql::PGSql& pg) {
const failable<value> put(const list<value>& params, const pgsql::PGSql& pg) {
const failable<bool> val = pgsql::put(car(params), cadr(params), pg);
if (!hasContent(val))
return mkfailure<value>(val);
@ -66,7 +66,7 @@ const failable<value> put(const list<value>& params, pgsql::PGSql& pg) {
/**
* Delete an item from the database.
*/
const failable<value> del(const list<value>& params, pgsql::PGSql& pg) {
const failable<value> del(const list<value>& params, const pgsql::PGSql& pg) {
const failable<bool> val = pgsql::del(car(params), pg);
if (!hasContent(val))
return mkfailure<value>(val);
@ -74,14 +74,23 @@ const failable<value> del(const list<value>& params, pgsql::PGSql& pg) {
}
/**
* Component implementation lambda function.
* Start the component.
*/
class applySqldb {
public:
applySqldb(const perthread_ptr<pgsql::PGSql>& pg) : pg(pg) {
}
const failable<value> start(const list<value>& 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<const gc_ptr<pgsql::PGSql>()> newPGSql = [conninfo, table, cp]() -> const gc_ptr<pgsql::PGSql> {
debug("sqldb::newPGSql");
const gc_scoped_pool sp(pool(cp));
return new (gc_new<pgsql::PGSql>()) pgsql::PGSql(conninfo, table);
};
const perthread_ptr<pgsql::PGSql> pg = *(new (gc_new<perthread_ptr<pgsql::PGSql> >()) perthread_ptr<pgsql::PGSql>(newPGSql));
const value operator()(const list<value>& params) const {
// Return the component implementation lambda function
const lvvlambda applySqldb = [pg](const list<value>& 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<value>();
}
private:
const perthread_ptr<pgsql::PGSql> 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<pgsql::PGSql> operator()() const {
return new (gc_new<pgsql::PGSql>()) pgsql::PGSql(conninfo, table);
}
private:
const string conninfo;
const string table;
};
/**
* Start the component.
*/
const failable<value> start(unused const list<value>& params) {
// Connect to the configured database and table
const value conninfo = ((lambda<value(const list<value>&)>)car(params))(list<value>());
const value table = ((lambda<value(const list<value>&)>)cadr(params))(list<value>());
const perthread_ptr<pgsql::PGSql> pg(lambda<gc_ptr<pgsql::PGSql>()>(newPGSql(conninfo, table)));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applySqldb(pg)));
};
return value(applySqldb);
}
}

View file

@ -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

View file

@ -45,11 +45,11 @@ const string customerElement =
"<account><id>4567</id><balance>3000</balance></account>"
"</customer>";
const string echo("<ns1:echoString xmlns:ns1=\"http://ws.apache.org/axis2/services/echo\">\n"
" <text>Hello World!</text>\n"
const string echo("<ns1:echoString xmlns:ns1=\"http://ws.apache.org/axis2/services/echo\">"
"<text>Hello World!</text>"
"</ns1:echoString>");
bool testAxiom() {
const bool testAxiom() {
const Axis2Context ax;
{
const failable<axiom_node_t*> n = stringToAxiomNode(customerElement, ax);
@ -60,9 +60,9 @@ bool testAxiom() {
}
{
const list<value> arg = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "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<axiom_node_t*> n = valuesToAxiomNode(arg, ax);
assert(hasContent(n));
const failable<const string> x = axiomNodeToString(content(n), ax);

View file

@ -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;

View file

@ -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<const value*>((value*)ap_get_module_config(r->request_config, &axis2_module));
const value* const rv = const_cast<const value*>((value*)ap_get_module_config(r->request_config, &axis2_module));
cout << "relay: " << rv << endl;
const lambda<value(const list<value>&)> relay = *rv;
const lvvlambda relay = *rv;
const value res = relay(expr);
debug(res, "webservice::serviceInvoke::result");

View file

@ -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<value> arg = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "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<value> rval = evalExpr(mklist<value>(func, arg, string("http://localhost:9090/axis2/services/echo")), ax);
assert(hasContent(rval));
const list<value> r = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples"))
+ (list<value>() + "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;

View file

@ -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<axutil_env_t*>(env)), owner(false) {
Axis2Context(const axutil_env_t* const env) : env(const_cast<axutil_env_t*>(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<axiom_node_t*> stringToAxiomNode(const string& s, const Axis2Context& ax) {
axiom_node_t* node = axiom_node_create_from_buffer(env(ax), const_cast<axis2_char_t*>(c_str(s)));
axiom_node_t* const node = axiom_node_create_from_buffer(env(ax), const_cast<axis2_char_t*>(c_str(s)));
if (node == NULL)
return mkfailure<axiom_node_t*>(string("Couldn't convert XML to Axiom node: ") + axis2Error(ax));
return node;
@ -119,7 +112,7 @@ const failable<axiom_node_t*> stringToAxiomNode(const string& s, const Axis2Cont
* Convert a list of values representing XML elements to an Axiom node.
*/
const failable<axiom_node_t*> valuesToAxiomNode(const list<value>& l, const Axis2Context& ax) {
const failable<list<string> > xml = writeXML(valuesToElements(l), false);
const failable<list<string> > xml = xml::writeElements(valuesToElements(l), false);
if (!hasContent(xml))
return mkfailure<axiom_node_t*>(xml);
ostringstream os;
@ -130,8 +123,8 @@ const failable<axiom_node_t*> valuesToAxiomNode(const list<value>& l, const Axis
/**
* Convert an axiom node to a string.
*/
const failable<const string> axiomNodeToString(axiom_node_t* node, const Axis2Context& ax) {
const char* c = axiom_node_to_string(node, env(ax));
const failable<const string> 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<const string>(string("Couldn't convert Axiom node to XML: ") + axis2Error(ax));
const string s(c);
@ -142,12 +135,12 @@ const failable<const string> axiomNodeToString(axiom_node_t* node, const Axis2Co
/**
* Convert an axiom node to a list of values representing XML elements.
*/
const failable<const list<value> > axiomNodeToValues(axiom_node_t* node, const Axis2Context& ax) {
const failable<const list<value> > axiomNodeToValues(axiom_node_t* const node, const Axis2Context& ax) {
const failable<const string> s = axiomNodeToString(node, ax);
if (!hasContent(s))
return mkfailure<const list<value> >(s);
istringstream is(content(s));
const failable<const list<value> > l = readXML(streamList(is));
const failable<const list<value> > l = content(xml::readElements(streamList(is)));
if (!hasContent(l))
return l;
return elementsToValues(content(l));
@ -166,11 +159,11 @@ const failable<value> evalExpr(const value& expr, const Axis2Context& ax) {
const value uri(caddr<value>(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<value>("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<value> evalExpr(const value& expr, const Axis2Context& ax) {
return mkfailure<value>(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<value>("Couldn't invoke Axis2 service: " + axis2Error(ax));

View file

@ -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<value> arg = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "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<value> rval = evalExpr(mklist<value>(func, arg, string("http://localhost:8090/echo-listener")), ax);
assert(hasContent(rval));
const list<value> r = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "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<value> arg = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "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<value> rval = http::evalExpr(mklist<value>(func, arg), "http://localhost:8090/echo-client", cs);
assert(hasContent(rval));
const list<value> r = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples"))
+ (list<value>() + "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;
}

View file

@ -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"

View file

@ -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"

View file

@ -42,10 +42,10 @@ const failable<value> apply(const value& func, const list<value>& params) {
// Extract parameters
const value doc = car<value>(params);
const lambda<value(const list<value>&)> l = cadr<value>(params);
const lvvlambda l = cadr<value>(params);
// Call the URI property lambda function to get the configured URI
const value uri = l(list<value>());
const value uri = l(nilListValue);
// Evaluate using Axis2
return evalExpr(mklist<value>(func, doc, uri), ax);

View file

@ -44,10 +44,10 @@ extern "C" {
extern module axis2_module;
}
const value redirectToAxis2(const string& uri, request_rec* r, const value& relay) {
const failable<request_rec*, int> nr = httpd::internalRedirectRequest(uri, r);
const failable<value> redirectToAxis2(const string& uri, request_rec* const r, const value& relay) {
const failable<request_rec*> nr = httpd::internalRedirectRequest(uri, r);
if (!hasContent(nr))
return value(reason(nr), rcode(nr));
return mkfailure<value>(reason(nr), rcode(nr));
ap_set_module_config(content(nr)->request_config, &axis2_module, const_cast<void*>((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<value> handle(const list<value>& 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<value> handle(const list<value>& 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);
}
}

View file

@ -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)
JANSSON_INCLUDE="/usr/include"
JANSSON_LIB="/usr/lib"
AC_MSG_RESULT(/usr)
])
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)
])
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

View file

@ -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";

View file

@ -36,7 +36,7 @@
namespace tuscany {
namespace server {
string testURI = "http://localhost:8090";
gc_mutable_ref<string> 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<list<ostream*> > r = http::get<ostream*>(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<value> r = http::getcontent(testURI + "/", ch);
assert(hasContent(r));
assert(contains(car(list<value>(content(r))), "<base href=\"/\"/>"));
return true;
}
};
const bool testGetDocPerf() {
gc_scoped_pool pool;
http::CURLSession ch("", "", "", "", 0);
const lambda<bool()> 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<value> 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<bool()> 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<value> 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<bool()> 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<value> 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<bool()> 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<value> r = http::evalExpr(mklist<value>(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<value> r = http::evalExpr(mklist<value>(string("echo"), string("Hello")), uri, ch);
assert(hasContent(r));
assert(content(r) == string("Hello"));
return true;
}
};
const value blob(string(2048, 'A'));
const list<value> 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<value> r = content(http::evalExpr(mklist<value>(string("echo"), blobs), uri, ch));
assert(hasContent(r));
assert(content(r) == blobs);
return true;
}
};
const bool testEvalPerf() {
gc_scoped_pool pool;
http::CURLSession ch("", "", "", "", 0);
const lambda<bool()> el = evalLoop(testURI, ch);
const gc_scoped_pool pool;
const http::CURLSession ch("", "", "", "", 0);
const blambda el = [ch]() -> const bool {
const failable<value> r = http::evalExpr(mklist<value>(string("echo"), string("Hello")), testURI, ch);
assert(hasContent(r));
assert(content(r) == string("Hello"));
return true;
};
cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl;
if (testBlobs) {
const lambda<bool()> bel = blobEvalLoop(testURI, ch);
const blambda bel = [ch]() -> const bool {
const failable<value> r = content(http::evalExpr(mklist<value>(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<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const bool testPost() {
const gc_scoped_pool pool;
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> 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<value> 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<value> 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<value> 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<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> val = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> val = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ i);
const lambda<bool()> pl = postLoop(testURI, val, ch);
const blambda pl = [val, ch]() -> const bool {
const failable<value> 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<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "blob1" + blob)
+ (list<value>() + "blob2" + blob)
+ (list<value>() + "price" + string("$2.99")));
const list<value> val = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "blob1" + blob)
+ (nilListValue + "blob2" + blob)
+ (nilListValue + "price" + string("$2.99")));
const list<value> val = nilListValue + (nilListValue + "entry"
+ (nilListValue + "title" + string("item"))
+ (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ i);
const lambda<bool()> pl = postBlobLoop(testURI, val, ch);
const blambda pl = [val, ch]() -> const bool {
const gc_scoped_pool pool;
const failable<value> 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<bool()> 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<value> id = http::post(val, testURI, ch);
assert(hasContent(id));
return true;
};
time(pl, 0, count);
return true;
}
const list<future<bool> > startPost(worker& w, const int threads, const lambda<bool()>& l) {
const list<future<bool> > startPost(const worker& w, const int threads, const blambda& l) {
if (threads == 0)
return list<future<bool> >();
return cons(submit(w, l), startPost(w, threads - 1, l));
@ -285,36 +227,27 @@ const bool checkPost(const list<future<bool> >& r) {
return checkPost(cdr(r));
}
struct postThreadLoop {
const lambda<bool()> l;
worker& w;
const int threads;
postThreadLoop(const lambda<bool()>& l, worker& w, const int threads) : l(l), w(w), threads(threads) {
}
const bool operator()() const {
list<future<bool> > 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 worker w(threads);
const list<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const value val = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> 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<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postThread), testURI, count, val);
const lambda<bool()> ptl = postThreadLoop(pl, w, threads);
double t = time(ptl, 0, 1) / (threads * count);
const blambda pl= curry(lambda<const bool(const int, const value)>(postThread), count, val);
const blambda ptl = [pl, w, threads]() -> const bool {
list<future<bool> > 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<bool()> pl = postLoop(uri, val, ch);
const gc_scoped_pool pool;
const http::CURLSession ch("", "", "", "", 0);
const blambda pl = [val, ch]() -> const bool {
const failable<value> id = http::post(val, testURI, ch);
assert(hasContent(id));
return true;
};
time(pl, 0, count);
return true;
}
const list<pid_t> startPost(const int procs, const lambda<bool()>& l) {
const list<pid_t> startPost(const int procs, const blambda& l) {
if (procs == 0)
return list<pid_t>();
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<pid_t>& r) {
return checkPost(cdr(r));
}
struct postForkLoop {
const lambda<bool()> l;
const int procs;
postForkLoop(const lambda<bool()>& l, const int procs) : l(l), procs(procs) {
}
const bool operator()() const {
list<pid_t> 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<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const value val = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const list<value> 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<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postProc), testURI, count, val);
const lambda<bool()> ptl = postForkLoop(pl, procs);
double t = time(ptl, 0, 1) / (procs * count);
const blambda pl= curry(lambda<const bool(const string, const int, const value)>(postProc), testURI, count, val);
const blambda ptl = [pl, procs]() -> const bool {
list<pid_t> 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<value> i = list<value>() + "content" + (list<value>() + "item"
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99")));
const list<value> a = list<value>() + (list<value>() + "entry"
+ (list<value>() + "title" + string("item"))
+ (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
const gc_scoped_pool pool;
const list<value> i = nilListValue + "content" + (nilListValue + "item"
+ (nilListValue + "name" + string("Apple"))
+ (nilListValue + "price" + string("$2.99")));
const list<value> 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;
}

View file

@ -10,6 +10,23 @@
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>
--- 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<LogEntry>& messages) {
- ResultCode result;
+ResultCode::type scribeHandler::Log(const vector<LogEntry>& 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<scribe::thrift::LogEntry>& messages);
+ scribe::thrift::ResultCode::type Log(const std::vector<scribe::thrift::LogEntry>& 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;

View file

@ -1,6 +1,6 @@
--- lib/cpp/src/server/TNonblockingServer.cpp
+++ lib/cpp/src/server/TNonblockingServer.cpp
@@ -622,8 +622,8 @@
@@ -989,8 +989,8 @@
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
sprintf(port, "%d", port_);
@ -14,26 +14,28 @@
--- lib/cpp/src/server/TNonblockingServer.h
+++ lib/cpp/src/server/TNonblockingServer.h
@@ -65,6 +65,9 @@
// Server socket file descriptor
@@ -126,6 +126,9 @@
/// Server socket file descriptor
int serverSocket_;
+ // Host server runs on
+ /// Host server runs on
+ std::string host_;
+
// Port server runs on
/// Port server runs on
int port_;
@@ -117,10 +120,12 @@
@@ -294,11 +297,13 @@
TNonblockingServer(
const boost::shared_ptr<Processor>& processor,
const boost::shared_ptr<TProtocolFactory>& protocolFactory,
+ const std::string host,
int port,
const boost::shared_ptr<ThreadManager>& threadManager =
boost::shared_ptr<ThreadManager>(),
THRIFT_OVERLOAD_IF(Processor, TProcessor)) :
- TServer(processor) {
+ TServer(processor),
+ host_(host) {
init(port);
TNonblockingServer(boost::shared_ptr<TProcessor> processor,
boost::shared_ptr<TProtocolFactory> protocolFactory,
+ std::string host,
int port,
boost::shared_ptr<ThreadManager> threadManager = boost::shared_ptr<ThreadManager>()) :
TServer(processor),
serverSocket_(-1),
+ host_(host),
port_(port),
threadManager_(threadManager),
eventBase_(NULL),

View file

@ -35,27 +35,19 @@ namespace store {
/**
* Returns the catalog.
*/
struct convert {
const lambda<value(const list<value>&)> converter;
const string currency;
convert(const lambda<value(const list<value>&)>& converter, const string& currency) : converter(converter), currency(currency) {
}
const value operator()(const value& price) const {
return converter(mklist<value>("convert", string("USD"), currency, price));
}
};
const list<value> mkfruit(const string& name, const string& code, const string& symbol, const double price) {
return list<value>() +
return nilListValue +
mklist<value>("name", name) + mklist<value>("currencyCode", code) + mklist<value>("currencySymbol", symbol) + mklist<value>("price", price);
}
const failable<value> items(const lambda<value(const list<value>&)>& converter, const lambda<value(const list<value>&)>& currencyCode) {
const string currency(currencyCode(list<value>()));
const failable<value> items(const lvvlambda& converter, const lvvlambda& currencyCode) {
const string currency(currencyCode(nilListValue));
const string symbol(converter(mklist<value>("symbol", currency)));
const lambda<value(const value&)> conv(convert(converter, currency));
const vvlambda conv = [converter, currency](const value& price) -> const value {
return converter(mklist<value>("convert", string("USD"), currency, price));
};
return value(list<value>() +
return value(nilListValue +
mkfruit("Apple", currency, symbol, conv(2.99)) +
mkfruit("Orange", currency, symbol, conv(3.55)) +
mkfruit("Pear", currency, symbol, conv(1.55)));

View file

@ -38,7 +38,7 @@ const string cartId("1234");
* Get the shopping cart from the cache. Return an empty
* cart if not found.
*/
const list<value> getcart(const value& id, const lambda<value(const list<value>&)>& cache) {
const list<value> getcart(const value& id, const lvvlambda& cache) {
const value cart = cache(mklist<value>("get", mklist<value>(id)));
cerr << "cart value: " << cart << "\n";
const failable<value> fcart = cart;
@ -46,14 +46,14 @@ const list<value> getcart(const value& id, const lambda<value(const list<value>&
cerr << "cart content: " << content(fcart) << "\n";
cerr << "cart reason: " << reason(fcart) << "\n";
if (isNil(cart))
return value(list<value>());
return value(nilListValue);
return (list<value>)cart;
}
/**
* Post a new item to the cart. Create a new cart if necessary.
*/
const failable<value> post(unused const list<value>& collection, const value& item, const lambda<value(const list<value>&)>& cache) {
const failable<value> post(unused const list<value>& collection, const value& item, const lvvlambda& cache) {
const value id(mkuuid());
const list<value> newItem(mklist<value>("entry", cadr<value>(car<value>(item)), mklist<value>("id", id), cadddr<value>(car<value>(item))));
const list<value> cart(cons<value>(newItem, getcart(cartId, cache)));
@ -75,7 +75,7 @@ const value find(const value& id, const list<value>& cart) {
/**
* Return items from the cart.
*/
const failable<value> get(const list<value>& id, const lambda<value(const list<value>&)>& cache) {
const failable<value> get(const list<value>& id, const lvvlambda& cache) {
if (isNil(id))
return value(mklist<value>(append(mklist<value>("feed", mklist<value>("title", string("Your Cart")), mklist<value>("id", cartId)), getcart(cartId, cache))));
return find(car(id), getcart(cartId, cache));
@ -84,10 +84,10 @@ const failable<value> get(const list<value>& id, const lambda<value(const list<v
/**
* Delete items from the cart.
*/
const failable<value> del(const list<value>& id, unused const lambda<value(const list<value>&)>& cache) {
const failable<value> del(const list<value>& id, unused const lvvlambda& cache) {
if (isNil(id))
return cache(mklist<value>("delete", mklist<value>(cartId)));
return value(true);
return trueValue;
}
/**
@ -109,7 +109,7 @@ const double sum(const list<value>& items) {
/**
* Return the total price of the items in the cart.
*/
const failable<value> total(const lambda<value(const list<value>&)>& cache) {
const failable<value> total(const lvvlambda& cache) {
const list<value> cart(getcart(cartId, cache));
return value(sum(cart));
}

View file

@ -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

View file

@ -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

View file

@ -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);