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:
parent
86b1de8553
commit
36adc76235
90 changed files with 1428 additions and 1813 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
|
|
|
|||
2
sca-cpp/trunk/components/cache/Makefile.am
vendored
2
sca-cpp/trunk/components/cache/Makefile.am
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@
|
|||
<service name="selector">
|
||||
<binding.http uri="selector"/>
|
||||
</service>
|
||||
</component>
|
||||
</component>
|
||||
|
||||
<component name="partition1">
|
||||
<implementation.scheme script="partition1-test.scm"/>
|
||||
|
|
|
|||
81
sca-cpp/trunk/components/cache/client-test.cpp
vendored
81
sca-cpp/trunk/components/cache/client-test.cpp
vendored
|
|
@ -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;
|
||||
|
|
|
|||
12
sca-cpp/trunk/components/cache/datacache.cpp
vendored
12
sca-cpp/trunk/components/cache/datacache.cpp
vendored
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
26
sca-cpp/trunk/components/cache/memcache-test.cpp
vendored
26
sca-cpp/trunk/components/cache/memcache-test.cpp
vendored
|
|
@ -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();
|
||||
|
|
|
|||
57
sca-cpp/trunk/components/cache/memcache.cpp
vendored
57
sca-cpp/trunk/components/cache/memcache.cpp
vendored
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
78
sca-cpp/trunk/components/cache/memcache.hpp
vendored
78
sca-cpp/trunk/components/cache/memcache.hpp
vendored
|
|
@ -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;
|
||||
|
|
|
|||
2
sca-cpp/trunk/components/cache/memocache.cpp
vendored
2
sca-cpp/trunk/components/cache/memocache.cpp
vendored
|
|
@ -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
|
||||
|
|
|
|||
95
sca-cpp/trunk/components/cache/partitioner.cpp
vendored
95
sca-cpp/trunk/components/cache/partitioner.cpp
vendored
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))))
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
@ -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)));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue