summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohann Latocha2012-01-26 18:53:43 +0100
committerJohann Latocha2012-01-26 18:53:43 +0100
commitecd41fa1ea2b5b267e6f04170bad30b150433fc6 (patch)
tree5092f862fa50ede329e25a6e104e0cacbbe25eea
parent[KERNEL] Multi device support (diff)
downloaddnbd3-ecd41fa1ea2b5b267e6f04170bad30b150433fc6.tar.gz
dnbd3-ecd41fa1ea2b5b267e6f04170bad30b150433fc6.tar.xz
dnbd3-ecd41fa1ea2b5b267e6f04170bad30b150433fc6.zip
[SERVER] Reload configuration at runtime
-rw-r--r--src/config.h3
-rw-r--r--src/server/hashtable.c7
-rw-r--r--src/server/hashtable.h2
-rw-r--r--src/server/server.c96
-rw-r--r--src/server/utils.c117
-rw-r--r--src/server/utils.h38
6 files changed, 232 insertions, 31 deletions
diff --git a/src/config.h b/src/config.h
index 2839bb5..1aabf47 100644
--- a/src/config.h
+++ b/src/config.h
@@ -35,4 +35,7 @@
#define MAX_FILE_NAME 4096
#define MAX_FILE_ID 8
+// misc
+#define SERVER_PID_FILE "/tmp/dnbd3-server.pid"
+
#endif /* CONFIG_H_ */
diff --git a/src/server/hashtable.c b/src/server/hashtable.c
index 2099a65..b6272f2 100644
--- a/src/server/hashtable.c
+++ b/src/server/hashtable.c
@@ -35,6 +35,13 @@ void ht_create()
(void) hcreate(MAX_NUMBER_IMAGES);
}
+void ht_destroy()
+{
+ key_ptr = key_buf;
+ val_ptr = value_buf;
+ hdestroy();
+}
+
int ht_insert(char* key, char* value)
{
if (strlen(key) > MAX_FILE_ID) return -1;
diff --git a/src/server/hashtable.h b/src/server/hashtable.h
index c05d459..3851d96 100644
--- a/src/server/hashtable.h
+++ b/src/server/hashtable.h
@@ -23,6 +23,8 @@
void ht_create ();
+void ht_destroy();
+
int ht_insert(char* key, char* value);
char* ht_search(char* key);
diff --git a/src/server/server.c b/src/server/server.c
index c266f19..90ec77b 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -39,14 +39,22 @@
#include "../types.h"
#include "../version.h"
+#include "utils.h"
#include "hashtable.h"
+int _sock;
+pthread_spinlock_t spinlock;
+char *config_file_name = DEFAULT_CONFIG_FILE;
+
void 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\n \t\t\t (default /etc/dnbd3-server.conf)\n");
+ printf("-f or --file \t\t Configuration file (default /etc/dnbd3-server.conf)\n");
+ printf("-n or --nodaemon \t\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");
printf("-h or --help \t\t Show this help text and quit\n");
printf("-v or --version \t Show version and quit\n");
exit(0);
@@ -64,6 +72,24 @@ void handle_sigpipe(int signum)
return;
}
+void handle_sighup(int signum)
+{
+ printf("INFO: SIGHUP received!\n");
+ printf("INFO: Reloading configuration...\n");
+ pthread_spin_lock(&spinlock);
+ reload_config(config_file_name);
+ pthread_spin_unlock(&spinlock);
+ // TODO: stop handle_query or use mutex before image_file = open(ht_search(request.image_id), O_RDONLY);
+}
+
+void handle_sigterm(int signum)
+{
+ printf("INFO: SIGTERM or SIGINT received!\n");
+ close(_sock);
+ delete_pid_file();
+ exit(EXIT_SUCCESS);
+}
+
void *handle_query(void *client_socket)
{
int image_file = -1;
@@ -79,7 +105,9 @@ void *handle_query(void *client_socket)
switch (cmd)
{
case CMD_GET_SIZE:
+ pthread_spin_lock(&spinlock); // because of reloading config
image_file = open(ht_search(request.image_id), O_RDONLY);
+ pthread_spin_unlock(&spinlock);
if (image_file < 0)
{
printf("ERROR: Client requested an unknown image id.\n");
@@ -124,14 +152,16 @@ void *handle_query(void *client_socket)
int main(int argc, char* argv[])
{
- char *config_file_name = DEFAULT_CONFIG_FILE;
-
+ int demonize = 1;
int opt = 0;
int longIndex = 0;
- static const char *optString = "f:hv?";
+ static const char *optString = "f:nrshv?";
static const struct option longOpts[] =
{
{ "file", required_argument, NULL, 'f' },
+ { "nodaemon", no_argument, NULL, 'n' },
+ { "reload", no_argument, NULL, 'r' },
+ { "stop", no_argument, NULL, 's' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' } };
@@ -144,6 +174,17 @@ int main(int argc, char* argv[])
case 'f':
config_file_name = optarg;
break;
+ case 'n':
+ demonize = 0;
+ break;
+ case 'r':
+ printf("INFO: Reloading configuration file...\n");
+ send_signal(SIGHUP);
+ return EXIT_SUCCESS;
+ case 's':
+ printf("INFO: Stopping running server...\n");
+ send_signal(SIGTERM);
+ return EXIT_SUCCESS;
case 'h':
print_help(argv[0]);
break;
@@ -156,38 +197,27 @@ int main(int argc, char* argv[])
opt = getopt_long(argc, argv, optString, longOpts, &longIndex);
}
- // parse config file
- ht_create();
- FILE *config_file = fopen(config_file_name, "r");
- if (config_file == NULL)
- {
- printf("ERROR: Config file not found: %s\n", config_file_name);
- exit(EXIT_FAILURE);
- }
- char line[MAX_FILE_NAME + 1 + MAX_FILE_ID];
- char* image_name = NULL;
- char* image_id = NULL;
- while (fgets(line, sizeof(line), config_file) != NULL)
- {
- sscanf(line, "%as %as", &image_name, &image_id);
- if (ht_insert(image_id, image_name) < 0)
- {
- printf("ERROR: Image name or ID is too big\n");
- exit(EXIT_FAILURE);
- }
- }
+ if (demonize)
+ daemon(1,0);
- // setup network
+ pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE);
+ load_config(config_file_name);
+
+ // setup signal handler
signal(SIGPIPE, handle_sigpipe);
+ signal(SIGHUP, handle_sighup);
+ signal(SIGTERM, handle_sigterm);
+ signal(SIGINT, handle_sigterm);
+ // setup network
struct sockaddr_in server;
struct sockaddr_in client;
- int sock, fd;
+ int fd;
unsigned int len;
// Create socket
- sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (sock < 0)
+ _sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (_sock < 0)
{
printf("ERROR: Socket failure\n");
exit(EXIT_FAILURE);
@@ -199,25 +229,26 @@ int main(int argc, char* argv[])
server.sin_port = htons(PORT); // set port number
// Bind to socket
- if (bind(sock, (struct sockaddr*) &server, sizeof(server)) < 0)
+ if (bind(_sock, (struct sockaddr*) &server, sizeof(server)) < 0)
{
printf("ERROR: Bind failure\n");
exit(EXIT_FAILURE);
}
// Listen on socket
- if (listen(sock, 50) == -1)
+ if (listen(_sock, 50) == -1)
{
printf("ERROR: Listen failure\n");
exit(EXIT_FAILURE);
}
+ write_pid_file(getpid());
printf("INFO: Server is ready...\n");
while (1)
{
len = sizeof(client);
- fd = accept(sock, (struct sockaddr*) &client, &len);
+ fd = accept(_sock, (struct sockaddr*) &client, &len);
if (fd < 0)
{
printf("ERROR: Accept failure\n");
@@ -230,5 +261,8 @@ int main(int argc, char* argv[])
pthread_create(&(thread), NULL, handle_query, (void *) fd);
pthread_detach(thread);
}
+
+ close(_sock);
+ delete_pid_file();
return EXIT_SUCCESS;
}
diff --git a/src/server/utils.c b/src/server/utils.c
new file mode 100644
index 0000000..e0bbecf
--- /dev/null
+++ b/src/server/utils.c
@@ -0,0 +1,117 @@
+/*
+ * This file is part of the Distributed Network Block Device 3
+ *
+ * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de>
+ *
+ * This file may be licensed under the terms of of the
+ * GNU General Public License Version 2 (the ``GPL'').
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the GPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the GPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "utils.h"
+#include "hashtable.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+
+void write_pid_file(pid_t pid)
+{
+ FILE *f = fopen(SERVER_PID_FILE, "w");
+ if(f != NULL)
+ {
+ fprintf(f, "%i", pid);
+ fclose(f);
+ }
+ else
+ {
+ printf("ERROR: Couldn't write pid file (%s).\n", SERVER_PID_FILE);
+ }
+}
+
+pid_t read_pid_file()
+{
+ pid_t pid = 0;
+
+ FILE *f = fopen(SERVER_PID_FILE, "r");
+ if(f != NULL)
+ {
+ fscanf(f, "%i", &pid);
+ fclose(f);
+ }
+ else
+ {
+ printf("ERROR: Couldn't read pid file (%s).\n", SERVER_PID_FILE);
+ }
+
+ return pid;
+}
+
+void delete_pid_file()
+{
+ if (unlink(SERVER_PID_FILE) != 0)
+ {
+ printf("ERROR: Couldn't delete pid file (%s).\n", SERVER_PID_FILE);
+ }
+}
+
+
+void load_config(char* config_file_name)
+{
+ ht_create();
+ FILE *config_file = fopen(config_file_name, "r");
+
+ if (config_file == NULL)
+ {
+ printf("ERROR: Config file not found: %s\n", config_file_name);
+ exit(EXIT_FAILURE);
+ }
+
+ char line[MAX_FILE_NAME + 1 + MAX_FILE_ID];
+ char* image_name = NULL;
+ char* image_id = NULL;
+
+ while (fgets(line, sizeof(line), config_file) != NULL)
+ {
+ sscanf(line, "%as %as", &image_name, &image_id);
+ if (ht_insert(image_id, image_name) < 0)
+ {
+ printf("ERROR: Image name or ID is too big\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ fclose(config_file);
+}
+
+void reload_config(char* config_file_name)
+{
+ ht_destroy();
+ load_config(config_file_name);
+}
+
+void send_signal(int signum)
+{
+ pid_t pid = read_pid_file();
+ if (pid != 0)
+ {
+ if (kill(pid, signum) != 0)
+ {
+ printf("ERROR: dnbd3-server is not running\n");
+ delete_pid_file();
+ }
+ }
+ else
+ {
+ printf("ERROR: dnbd3-server is not running\n");
+ }
+}
diff --git a/src/server/utils.h b/src/server/utils.h
new file mode 100644
index 0000000..f9d6896
--- /dev/null
+++ b/src/server/utils.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the Distributed Network Block Device 3
+ *
+ * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de>
+ *
+ * This file may be licensed under the terms of of the
+ * GNU General Public License Version 2 (the ``GPL'').
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the GPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the GPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "../config.h"
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+void write_pid_file(pid_t pid);
+pid_t read_pid_file();
+void delete_pid_file();
+
+void load_config(char* config_file_name);
+void reload_config(char* config_file_name);
+
+void send_signal(int signum);
+
+#endif /* UTILS_H_ */