summaryrefslogtreecommitdiffstats
path: root/server/query.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/query.c')
-rw-r--r--server/query.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/server/query.c b/server/query.c
new file mode 100644
index 0000000..16f48b6
--- /dev/null
+++ b/server/query.c
@@ -0,0 +1,74 @@
+/*
+ * server/query.c
+ */
+
+
+#include <arpa/inet.h>
+#include <inttypes.h>
+#include <byteswap.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "dnbd2.h"
+#include "query.h"
+#include "tree.h"
+#include "file.h"
+
+
+int handle_query(dnbd2_data_request_t *request,
+ dnbd2_data_reply_t *reply,
+ void **tree)
+{
+ int fd, i;
+ node_t node1;
+ node_t *node2;
+ dataset_t ds;
+ off_t size, pos;
+ uint16_t cmd;
+
+ /* Fetch the right fd for this vid/rid pair. */
+ ds.vid = ntohs(request->vid);
+ ds.rid = ntohs(request->rid);
+ node1.ds = &ds;
+ node2 = tree_find(&node1, tree);
+ if (!node2)
+ return -1;
+ fd = node2->fd;
+
+ cmd = ntohs(request->cmd);
+ switch (cmd) {
+ case CMD_GET_BLOCK:
+ reply->num = request->num;
+ pos = ntohll(request->num);
+ file_read(fd, reply->payload.data, DNBD2_BLOCK_SIZE, pos);
+ break;
+
+ case CMD_GET_SIZE:
+ if (file_getsize(fd, &size) == -1)
+ return -1;
+ reply->num = htonll(size);
+ break;
+
+ case CMD_GET_SERVERS:
+ /* Fetch a random block to deliver a more realistic RTT. */
+ pos = 0;
+ if (!file_getsize(fd, &size))
+ pos = (off_t) (size * (rand() / (RAND_MAX + 1.0)));
+ file_read(fd, reply->payload.data, DNBD2_BLOCK_SIZE, pos);
+ reply->num = htonll(node2->servers);
+ for (i=0 ; i<node2->servers ; i++) {
+ memcpy(&reply->payload.server[i],
+ &node2->server[i],
+ sizeof(dnbd2_server_t));
+ }
+ break;
+ }
+
+ reply->cmd = request->cmd;
+ reply->time = request->time;
+ reply->vid = request->vid;
+ reply->rid = request->rid;
+
+ return 0;
+}