From a4f8fcde0e7d4a592eb07628a08b5534abdb2613 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Fri, 24 Dec 2010 02:54:28 +0000 Subject: 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 --- sca-cpp/trunk/components/filedb/Makefile.am | 4 +- sca-cpp/trunk/components/filedb/file-test.cpp | 44 +++++--- sca-cpp/trunk/components/filedb/filedb-test | 4 +- sca-cpp/trunk/components/filedb/filedb.composite | 1 + sca-cpp/trunk/components/filedb/filedb.cpp | 5 +- sca-cpp/trunk/components/filedb/filedb.hpp | 137 ++++++++++++++++++----- sca-cpp/trunk/kernel/fstream.hpp | 4 + 7 files changed, 151 insertions(+), 48 deletions(-) (limited to 'sca-cpp') 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("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("a", "b"); + + const list a = mklist(list() + "ns1:a" + (list() + "@xmlns:ns1" + string("http://aaa")) + (list() + "text" + string("Hey!"))); + const list b = mklist(list() + "ns1:b" + (list() + "@xmlns:ns1" + string("http://bbb")) + (list() + "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 c; + getLoop(const value& k, FileDB& db) : k(k), db(db), + c(mklist(list() + "ns1:c" + (list() + "@xmlns:ns1" + string("http://ccc")) + (list() + "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("c"); - FileDB db("tmp/testdb"); - assert(hasContent(post(k, string("CCC"), db))); + const list c = mklist(list() + "ns1:c" + (list() + "@xmlns:ns1" + string("http://ccc")) + (list() + "text" + string("Hey!"))); + assert(hasContent(post(k, c, db))); const lambda 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 @@ tmp/testdb + scheme 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 start(unused const list& params) { +const failable start(const list& params) { // Connect to the configured database and table const value dbname = ((lambda)>)car(params))(list()); - filedb::FileDB& db = *(new (gc_new()) filedb::FileDB(dbname)); + const value format = ((lambda)>)cadr(params))(list()); + filedb::FileDB& db = *(new (gc_new()) filedb::FileDB(dbname, format)); // Return the component implementation lambda function return value(lambda&)>(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(); + } + + friend const failable write(const value& v, ostream& os, const string& format, FileDB& db); + friend const failable read(istream& is, const string& format, FileDB& db); + friend const failable post(const value& key, const value& val, FileDB& db); + friend const failable put(const value& key, const value& val, FileDB& db); + friend const failable get(const value& key, FileDB& db); + friend const failable 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& 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)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 mkdirs(const list& 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 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 > s = writeXML(valuesToElements(v)); + if (!hasContent(s)) + return mkfailure(reason(s)); + write(content(s), os); + return true; + } + if (format == "json") { + failable > s = json::writeJSON(valuesToElements(v), db.jscx); + if (!hasContent(s)) + return mkfailure(reason(s)); + write(content(s), os); + return true; + } + return mkfailure(string("Unsupported database format: ") + format); +} + +/** + * Read a value from a database file. + */ +const failable 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 > fv = json::readJSON(streamList(is), db.jscx); + if (!hasContent(fv)) + return mkfailure(reason(fv)); + const value v = elementsToValues(content(fv)); + return v; + } + return mkfailure(string("Unsupported database format: ") + format); } /** @@ -80,14 +156,17 @@ const string filename(const value& key, const FileDB& db) { const failable 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("Couldn't post file database entry."); + const failable 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 post(const value& key, const value& val, FileDB& db) { const failable 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("Couldn't put file database entry."); + const failable 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 put(const value& key, const value& val, FileDB& db) { */ const failable 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("Couldn't get file database entry."); - const value val(scheme::readValue(is)); + const failable val = read(is, db.format, db); debug(val, "filedb::get::result"); return val; @@ -127,11 +209,12 @@ const failable get(const value& key, FileDB& db) { */ const failable 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("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); -- cgit v1.2.3