From ecd41fa1ea2b5b267e6f04170bad30b150433fc6 Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Thu, 26 Jan 2012 18:53:43 +0100 Subject: [SERVER] Reload configuration at runtime --- src/config.h | 3 ++ src/server/hashtable.c | 7 +++ src/server/hashtable.h | 2 + src/server/server.c | 96 +++++++++++++++++++++++++++------------- src/server/utils.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++ src/server/utils.h | 38 ++++++++++++++++ 6 files changed, 232 insertions(+), 31 deletions(-) create mode 100644 src/server/utils.c create mode 100644 src/server/utils.h 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 + * + * 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 +#include +#include + +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 + * + * 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 +#include + +#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_ */ -- cgit v1.2.3-55-g7522