diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-12-24 02:54:28 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-12-24 02:54:28 +0000 |
commit | a4f8fcde0e7d4a592eb07628a08b5534abdb2613 (patch) | |
tree | 1501280d607823c5ed3a8d9db98a5b6aedfe2258 /sca-cpp/trunk | |
parent | 0d01ae7c048afc0d978394d4a6508273abac55e2 (diff) |
Add support for XML and JSON formats to file database component.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1052430 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk')
-rw-r--r-- | sca-cpp/trunk/components/filedb/Makefile.am | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/components/filedb/file-test.cpp | 44 | ||||
-rwxr-xr-x | sca-cpp/trunk/components/filedb/filedb-test | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/components/filedb/filedb.composite | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/components/filedb/filedb.cpp | 5 | ||||
-rw-r--r-- | sca-cpp/trunk/components/filedb/filedb.hpp | 137 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/fstream.hpp | 4 |
7 files changed, 151 insertions, 48 deletions
diff --git a/sca-cpp/trunk/components/filedb/Makefile.am b/sca-cpp/trunk/components/filedb/Makefile.am index 9b0e82a54d..90c8b4207d 100644 --- a/sca-cpp/trunk/components/filedb/Makefile.am +++ b/sca-cpp/trunk/components/filedb/Makefile.am @@ -28,12 +28,12 @@ comp_LTLIBRARIES = libfiledb.la noinst_DATA = libfiledb.so libfiledb_la_SOURCES = filedb.cpp -libfiledb_la_LDFLAGS = +libfiledb_la_LDFLAGS = -lxml2 -lmozjs libfiledb.so: ln -s .libs/libfiledb.so file_test_SOURCES = file-test.cpp -file_test_LDFLAGS = +file_test_LDFLAGS = -lxml2 -lmozjs client_test_SOURCES = client-test.cpp client_test_LDFLAGS = -lxml2 -lcurl -lmozjs diff --git a/sca-cpp/trunk/components/filedb/file-test.cpp b/sca-cpp/trunk/components/filedb/file-test.cpp index eba88ecbf7..ff57bd79ce 100644 --- a/sca-cpp/trunk/components/filedb/file-test.cpp +++ b/sca-cpp/trunk/components/filedb/file-test.cpp @@ -32,16 +32,20 @@ namespace tuscany { namespace filedb { -bool testFileDB() { - FileDB db("tmp/testdb"); - const value k = mklist<value>("a"); - - assert(hasContent(post(k, string("AAA"), db))); - assert((get(k, db)) == value(string("AAA"))); - assert(hasContent(put(k, string("aaa"), db))); - assert((get(k, db)) == value(string("aaa"))); +bool testFileDB(const string& dbname, const string& format) { + 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!"))); + + 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(del(k, db))); assert(!hasContent(get(k, db))); + assert(hasContent(post(k, a, db))); return true; } @@ -49,21 +53,25 @@ bool testFileDB() { struct getLoop { const value k; FileDB& db; - getLoop(const value& k, FileDB& db) : k(k), db(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(string("CCC"))); + assert((get(k, db)) == value(c)); return true; } }; -bool testGetPerf() { +bool testGetPerf(const string& dbname, const string& format) { + FileDB db(dbname, format); + const value k = mklist<value>("c"); - FileDB db("tmp/testdb"); - assert(hasContent(post(k, string("CCC"), db))); + const list<value> c = mklist<value>(list<value>() + "ns1:c" + (list<value>() + "@xmlns:ns1" + string("http://ccc")) + (list<value>() + "text" + string("Hey!"))); + assert(hasContent(post(k, c, db))); const lambda<bool()> gl = getLoop(k, db); - cout << "FileDB get test " << time(gl, 5, 10000) << " ms" << endl; + cout << "FileDB get test " << time(gl, 5, 5000) << " ms" << endl; return true; } @@ -73,8 +81,12 @@ bool testGetPerf() { int main() { tuscany::cout << "Testing..." << tuscany::endl; - tuscany::filedb::testFileDB(); - tuscany::filedb::testGetPerf(); + tuscany::filedb::testFileDB("tmp/schemedb", "scheme"); + tuscany::filedb::testGetPerf("tmp/schemedb", "scheme"); + tuscany::filedb::testFileDB("tmp/xmldb", "xml"); + tuscany::filedb::testGetPerf("tmp/xmldb", "xml"); + tuscany::filedb::testFileDB("tmp/jsondb", "json"); + tuscany::filedb::testGetPerf("tmp/jsondb", "json"); tuscany::cout << "OK" << tuscany::endl; diff --git a/sca-cpp/trunk/components/filedb/filedb-test b/sca-cpp/trunk/components/filedb/filedb-test index 5a01d16676..083bd1b96c 100755 --- a/sca-cpp/trunk/components/filedb/filedb-test +++ b/sca-cpp/trunk/components/filedb/filedb-test @@ -19,7 +19,9 @@ # Setup mkdir -p tmp -mkdir -p tmp/testdb +mkdir -p tmp/schemedb +mkdir -p tmp/xmldb +mkdir -p tmp/jsondb # Test ./file-test 2>/dev/null diff --git a/sca-cpp/trunk/components/filedb/filedb.composite b/sca-cpp/trunk/components/filedb/filedb.composite index 286afc1d7d..05a2d50847 100644 --- a/sca-cpp/trunk/components/filedb/filedb.composite +++ b/sca-cpp/trunk/components/filedb/filedb.composite @@ -25,6 +25,7 @@ <component name="filedb"> <implementation.cpp path="." library="libfiledb"/> <property name="dbname">tmp/testdb</property> + <property name="format">scheme</property> <service name="filedb"> <t:binding.http uri="filedb"/> </service> diff --git a/sca-cpp/trunk/components/filedb/filedb.cpp b/sca-cpp/trunk/components/filedb/filedb.cpp index bb2f0590b0..473dfea281 100644 --- a/sca-cpp/trunk/components/filedb/filedb.cpp +++ b/sca-cpp/trunk/components/filedb/filedb.cpp @@ -99,10 +99,11 @@ private: /** * Start the component. */ -const failable<value> start(unused const list<value>& params) { +const failable<value> start(const list<value>& params) { // Connect to the configured database and table const value dbname = ((lambda<value(list<value>)>)car(params))(list<value>()); - filedb::FileDB& db = *(new (gc_new<filedb::FileDB>()) filedb::FileDB(dbname)); + const value format = ((lambda<value(list<value>)>)cadr(params))(list<value>()); + filedb::FileDB& db = *(new (gc_new<filedb::FileDB>()) filedb::FileDB(dbname, format)); // Return the component implementation lambda function return value(lambda<value(const list<value>&)>(applyfiledb(db))); diff --git a/sca-cpp/trunk/components/filedb/filedb.hpp b/sca-cpp/trunk/components/filedb/filedb.hpp index 0b11da67ba..89ff3b8157 100644 --- a/sca-cpp/trunk/components/filedb/filedb.hpp +++ b/sca-cpp/trunk/components/filedb/filedb.hpp @@ -31,7 +31,10 @@ #include "value.hpp" #include "monad.hpp" #include "fstream.hpp" +#include "element.hpp" +#include "xml.hpp" #include "../../modules/scheme/eval.hpp" +#include "../../modules/json/json.hpp" namespace tuscany { namespace filedb { @@ -41,13 +44,13 @@ namespace filedb { */ class FileDB { public: - FileDB() : owner(false) { + FileDB() : owner(false), jscx(*jscontext("")) { } - FileDB(const string& name) : owner(true), name(name) { + FileDB(const string& name, const string& format) : owner(true), name(name), format(format), jscx(*jscontext(format)) { } - FileDB(const FileDB& c) : owner(false), name(c.name) { + FileDB(const FileDB& c) : owner(false), name(c.name), format(c.format), jscx(c.jscx) { } ~FileDB() { @@ -56,22 +59,95 @@ public: private: bool owner; string name; + string format; + js::JSContext& jscx; - friend const string dbname(const FileDB& db); + js::JSContext* jscontext(const string& format) { + if (format != "json") + return NULL; + return new (gc_new<js::JSContext>()) js::JSContext(); + } + + friend const failable<bool> write(const value& v, ostream& os, const string& format, FileDB& db); + friend const failable<value> read(istream& is, const string& format, FileDB& db); + 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); }; /** - * Return the name of the database. + * Convert a key to a file name. */ -const string dbname(const FileDB& db) { - return db.name; +const string filename(const list<value>& path, const string& root) { + if (isNil(path)) + return root; + string name = root + "/" + scheme::writeValue(car(path)); + return filename(cdr(path), name); +} + +const string filename(const value& key, const string& root) { + if (!isList(key)) + return filename(mklist(key), root); + return filename((list<value>)key, root); } /** - * Convert a key to a file name. + * Make the parent directories of a keyed file. */ -const string filename(const value& key, const FileDB& db) { - return dbname(db) + "/" + scheme::writeValue(key); +const failable<bool> mkdirs(const list<value>& path, const string& root) { + if (isNil(cdr(path))) + return true; + string dir = root + "/" + scheme::writeValue(car(path)); + mkdir(c_str(dir), S_IRWXU); + return mkdirs(cdr(path), dir); +} + +/** + * Write a value to a database file. + */ +const failable<bool> write(const value& v, ostream& os, const string& format, FileDB& db) { + if (format == "scheme") { + const string vs(scheme::writeValue(v)); + os << vs; + return true; + } + if (format == "xml") { + failable<list<string> > s = writeXML(valuesToElements(v)); + if (!hasContent(s)) + return mkfailure<bool>(reason(s)); + write(content(s), os); + return true; + } + if (format == "json") { + failable<list<string> > s = json::writeJSON(valuesToElements(v), db.jscx); + if (!hasContent(s)) + return mkfailure<bool>(reason(s)); + write(content(s), os); + return true; + } + return mkfailure<bool>(string("Unsupported database format: ") + format); +} + +/** + * Read a value from a database file. + */ +const failable<value> read(istream& is, const string& format, FileDB& db) { + if (format == "scheme") { + return scheme::readValue(is); + } + if (format == "xml") { + const value v = elementsToValues(readXML(streamList(is))); + return v; + } + if (format == "json") { + const failable<list<value> > fv = json::readJSON(streamList(is), db.jscx); + if (!hasContent(fv)) + return mkfailure<value>(reason(fv)); + const value v = elementsToValues(content(fv)); + return v; + } + return mkfailure<value>(string("Unsupported database format: ") + format); } /** @@ -80,14 +156,17 @@ const string filename(const value& key, const FileDB& db) { const failable<bool> post(const value& key, const value& val, FileDB& db) { debug(key, "filedb::post::key"); debug(val, "filedb::post::value"); - debug(dbname(db), "filedb::post::dbname"); + debug(db.name, "filedb::post::dbname"); - ofstream os(filename(key, db)); - const string vs(scheme::writeValue(val)); - os << vs; + if (isList(key)) + mkdirs(key, db.name); + ofstream os(filename(key, db.name)); + if (os.fail()) + return mkfailure<bool>("Couldn't post file database entry."); + const failable<bool> r = write(val, os, db.format, db); - debug(true, "filedb::post::result"); - return true; + debug(r, "filedb::post::result"); + return r; } /** @@ -96,14 +175,17 @@ const failable<bool> post(const value& key, const value& val, FileDB& db) { const failable<bool> put(const value& key, const value& val, FileDB& db) { debug(key, "filedb::put::key"); debug(val, "filedb::put::value"); - debug(dbname(db), "filedb::put::dbname"); + debug(db.name, "filedb::put::dbname"); - ofstream os(filename(key, db)); - const string vs(scheme::writeValue(val)); - os << vs; + if (isList(key)) + mkdirs(key, db.name); + ofstream os(filename(key, db.name)); + if (os.fail()) + return mkfailure<bool>("Couldn't put file database entry."); + const failable<bool> r = write(val, os, db.format, db); - debug(true, "filedb::put::result"); - return true; + debug(r, "filedb::put::result"); + return r; } /** @@ -111,12 +193,12 @@ const failable<bool> put(const value& key, const value& val, FileDB& db) { */ const failable<value> get(const value& key, FileDB& db) { debug(key, "filedb::get::key"); - debug(dbname(db), "filedb::get::dbname"); + debug(db.name, "filedb::get::dbname"); - ifstream is(filename(key, db)); + ifstream is(filename(key, db.name)); if (is.fail()) return mkfailure<value>("Couldn't get file database entry."); - const value val(scheme::readValue(is)); + const failable<value> val = read(is, db.format, db); debug(val, "filedb::get::result"); return val; @@ -127,11 +209,12 @@ const failable<value> get(const value& key, FileDB& db) { */ const failable<bool> del(const value& key, FileDB& db) { debug(key, "filedb::delete::key"); - debug(dbname(db), "filedb::delete::dbname"); + debug(db.name, "filedb::delete::dbname"); - const int rc = unlink(c_str(filename(key, db))); + const int rc = unlink(c_str(filename(key, db.name))); if (rc == -1) return mkfailure<bool>("Couldn't delete file database entry."); + debug(true, "filedb::delete::result"); return true; } diff --git a/sca-cpp/trunk/kernel/fstream.hpp b/sca-cpp/trunk/kernel/fstream.hpp index 8efb798b57..99fc51565f 100644 --- a/sca-cpp/trunk/kernel/fstream.hpp +++ b/sca-cpp/trunk/kernel/fstream.hpp @@ -56,6 +56,10 @@ public: fclose(file); } + const bool fail() { + return file == NULL; + } + ofstream& vprintf(const char* fmt, ...) { va_list args; va_start (args, fmt); |