summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/components/filedb
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/components/filedb')
-rw-r--r--sca-cpp/trunk/components/filedb/Makefile.am4
-rw-r--r--sca-cpp/trunk/components/filedb/file-test.cpp44
-rwxr-xr-xsca-cpp/trunk/components/filedb/filedb-test4
-rw-r--r--sca-cpp/trunk/components/filedb/filedb.composite1
-rw-r--r--sca-cpp/trunk/components/filedb/filedb.cpp5
-rw-r--r--sca-cpp/trunk/components/filedb/filedb.hpp137
6 files changed, 147 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;
}