summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/components/cache
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/components/cache')
-rw-r--r--sca-cpp/trunk/components/cache/client-test.cpp26
-rw-r--r--sca-cpp/trunk/components/cache/datacache.cpp16
-rw-r--r--sca-cpp/trunk/components/cache/memcache-test.cpp2
-rw-r--r--sca-cpp/trunk/components/cache/memcache.cpp35
-rw-r--r--sca-cpp/trunk/components/cache/memcache.hpp23
-rw-r--r--sca-cpp/trunk/components/cache/partitioner.cpp19
6 files changed, 120 insertions, 1 deletions
diff --git a/sca-cpp/trunk/components/cache/client-test.cpp b/sca-cpp/trunk/components/cache/client-test.cpp
index 5e9be6c14a..3c8a261f84 100644
--- a/sca-cpp/trunk/components/cache/client-test.cpp
+++ b/sca-cpp/trunk/components/cache/client-test.cpp
@@ -81,6 +81,32 @@ const bool testCache(const string& uri) {
assert(hasContent(val));
assert(content(val) == b);
}
+
+ const list<value> k = nilListValue + "content" + (nilListValue + "item"
+ + (nilListValue + "name" + string("Apple"))
+ + (nilListValue + "price" + string("$3.99")));
+ const list<value> c = nilListValue + (nilListValue + "entry"
+ + (nilListValue + "title" + string("item"))
+ + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ + k);
+
+ {
+ const list<value> s = nilListValue + "content" +
+ (nilListValue + "patch" + string("(define (patch id e) (tree-subst-assoc '(price) '(price \"$3.99\") e))"));
+ const list<value> ps = nilListValue + (nilListValue + "entry"
+ + (nilListValue + "title" + string("item"))
+ + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+ + s);
+
+ const failable<value> r = http::patch(ps, uri + p, cs);
+ assert(hasContent(r));
+ assert(content(r) == trueValue);
+ }
+ {
+ const failable<value> val = http::get(uri + p, cs);
+ assert(hasContent(val));
+ assert(content(val) == c);
+ }
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
diff --git a/sca-cpp/trunk/components/cache/datacache.cpp b/sca-cpp/trunk/components/cache/datacache.cpp
index 975ca43dce..4fafd9e345 100644
--- a/sca-cpp/trunk/components/cache/datacache.cpp
+++ b/sca-cpp/trunk/components/cache/datacache.cpp
@@ -95,6 +95,20 @@ const failable<value> put(const value& key, const value& val, unused const lvvla
}
/**
+ * Patch an item in the cache.
+ */
+const failable<value> patch(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>("patch", key, val));
+
+ // Update level2 cache
+ wcache2(mklist<value>("patch", key, val));
+
+ return trueValue;
+}
+
+/**
* Delete an item from the cache.
*/
const failable<value> del(const value& key, unused const lvvlambda& rcache1, const lvvlambda& wcache1, unused const lvvlambda& rcache2, const lvvlambda& wcache2) {
@@ -121,6 +135,8 @@ const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
return tuscany::datacache::post(cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params), caddddddr(params));
if (func == "put")
return tuscany::datacache::put(cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params), caddddddr(params));
+ if (func == "patch")
+ return tuscany::datacache::patch(cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params), caddddddr(params));
if (func == "delete")
return tuscany::datacache::del(cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params));
return tuscany::mkfailure<tuscany::value>();
diff --git a/sca-cpp/trunk/components/cache/memcache-test.cpp b/sca-cpp/trunk/components/cache/memcache-test.cpp
index 6c6adb0541..10eda45eae 100644
--- a/sca-cpp/trunk/components/cache/memcache-test.cpp
+++ b/sca-cpp/trunk/components/cache/memcache-test.cpp
@@ -40,6 +40,8 @@ bool testMemCached() {
assert(get(k, ch) == value(string("AAA")));
assert(hasContent(put(k, string("aaa"), ch)));
assert(get(k, ch) == value(string("aaa")));
+ assert(hasContent(patch(k, string("bbb"), ch)));
+ assert(get(k, ch) == value(string("bbb")));
assert(hasContent(del(k, ch)));
assert(!hasContent(get(k, ch)));
diff --git a/sca-cpp/trunk/components/cache/memcache.cpp b/sca-cpp/trunk/components/cache/memcache.cpp
index 2e4597efd3..e1a3c7e9af 100644
--- a/sca-cpp/trunk/components/cache/memcache.cpp
+++ b/sca-cpp/trunk/components/cache/memcache.cpp
@@ -63,6 +63,39 @@ const failable<value> put(const list<value>& params, const memcache::MemCached&
}
/**
+ * Patch an item in the cache.
+ */
+const failable<value> patch(const list<value>& params, const memcache::MemCached& ch) {
+ // Read patch
+ value p = assoc<value>("patch", assoc<value>("content", car<value>(cadr(params))));
+ if (isNil(p))
+ return mkfailure<value>("Couldn't read patch script");
+ const string script = cadr<value>(p);
+ debug(script, "memcache::patch::script");
+ istringstream is(script);
+
+ // Get existing value from cache
+ const failable<value> ival = memcache::get(car(params), ch);
+ if (!hasContent(ival) && rcode(ival) != 404)
+ return mkfailure<value>(ival);
+
+ // Apply patch
+ scheme::Env env = scheme::setupEnvironment();
+ const value pval = scheme::evalScript(cons<value>("patch", scheme::quotedParameters(mklist<value>(car(params), hasContent(ival)? content(ival) : (value)list<value>()))), is, env);
+ if (isNil(pval)) {
+ ostringstream os;
+ os << "Couldn't patch memcached entry: " << car(params);
+ return mkfailure<value>(str(os), 404, false);
+ }
+
+ // Push patched value to cache
+ const failable<bool> val = memcache::patch(car(params), pval, ch);
+ if (!hasContent(val))
+ return mkfailure<value>(val);
+ return value(content(val));
+}
+
+/**
* Delete an item from the cache.
*/
const failable<value> del(const list<value>& params, const memcache::MemCached& ch) {
@@ -98,6 +131,8 @@ const failable<value> start(const list<value>& params) {
return post(cdr(params), ch);
if (func == "put")
return put(cdr(params), ch);
+ if (func == "patch")
+ return patch(cdr(params), ch);
if (func == "delete")
return del(cdr(params), ch);
return mkfailure<value>();
diff --git a/sca-cpp/trunk/components/cache/memcache.hpp b/sca-cpp/trunk/components/cache/memcache.hpp
index 00ee9c6291..7962d1caa0 100644
--- a/sca-cpp/trunk/components/cache/memcache.hpp
+++ b/sca-cpp/trunk/components/cache/memcache.hpp
@@ -73,6 +73,7 @@ private:
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);
+ friend const failable<bool> patch(const value& key, const value& val, const MemCached& cache);
friend const failable<value> get(const value& key, const MemCached& cache);
friend const failable<bool> del(const value& key, const MemCached& cache);
@@ -177,6 +178,26 @@ const failable<bool> put(const value& key, const value& val, const MemCached& ca
}
/**
+ * Patch an item in the cache. If the item doesn't exist it is added.
+ */
+const failable<bool> patch(const value& key, const value& val, const MemCached& cache) {
+ debug(key, "memcache::patch::key");
+ debug(val, "memcache::patch::value");
+
+ 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;
+ os << "Couldn't set memcached entry: " << key;
+ return mkfailure<bool>(str(os));
+ }
+
+ debug(true, "memcache::patch::result");
+ return true;
+}
+
+/**
* Get an item from the cache.
*/
const failable<value> get(const value& key, const MemCached& cache) {
@@ -209,7 +230,7 @@ const failable<bool> del(const value& key, const MemCached& cache) {
if (rc != APR_SUCCESS) {
ostringstream os;
os << "Couldn't delete memcached entry: " << key;
- return mkfailure<bool>(str(os));
+ return rc == APR_NOTFOUND? mkfailure<bool>(str(os), 404, false) : mkfailure<bool>(str(os));
}
debug(true, "memcache::delete::result");
diff --git a/sca-cpp/trunk/components/cache/partitioner.cpp b/sca-cpp/trunk/components/cache/partitioner.cpp
index a38c053358..8a56a7f932 100644
--- a/sca-cpp/trunk/components/cache/partitioner.cpp
+++ b/sca-cpp/trunk/components/cache/partitioner.cpp
@@ -143,6 +143,23 @@ const failable<value> put(const value& key, const value& val, const lvvlambda& s
}
/**
+ * Patch an item in a partition.
+ */
+const failable<value> patch(const value& key, const value& val, const lvvlambda& selector, const list<value>& partitions) {
+
+ // Select partition
+ const failable<list<value> > p = partition(key, selector, partitions);
+ if (!hasContent(p))
+ return mkfailure<value>(p);
+
+ // Path item in selected partition
+ const lvvlambda l = car(content(p));
+ l(mklist<value>("patch", key, val));
+
+ return trueValue;
+}
+
+/**
* Delete an item from a partition.
*/
const failable<value> del(const value& key, const lvvlambda& selector, const list<value>& partitions) {
@@ -172,6 +189,8 @@ const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
return tuscany::partitioner::post(cadr(params), caddr(params), cadddr(params), cddddr(params));
if (func == "put")
return tuscany::partitioner::put(cadr(params), caddr(params), cadddr(params), cddddr(params));
+ if (func == "patch")
+ return tuscany::partitioner::patch(cadr(params), caddr(params), cadddr(params), cddddr(params));
if (func == "delete")
return tuscany::partitioner::del(cadr(params), caddr(params), cdddr(params));
return tuscany::mkfailure<tuscany::value>();