summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorsr2012-08-27 21:02:49 +0200
committersr2012-08-27 21:02:49 +0200
commitde01183aa40dbbd274e18f681d8a255a886f493e (patch)
treef614e764704aec26df15df68c633178064c60a41 /src/server
parent[KERNEL] Make rtt threshold relative (diff)
downloaddnbd3-de01183aa40dbbd274e18f681d8a255a886f493e.tar.gz
dnbd3-de01183aa40dbbd274e18f681d8a255a886f493e.tar.xz
dnbd3-de01183aa40dbbd274e18f681d8a255a886f493e.zip
[KERNEL] Refactor and extend sysfs (add data the server will need in proxy mode)
[SERVER] Use MSG_MORE instead of cork/uncork to save two syscalls [KERNEL] Fail-Counter for alt servers, ignore servers that fail too often [KERNEL] Add new alt servers to list, instead of replacing the old list [*] Add CMD_LATEST_RID to tell client about new revisions
Diffstat (limited to 'src/server')
-rw-r--r--src/server/ipc.c8
-rw-r--r--src/server/net.c38
-rw-r--r--src/server/server.c19
-rw-r--r--src/server/server.h5
-rw-r--r--src/server/utils.c4
5 files changed, 48 insertions, 26 deletions
diff --git a/src/server/ipc.c b/src/server/ipc.c
index 5da811c..ece6f07 100644
--- a/src/server/ipc.c
+++ b/src/server/ipc.c
@@ -403,9 +403,10 @@ void dnbd3_ipc_send(int cmd)
if (cmd == IPC_INFO && header.size > 0)
{
- char* buf = malloc(header.size);
+ char* buf = malloc(header.size+1);
size = recv(client_sock, buf, header.size, MSG_WAITALL);
xmlDocPtr doc = xmlReadMemory(buf, size, "noname.xml", NULL, 0);
+ buf[header.size] = 0;
if (doc)
{
@@ -479,9 +480,10 @@ void dnbd3_ipc_send(int cmd)
// xmlDocDump(stdout, doc);
- } else
+ }
+ else
{
- printf("ERROR: Failed to parse reply\n");
+ printf("ERROR: Failed to parse reply\n-----------\n%s\n-------------\n", buf);
}
}
diff --git a/src/server/net.c b/src/server/net.c
index c145beb..49cfb24 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -39,7 +39,7 @@
#include "../config.h"
-static char recv_request_header(int sock, dnbd3_request_t *request)
+static inline char recv_request_header(int sock, dnbd3_request_t *request)
{
int ret;
// Read request header from socket
@@ -62,10 +62,13 @@ static char recv_request_header(int sock, dnbd3_request_t *request)
memlogf("[WARNING] Client tries to send a packet of type %d with %d bytes payload. Dropping client.", (int)request->cmd, (int)request->size);
return 0;
}
+#ifdef _DEBUG
+ if (_fake_delay) usleep(_fake_delay);
+#endif
return 1;
}
-static char recv_request_payload(int sock, uint32_t size, serialized_buffer_t *payload)
+static inline char recv_request_payload(int sock, uint32_t size, serialized_buffer_t *payload)
{
if (size == 0)
{
@@ -87,10 +90,11 @@ static char recv_request_payload(int sock, uint32_t size, serialized_buffer_t *p
return 1;
}
-static char send_reply(int sock, dnbd3_reply_t *reply, void *payload)
+static inline char send_reply(int sock, dnbd3_reply_t *reply, void *payload)
{
+ const unsigned int size = reply->size;
fixup_reply(*reply);
- if (!payload || reply->size == 0)
+ if (!payload || size == 0)
{
if (send(sock, reply, sizeof(dnbd3_reply_t), MSG_WAITALL) != sizeof(dnbd3_reply_t))
{
@@ -104,10 +108,10 @@ static char send_reply(int sock, dnbd3_reply_t *reply, void *payload)
iov[0].iov_base = reply;
iov[0].iov_len = sizeof(dnbd3_reply_t);
iov[1].iov_base = payload;
- iov[1].iov_len = reply->size;
- if (writev(sock, iov, 2) != sizeof(dnbd3_reply_t) + reply->size)
+ iov[1].iov_len = size;
+ if (writev(sock, iov, 2) != sizeof(dnbd3_reply_t) + size)
{
- printf("[DEBUG] Send failed (reply with payload of %d bytes)\n", (int)reply->size);
+ printf("[DEBUG] Send failed (reply with payload of %u bytes)\n", size);
return 0;
}
}
@@ -120,9 +124,6 @@ void *dnbd3_handle_query(void *dnbd3_client)
dnbd3_request_t request;
dnbd3_reply_t reply;
- const int cork = 1;
- const int uncork = 0;
-
dnbd3_image_t *image = NULL;
int image_file = -1, image_cache = -1;
@@ -216,7 +217,6 @@ void *dnbd3_handle_query(void *dnbd3_client)
if (image) while (recv_request_header(client->sock, &request))
{
-
switch (request.cmd)
{
@@ -246,12 +246,16 @@ void *dnbd3_handle_query(void *dnbd3_client)
break;
}
- // TODO: Try MSG_MORE instead of cork+uncork if performance ever becomes an issue..
- setsockopt(client->sock, SOL_TCP, TCP_CORK, &cork, sizeof(cork));
reply.cmd = CMD_GET_BLOCK;
reply.size = request.size;
reply.handle = request.handle;
- send_reply(client->sock, &reply, NULL);
+
+ fixup_reply(reply);
+ if (send(client->sock, &reply, sizeof(dnbd3_reply_t), MSG_MORE) != sizeof(dnbd3_reply_t))
+ {
+ printf("[DEBUG] Sending CMD_GET_BLOCK header failed\n");
+ return 0;
+ }
if (request.size == 0) // Request for 0 bytes, done after sending header
break;
@@ -264,8 +268,6 @@ void *dnbd3_handle_query(void *dnbd3_client)
printf("[ERROR] sendfile failed (image to net)\n");
close(client->sock);
}
-
- setsockopt(client->sock, SOL_TCP, TCP_CORK, &uncork, sizeof(uncork));
break;
}
@@ -343,8 +345,6 @@ void *dnbd3_handle_query(void *dnbd3_client)
memlogf("[ERROR] sendfile failed (cache to net)\n");
close(client->sock);
}
-
- setsockopt(client->sock, SOL_TCP, TCP_CORK, &uncork, sizeof(uncork));
break;
@@ -353,7 +353,7 @@ void *dnbd3_handle_query(void *dnbd3_client)
num = 0;
for (i = 0; i < NUMBER_SERVERS; i++)
{
- if (image->servers[i].addrtype == 0 || image->servers[i].failures > 200) continue;
+ if (image->servers[i].hostaddrtype == 0 || image->servers[i].failures > 200) continue;
memcpy(server_list + num++, image->servers + i, sizeof(dnbd3_server_entry_t));
}
reply.cmd = CMD_GET_SERVERS;
diff --git a/src/server/server.c b/src/server/server.c
index b2a36a5..965c368 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -37,6 +37,9 @@
#include "memlog.h"
int _sock;
+#ifdef _DEBUG
+int _fake_delay = 0;
+#endif
pthread_spinlock_t _spinlock;
GSList *_dnbd3_clients = NULL;
@@ -48,6 +51,9 @@ void dnbd3_print_help(char* argv_0)
printf("Usage: %s [OPTIONS]...\n", argv_0);
printf("Start the DNBD3 server\n");
printf("-f or --file \t\t Configuration file (default /etc/dnbd3-server.conf)\n");
+#ifdef _DEBUG
+ printf("-d or --delay \t\t Add a fake network delay of X µs\n");
+#endif
printf("-n or --nodaemon \t Start server in foreground\n");
printf("-r or --reload \t\t Reload configuration file\n");
printf("-s or --stop \t\t Stop running dnbd3-server\n");
@@ -119,10 +125,11 @@ int main(int argc, char* argv[])
int demonize = 1;
int opt = 0;
int longIndex = 0;
- static const char *optString = "f:nrsiHV?";
+ static const char *optString = "f:d:nrsiHV?";
static const struct option longOpts[] =
{
{ "file", required_argument, NULL, 'f' },
+ { "delay", required_argument, NULL, 'd' },
{ "nodaemon", no_argument, NULL, 'n' },
{ "reload", no_argument, NULL, 'r' },
{ "stop", no_argument, NULL, 's' },
@@ -137,8 +144,16 @@ int main(int argc, char* argv[])
switch (opt)
{
case 'f':
- _config_file_name = optarg;
+ _config_file_name = strdup(optarg);
break;
+ case 'd':
+#ifdef _DEBUG
+ _fake_delay = atoi(optarg);
+ break;
+#else
+ printf("This option is only available in debug builds.\n\n");
+ return EXIT_FAILURE;
+#endif
case 'n':
demonize = 0;
break;
diff --git a/src/server/server.h b/src/server/server.h
index 69d597b..7e19f27 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -56,6 +56,11 @@ extern pthread_spinlock_t _spinlock;
extern char *_config_file_name;
extern GSList *_dnbd3_images; // of dnbd3_image_t
+
+#ifdef _DEBUG
+extern int _fake_delay;
+#endif
+
void dnbd3_cleanup();
#endif /* SERVER_H_ */
diff --git a/src/server/utils.c b/src/server/utils.c
index 15e51f8..3fe1900 100644
--- a/src/server/utils.c
+++ b/src/server/utils.c
@@ -260,11 +260,11 @@ void dnbd3_load_config(char *file)
gchar **servers = g_key_file_get_string_list(gkf, groups[i], "servers", &num_servers, NULL);
if (servers) for (k = 0, j = 0; j < MIN(num_servers, NUMBER_SERVERS); ++j)
{
- if (parse_address(servers[j], &(image->servers[k].addrtype), image->servers[k].ipaddr, &(image->servers[k].port)))
+ if (parse_address(servers[j], &(image->servers[k].hostaddrtype), image->servers[k].hostaddr, &(image->servers[k].port)))
{
++k; continue;
}
- image->servers[k].addrtype = 0;
+ image->servers[k].hostaddrtype = 0;
}
g_strfreev(servers);