diff options
Diffstat (limited to 'sca-cpp/trunk/components/filedb')
-rw-r--r-- | sca-cpp/trunk/components/filedb/client-test.cpp | 26 | ||||
-rw-r--r-- | sca-cpp/trunk/components/filedb/file-test.cpp | 3 | ||||
-rw-r--r-- | sca-cpp/trunk/components/filedb/filedb.cpp | 35 | ||||
-rw-r--r-- | sca-cpp/trunk/components/filedb/filedb.hpp | 27 |
4 files changed, 90 insertions, 1 deletions
diff --git a/sca-cpp/trunk/components/filedb/client-test.cpp b/sca-cpp/trunk/components/filedb/client-test.cpp index 5694d97522..96c0212096 100644 --- a/sca-cpp/trunk/components/filedb/client-test.cpp +++ b/sca-cpp/trunk/components/filedb/client-test.cpp @@ -77,6 +77,32 @@ const bool testFileDB() { 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/filedb/file-test.cpp b/sca-cpp/trunk/components/filedb/file-test.cpp index 5270967ccb..55272800f0 100644 --- a/sca-cpp/trunk/components/filedb/file-test.cpp +++ b/sca-cpp/trunk/components/filedb/file-test.cpp @@ -38,11 +38,14 @@ const bool testFileDB(const string& dbname, const string& format) { 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!"))); + const list<value> c = mklist<value>(nilListValue + "ns1:c" + (nilListValue + "@xmlns:ns1" + string("http://ccc")) + (nilListValue + "text" + string("Hey!"))); assert(hasContent(post(k, a, db))); assert((get(k, db)) == value(a)); assert(hasContent(put(k, b, db))); assert((get(k, db)) == value(b)); + assert(hasContent(patch(k, c, db))); + assert((get(k, db)) == value(c)); assert(hasContent(del(k, db))); assert(!hasContent(get(k, db))); assert(hasContent(post(k, a, db))); diff --git a/sca-cpp/trunk/components/filedb/filedb.cpp b/sca-cpp/trunk/components/filedb/filedb.cpp index 37cb6c5260..b28cc9bedb 100644 --- a/sca-cpp/trunk/components/filedb/filedb.cpp +++ b/sca-cpp/trunk/components/filedb/filedb.cpp @@ -63,6 +63,39 @@ const failable<value> put(const list<value>& params, const filedb::FileDB& db) { } /** + * Patch an item in the database. + */ +const failable<value> patch(const list<value>& params, const filedb::FileDB& db) { + // 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, "filedb::patch::script"); + istringstream is(script); + + // Get existing value from database + const failable<value> ival = filedb::get(car(params), db); + 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 file database entry: " << car(params); + return mkfailure<value>(str(os), 404, false); + } + + // Push patched value to database + const failable<bool> val = filedb::patch(car(params), pval, db); + if (!hasContent(val)) + return mkfailure<value>(val); + return value(content(val)); +} + +/** * Delete an item from the database. */ const failable<value> del(const list<value>& params, const filedb::FileDB& db) { @@ -91,6 +124,8 @@ const failable<value> start(const list<value>& params) { return post(cdr(params), db); if (func == "put") return put(cdr(params), db); + if (func == "patch") + return patch(cdr(params), db); if (func == "delete") return del(cdr(params), db); return mkfailure<value>(); diff --git a/sca-cpp/trunk/components/filedb/filedb.hpp b/sca-cpp/trunk/components/filedb/filedb.hpp index 2855cebfc6..41dde88bef 100644 --- a/sca-cpp/trunk/components/filedb/filedb.hpp +++ b/sca-cpp/trunk/components/filedb/filedb.hpp @@ -82,6 +82,7 @@ private: friend const failable<value> read(istream& is, const string& format); 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<bool> patch(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); }; @@ -208,6 +209,30 @@ const failable<bool> put(const value& key, const value& val, const FileDB& db) { } /** + * Patch an item in the database. If the item doesn't exist it is added. + */ +const failable<bool> patch(const value& key, const value& val, const FileDB& db) { + debug(key, "filedb::patch::key"); + debug(val, "filedb::patch::value"); + debug(db.name, "filedb::patch::dbname"); + + if (isList(key)) + mkdirs(key, db.name); + const string fn = filename(key, db.name); + debug(fn, "filedb::patch::filename"); + ofstream os(fn); + if (os.fail()) { + ostringstream os; + os << "Couldn't patch file database entry: " << key; + return mkfailure<bool>(str(os)); + } + const failable<bool> r = write(val, os, db.format); + + debug(r, "filedb::patch::result"); + return r; +} + +/** * Get an item from the database. */ const failable<value> get(const value& key, const FileDB& db) { @@ -241,7 +266,7 @@ const failable<bool> del(const value& key, const FileDB& db) { if (rc == -1) { ostringstream os; os << "Couldn't delete file database entry: " << key; - return mkfailure<bool>(str(os)); + return errno == ENOENT? mkfailure<bool>(str(os), 404, false) : mkfailure<bool>(str(os)); } debug(true, "filedb::delete::result"); |