summaryrefslogtreecommitdiffstats
path: root/src/server/server.c
diff options
context:
space:
mode:
authorsr2013-07-09 19:14:34 +0200
committersr2013-07-09 19:14:34 +0200
commit09a25c819fc6784f2ac61a37fbe36b408d838cec (patch)
tree9a20f292c6ad5e8cebd2d62172bb470c6bcd0984 /src/server/server.c
parentRewriting.... (diff)
downloaddnbd3-09a25c819fc6784f2ac61a37fbe36b408d838cec.tar.gz
dnbd3-09a25c819fc6784f2ac61a37fbe36b408d838cec.tar.xz
dnbd3-09a25c819fc6784f2ac61a37fbe36b408d838cec.zip
Rewrite in progres....
Diffstat (limited to 'src/server/server.c')
-rw-r--r--src/server/server.c171
1 files changed, 104 insertions, 67 deletions
diff --git a/src/server/server.c b/src/server/server.c
index b2e5ba7..87b7c08 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -58,6 +58,8 @@ char *_config_file_name = DEFAULT_SERVER_CONFIG_FILE;
char *_rpc_password = NULL;
char *_cache_dir = NULL;
+static void dnbd3_handle_sigpipe(int signum);
+static void dnbd3_handle_sigterm(int signum);
void dnbd3_print_help(char *argv_0)
{
@@ -85,7 +87,6 @@ void dnbd3_print_version()
void dnbd3_cleanup()
{
int fd, i;
- GSList *iterator = NULL;
memlogf("INFO: Cleanup...\n");
@@ -98,12 +99,13 @@ void dnbd3_cleanup()
}
socket_count = 0;
+ // Clean up clients
pthread_spin_lock(&_clients_lock);
for (i = 0; i < _num_clients; ++i)
{
dnbd3_client_t * const client = _clients[i];
pthread_spin_lock(&client->lock);
- if (client->sock != -1) shutdown(client->sock, SHUT_RDWR);
+ if (client->sock >= 0) shutdown(client->sock, SHUT_RDWR);
if (client->thread != 0) pthread_join(client->thread, NULL);
_clients[i] = NULL;
pthread_spin_unlock(&client->lock);
@@ -112,41 +114,25 @@ void dnbd3_cleanup()
_num_clients = 0;
pthread_spin_unlock(&_clients_lock);
+ // Clean up images
pthread_spin_lock(&_images_lock);
for (i = 0; i < _num_images; ++i)
{
- // save cache maps to files
dnbd3_image_t *image = _images[i];
- if (image->cache_file)
- {
- char tmp[strlen(image->cache_file)+4];
- strcpy(tmp, image->cache_file);
- strcat(tmp, ".map");
- fd = open(tmp, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
-
- if (fd > 0)
- write(fd, image->cache_map, ((image->filesize + (1 << 15) - 1) >> 15) * sizeof(char));
-
- close(fd);
- }
- // Close bock devices of proxied images
- if (image->file && strncmp(image->file, "/dev/dnbd", 9) == 0)
- {
- int fd = open(image->file, O_RDONLY);
- dnbd3_ioctl_t msg;
- memset(&msg, 0, sizeof(msg));
- msg.len = sizeof(msg);
- ioctl(fd, IOCTL_CLOSE, &msg);
- close(fd);
- }
-
+ pthread_spin_lock(&image->lock);
+ // save cache maps to files
+ image_save_cache_map(image);
+ // free uplink connection
+ uplink_free(image->uplink);
+ // free other stuff
free(image->cache_map);
- free(image->config_group);
- free(image->low_name);
- free(image->file);
- free(image->cache_file);
- g_free(image);
+ free(image->path);
+ free(image->lower_name);
+ _images[i] = NULL;
+ pthread_spin_unlock(&image->lock);
+ free(image);
}
+ _num_images = 0;
pthread_spin_unlock(&_images_lock);
exit(EXIT_SUCCESS);
@@ -157,6 +143,7 @@ int main(int argc, char *argv[])
int demonize = 1;
int opt = 0;
int longIndex = 0;
+ int i;
static const char *optString = "f:d:nrsiHV?";
static const struct option longOpts[] =
{
@@ -218,7 +205,9 @@ int main(int argc, char *argv[])
if (demonize)
daemon(1, 0);
- pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE);
+ pthread_spin_init(&_clients_lock, PTHREAD_PROCESS_PRIVATE);
+ pthread_spin_init(&_images_lock, PTHREAD_PROCESS_PRIVATE);
+ pthread_spin_init(&_alts_lock, PTHREAD_PROCESS_PRIVATE);
initmemlog();
memlogf("DNBD3 server starting.... Machine type: " ENDIAN_MODE);
@@ -247,12 +236,12 @@ int main(int argc, char *argv[])
int fd;
// setup rpc
- pthread_t thread_rpc;
- pthread_create(&(thread_rpc), NULL, &dnbd3_rpc_mainloop, NULL);
+ //pthread_t thread_rpc;
+ //pthread_create(&(thread_rpc), NULL, &dnbd3_rpc_mainloop, NULL);
// setup the job thread (query other servers, delete old images etc.)
- pthread_t thread_job;
- pthread_create(&(thread_job), NULL, &dnbd3_job_thread, NULL);
+ //pthread_t thread_job;
+ //pthread_create(&(thread_job), NULL, &dnbd3_job_thread, NULL);
memlogf("[INFO] Server is ready...");
@@ -264,55 +253,31 @@ int main(int argc, char *argv[])
if (fd < 0)
{
memlogf("[ERROR] Client accept failure");
+ usleep(10000); // 10ms
continue;
}
//memlogf("INFO: Client %s connected\n", inet_ntoa(client.sin_addr));
sock_set_timeout(fd, SOCKET_TIMEOUT_SERVER_MS);
- dnbd3_client_t *dnbd3_client = g_new0(dnbd3_client_t, 1);
+ dnbd3_client_t *dnbd3_client = dnbd3_init_client(&client, fd);
if (dnbd3_client == NULL)
{
- memlogf("[ERROR] Could not alloc dnbd3_client_t for new client.");
close(fd);
continue;
}
- if (client.ss_family == AF_INET) {
- struct sockaddr_in *v4 = (struct sockaddr_in *)&client;
- dnbd3_client->host.type = AF_INET;
- memcpy(dnbd3_client->host.addr, &(v4->sin_addr), 4);
- dnbd3_client->host.port = v4->sin_port;
- }
- else if (client.ss_family == AF_INET6)
- {
- struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)&client;
- dnbd3_client->host.type = AF_INET6;
- memcpy(dnbd3_client->host.addr, &(v6->sin6_addr), 16);
- dnbd3_client->host.port = v6->sin6_port;
- }
- else
- {
- memlogf("[ERROR] New client has unknown address family %d, disconnecting...", (int)client.ss_family);
- close(fd);
- g_free(dnbd3_client);
- continue;
- }
- dnbd3_client->sock = fd;
- dnbd3_client->image = NULL;
// This has to be done before creating the thread, otherwise a race condition might occur when the new thread dies faster than this thread adds the client to the list after creating the thread
- pthread_spin_lock(&_spinlock);
- _dnbd3_clients = g_slist_prepend(_dnbd3_clients, dnbd3_client);
- pthread_spin_unlock(&_spinlock);
+ if (!dnbd3_add_client(dnbd3_client)) {
+ dnbd3_free_client(dnbd3_client);
+ continue;
+ }
if (0 != pthread_create(&(dnbd3_client->thread), NULL, net_client_handler, (void *) (uintptr_t) dnbd3_client))
{
memlogf("[ERROR] Could not start thread for new client.");
- pthread_spin_lock(&_spinlock);
- _dnbd3_clients = g_slist_remove(_dnbd3_clients, dnbd3_client);
- pthread_spin_unlock(&_spinlock);
+ dnbd3_remove_client(dnbd3_client);
dnbd3_free_client(dnbd3_client);
- close(fd);
continue;
}
pthread_detach(dnbd3_client->thread);
@@ -321,6 +286,34 @@ int main(int argc, char *argv[])
dnbd3_cleanup();
}
+dnbd3_client_t* dnbd3_init_client(struct sockaddr_storage *client, int fd)
+{
+ dnbd3_client_t *dnbd3_client = calloc(1, sizeof(dnbd3_client_t));
+ if (dnbd3_client == NULL) {
+ memlogf("[ERROR] Could not alloc dnbd3_client_t for new client.");
+ return NULL;
+ }
+
+ if (client.ss_family == AF_INET) {
+ struct sockaddr_in *v4 = (struct sockaddr_in *)&client;
+ dnbd3_client->host.type = AF_INET;
+ memcpy(dnbd3_client->host.addr, &(v4->sin_addr), 4);
+ dnbd3_client->host.port = v4->sin_port;
+ } else if (client.ss_family == AF_INET6) {
+ struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)&client;
+ dnbd3_client->host.type = AF_INET6;
+ memcpy(dnbd3_client->host.addr, &(v6->sin6_addr), 16);
+ dnbd3_client->host.port = v6->sin6_port;
+ } else {
+ memlogf("[ERROR] New client has unknown address family %d, disconnecting...", (int)client.ss_family);
+ free(dnbd3_client);
+ return NULL;
+ }
+ dnbd3_client->sock = fd;
+ pthread_spin_init(&dnbd3_client->lock, PTHREAD_PROCESS_PRIVATE);
+ return dnbd3_client;
+}
+
/**
* Free the client struct recursively
*/
@@ -332,5 +325,49 @@ void dnbd3_free_client(dnbd3_client_t *client)
free(it->data);
}
g_slist_free(client->sendqueue);
+ if (client->sock >= 0) close(client->sock);
g_free(client);
}
+
+int dnbd3_add_client(dnbd3_client_t *client)
+{
+ int i;
+ pthread_spin_lock(&_clients_lock);
+ for (i = 0; i < _num_clients; ++i) {
+ if (_clients[i] != NULL) continue;
+ _clients[i] = client;
+ pthread_spin_unlock(&_clients_lock);
+ return TRUE;
+ }
+ if (_num_clients >= SERVER_MAX_CLIENTS) {
+ pthread_spin_unlock(&_clients_lock);
+ memlogf("[ERROR] Maximum number of clients reached!");
+ return FALSE;
+ }
+ _clients[_num_clients++] = client;
+ pthread_spin_unlock(&_clients_lock);
+ return TRUE;
+}
+
+void dnbd3_remove_client(dnbd3_client_t *client)
+{
+ int i;
+ pthread_spin_lock(&_clients_lock);
+ for (i = _num_clients - 1; i >= 0; --i) {
+ if (_clients[i] != client) continue;
+ _clients[i] = NULL;
+ if (i + 1 == _num_clients) --_num_clients;
+ }
+ pthread_spin_unlock(&_clients_lock);
+}
+
+static void dnbd3_handle_sigpipe(int signum)
+{
+ memlogf("INFO: SIGPIPE received (%s)", strsignal(signum));
+}
+
+static void dnbd3_handle_sigterm(int signum)
+{
+ memlogf("INFO: SIGTERM or SIGINT received (%s)", strsignal(signum));
+ dnbd3_cleanup();
+}