diff options
Diffstat (limited to 'datastore-leveldb/src/web.cpp')
-rw-r--r-- | datastore-leveldb/src/web.cpp | 95 |
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; +} + |