#include "web.h" #include "db.h" #include #include 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; }