summaryrefslogtreecommitdiff
path: root/datastore-leveldb/src/main.cpp
diff options
context:
space:
mode:
authorYves Fischer <yvesf-git@xapek.org>2013-04-17 00:13:33 +0200
committerYves Fischer <yvesf-git@xapek.org>2013-04-17 00:13:33 +0200
commitc83bca9a9de29c155d519ccea2e8a8d07acc5bac (patch)
tree156131ebae5aae008fde4e241e95ae3b70c8dfcc /datastore-leveldb/src/main.cpp
parent6f20cda5c3071e03d2a56dc8236a530582cad2b7 (diff)
downloadebus-alt-c83bca9a9de29c155d519ccea2e8a8d07acc5bac.tar.gz
ebus-alt-c83bca9a9de29c155d519ccea2e8a8d07acc5bac.zip
leveldb
Diffstat (limited to 'datastore-leveldb/src/main.cpp')
-rw-r--r--datastore-leveldb/src/main.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/datastore-leveldb/src/main.cpp b/datastore-leveldb/src/main.cpp
new file mode 100644
index 0000000..4fd95df
--- /dev/null
+++ b/datastore-leveldb/src/main.cpp
@@ -0,0 +1,123 @@
+extern "C" {
+#include "server_eh.h"
+#include <unistd.h>
+#include <signal.h>
+#include <ev.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+}
+
+#include <iostream>
+
+#include "leveldb/db.h"
+#include "leveldb/comparator.h"
+
+// see http_parser.h
+// char DELETE = 0;
+// char GET = 1;
+// char HEAD = 2;
+// char POST = 3;
+// char PUT = 4;
+
+static inline void send_file(const char *path, int fd_out) {
+ int fd_in;
+ struct stat stat_buf;
+
+ fd_in = open(path, O_RDONLY);
+ fstat(fd_in, &stat_buf);
+ sendfile(fd_out, fd_in, 0, stat_buf.st_size);
+ close(fd_in);
+}
+
+static inline void http_ok(int fd, const char *content_type) {
+#define write_const(fd, text) \
+ write(fd, text, strlen(text));
+
+ write_const(fd, "HTTP/1.1 200 OK\r\nContent-Type: ");
+ write_const(fd, content_type);
+ write_const(fd, "\r\n\r\n");
+#undef write_const
+}
+
+static inline void http_fail(int fd) {
+ write(fd, "HTTP/1.1 501 FAIL\r\n\r\n",25);
+}
+
+void handle_request(struct http_request *request, int fd) {
+#define write_const(fd, text) \
+ write(fd, text, strlen(text));
+
+ if (request->url == NULL) { // happens only under high load
+ std::cerr << "url is null" << std::endl;
+ http_fail(fd);
+ close(fd);
+ return;
+ }
+
+ std::string url(request->url);
+
+ if (url == "/") {
+ http_ok(fd, "text/html; charset=UTF-8");
+ send_file("index.html", fd);
+ } else if (url.find("/api/put") == 0) {
+ http_ok(fd, "text/html; charset=UTF-8");
+ std::cout << "put" << std::endl;
+ } else if (url.find("/debug") == 0) {
+ http_ok(fd, "text/html; charset=UTF-8");
+ struct http_header *header = request->headers;
+ write_const(fd, "<pre>Headers:\n");
+ while (header != NULL) {
+ write_const(fd, header->name);
+ write_const(fd, ": ");
+ write_const(fd, header->value);
+ write_const(fd, "\n");
+ header = header->next;
+ }
+ if (request->flags & F_HREQ_KEEPALIVE) {
+ write_const(fd, "\nis keepalive.\n");
+ }
+ write_const(fd, "\r\n\r\n");
+ } else {
+ http_fail(fd);
+ }
+ close(fd);
+#undef write_const
+}
+
+static struct http_server server;
+
+void sigint_handler(int s) {
+ struct ev_loop *loop = server.loop;
+ ev_io_stop(EV_A_ server.ev_accept);
+ exit(0);
+}
+
+int main(int argc, char **argv) {
+ // configure server structures and desired listen address
+ struct sockaddr_in listen_addr;
+ memset(&listen_addr, 0, sizeof(listen_addr));
+ listen_addr.sin_family = AF_INET;
+ listen_addr.sin_addr.s_addr = INADDR_ANY;
+ listen_addr.sin_port = htons(5000);
+ server.listen_addr = &listen_addr;
+ server.handle_request = handle_request;
+
+ // ignore SIGPIPE
+ struct sigaction on_sigpipe;
+ on_sigpipe.sa_handler = SIG_IGN;
+ sigemptyset(&on_sigpipe.sa_mask);
+ sigaction(SIGPIPE, &on_sigpipe, NULL);
+
+ // handle C-c
+ struct sigaction on_sigint;
+ on_sigint.sa_handler = sigint_handler;
+ sigemptyset(&on_sigint.sa_mask);
+ on_sigint.sa_flags = 0;
+ sigaction(SIGINT, &on_sigint, NULL);
+
+ // start the server
+ return http_server_loop(&server);
+}