summaryrefslogtreecommitdiff
path: root/datastore-leveldb/src/web.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'datastore-leveldb/src/web.cpp')
-rw-r--r--datastore-leveldb/src/web.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/datastore-leveldb/src/web.cpp b/datastore-leveldb/src/web.cpp
new file mode 100644
index 0000000..4898451
--- /dev/null
+++ b/datastore-leveldb/src/web.cpp
@@ -0,0 +1,95 @@
+#include "web.h"
+#include "db.h"
+#include <leveldb/comparator.h>
+#include <iomanip>
+
+static inline std::string make_key(uint64_t timestamp) {
+ std::stringstream key;
+ key << "ts-";
+ key << std::setfill('0') << std::setw(20) << timestamp;
+ return key.str();
+}
+
+void web_handle_api_value(const boost::cmatch &match, struct mg_connection *conn) {
+// const struct mg_request_info *request_info = mg_get_request_info(conn);
+
+ std::string sensor(match[1].str());
+ uint64_t timestamp = std::stoul(match[2].str());
+ char buf[1024];
+ int count = mg_read(conn, buf, 1024);
+ std::string value(buf, count);
+
+ leveldb::DB *db = getDB(sensor);
+ if (db == nullptr) {
+ std::cout << "failed to get db for " << sensor << std::endl;
+ mg_printf(conn, "HTTP/1.1 500 Internal Error\r\n\r\n");
+ return;
+ }
+
+ std::cout << "sensor=" << sensor << " key=" << make_key(timestamp) << std::endl;
+ db->Put(leveldb::WriteOptions(), make_key(timestamp), value);
+ mg_printf(conn, "HTTP/1.1 200 Value received\r\n\r\n");
+}
+
+void web_handle_api_range(const boost::cmatch &match, struct mg_connection *conn) {
+ static const leveldb::Comparator *cmp = leveldb::BytewiseComparator();
+
+ std::string sensor(match[1].str());
+ uint64_t start = std::stoul(match[2].str());
+ uint64_t end = std::stoul(match[3].str());
+ std::string key_start(std::move(make_key(start)));
+ std::string key_end(std::move(make_key(end)));
+
+ leveldb::DB *db = getDB(sensor);
+ if (db == nullptr) {
+ mg_printf(conn, "HTTP/1.1 500 Internal Error\r\n\r\n");
+ return;
+ }
+
+ mg_printf(conn,
+ "HTTP/1.1 200 Value received\r\n"
+ "Content-Type: application/json; encoding=UTF-8\r\n"
+ "\r\n");
+
+ std::cout << "sensor=" << sensor << " start=" << start << " end=" << end << std::endl;
+
+ std::ostringstream out;
+ out << "{'sensor':'" << sensor << "', 'error':null, 'data':[";
+ mg_write(conn, out.str().c_str(), out.str().size());
+
+ leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
+ bool first = true;
+ std::ostringstream outbuf;
+ for (it->Seek(key_start);
+ it->Valid() && cmp->Compare(it->key(), key_end) < 0;
+ it->Next()) {
+ const char *key = it->key().data();
+ size_t key_size = it->key().size();
+ if (key_size != 20+3) {
+ std::cerr << "invalid key" << std::endl;
+ return;
+ }
+
+ unsigned int offset = 3; // "ts-"
+ // skip zeros in timestamp
+ while (offset < key_size-1 and *(key+offset) == '0')
+ offset++;
+
+ if (first)
+ first = false;
+ else
+ outbuf << ',';
+
+ outbuf << '[';
+ outbuf.write(key+offset, key_size-offset);
+ outbuf << ',';
+ outbuf.write(it->value().data(), it->value().size());
+ outbuf << ']';
+
+ mg_write(conn, outbuf.str().c_str(), outbuf.tellp());
+ outbuf.seekp(0);
+ }
+ mg_printf(conn, "]}\r\n");
+ delete it;
+}
+