public inbox for lvm2-cvs@sourceware.org
help / color / mirror / Atom feed
* LVM2/daemons/common daemon-client.h daemon-ser ...
@ 2011-07-18 14:46 mornfall
  0 siblings, 0 replies; 4+ messages in thread
From: mornfall @ 2011-07-18 14:46 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mornfall@sourceware.org	2011-07-18 14:46:54

Modified files:
	daemons/common : daemon-client.h daemon-server.c daemon-server.h 

Log message:
	Various improvements to the daemon-common code, including automated response
	formatting from config trees provided by the daemon implementation.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-client.h.diff?cvsroot=lvm2&r1=1.6&r2=1.7
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.7&r2=1.8
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.h.diff?cvsroot=lvm2&r1=1.8&r2=1.9

--- LVM2/daemons/common/daemon-client.h	2011/06/27 14:03:58	1.6
+++ LVM2/daemons/common/daemon-client.h	2011/07/18 14:46:54	1.7
@@ -12,6 +12,7 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include "libdevmapper.h" // for dm_list, needed by config.h
 #include "config.h" // should become part of libdevmapper later
 
 #ifndef _LVM_DAEMON_COMMON_CLIENT_H
--- LVM2/daemons/common/daemon-server.c	2011/06/29 22:20:14	1.7
+++ LVM2/daemons/common/daemon-server.c	2011/07/18 14:46:54	1.8
@@ -218,6 +218,22 @@
 	client_handle client;
 };
 
+int buffer_rewrite(char **buf, const char *format, const char *string) {
+	char *old = *buf;
+	dm_asprintf(buf, format, *buf, string);
+	dm_free(old);
+	return 0;
+}
+
+int buffer_line(const char *line, void *baton) {
+	response *r = baton;
+	if (r->buffer)
+		buffer_rewrite(&r->buffer, "%s\n%s", line);
+	else
+		dm_asprintf(&r->buffer, "%s\n", line);
+	return 0;
+}
+
 void *client_thread(void *baton)
 {
 	struct thread_baton *b = baton;
@@ -227,12 +243,16 @@
 			goto fail;
 
 		req.cft = create_config_tree_from_string(req.buffer);
+		if (!req.cft)
+			fprintf(stderr, "error parsing request:\n %s\n", req.buffer);
 		response res = b->s.handler(b->s, b->client, req);
-		destroy_config_tree(req.cft);
+		if (req.cft)
+			destroy_config_tree(req.cft);
 		dm_free(req.buffer);
 
 		if (!res.buffer) {
-			/* TODO fill in the buffer from res.cft */
+			write_config_node(res.cft->root, buffer_line, &res);
+			buffer_rewrite(&res.buffer, "%s\n\n", NULL);
 		}
 
 		write_buffer(b->client.socket_fd, res.buffer, strlen(res.buffer));
@@ -318,6 +338,9 @@
 	if (!s.foreground)
 		kill(getppid(), SIGTERM);
 
+	if (s.daemon_init)
+		s.daemon_init(&s);
+
 	while (!_shutdown_requested && !failed) {
 		int status;
 		fd_set in;
@@ -333,6 +356,9 @@
 	if (s.socket_fd >= 0)
 		unlink(s.socket_path);
 
+	if (s.daemon_fini)
+		s.daemon_fini(&s);
+
 	syslog(LOG_NOTICE, "%s shutting down", s.name);
 	closelog();
 	remove_lockfile(s.pidfile);
--- LVM2/daemons/common/daemon-server.h	2011/06/27 14:03:59	1.8
+++ LVM2/daemons/common/daemon-server.h	2011/07/18 14:46:54	1.9
@@ -45,10 +45,14 @@
 response daemon_reply_simple(char *id, ...);
 
 static inline int daemon_request_int(request r, const char *path, int def) {
+	if (!r.cft)
+		return def;
 	return find_config_int(r.cft->root, path, def);
 }
 
 static inline const char *daemon_request_str(request r, const char *path, const char *def) {
+	if (!r.cft)
+		return def;
 	return find_config_str(r.cft->root, path, def);
 }
 
@@ -77,7 +81,8 @@
 	const char *socket_path;
 	int log_level;
 	handle_request handler;
-	int (*setup_post)(struct daemon_state *st);
+	int (*daemon_init)(struct daemon_state *st);
+	int (*daemon_fini)(struct daemon_state *st);
 
 	/* Global runtime info maintained by the framework. */
 	int socket_fd;


^ permalink raw reply	[flat|nested] 4+ messages in thread

* LVM2/daemons/common daemon-client.h daemon-ser ...
@ 2011-06-14  2:34 mornfall
  0 siblings, 0 replies; 4+ messages in thread
From: mornfall @ 2011-06-14  2:34 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mornfall@sourceware.org	2011-06-14 02:34:18

Modified files:
	daemons/common : daemon-client.h daemon-server.c daemon-server.h 
Added files:
	daemons/common : daemon-client.c daemon-shared.c daemon-shared.h 

Log message:
	Common daemon code: Implement basic socket-based communication infrastructure
	(both client and server side). The server handles each connection in a separate
	thread.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-client.c.diff?cvsroot=lvm2&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-shared.c.diff?cvsroot=lvm2&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-shared.h.diff?cvsroot=lvm2&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-client.h.diff?cvsroot=lvm2&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.h.diff?cvsroot=lvm2&r1=1.4&r2=1.5

/cvs/lvm2/LVM2/daemons/common/daemon-client.c,v  -->  standard output
revision 1.1
--- LVM2/daemons/common/daemon-client.c
+++ -	2011-06-14 02:34:19.031404000 +0000
@@ -0,0 +1,54 @@
+#include "daemon-client.h"
+#include "daemon-shared.h"
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+daemon_handle daemon_open(daemon_info i) {
+	daemon_handle h;
+	struct sockaddr_un sockaddr;
+	if ((h.socket_fd = socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0) {
+		perror("socket");
+		goto error;
+	}
+	memset(&sockaddr, 0, sizeof(sockaddr));
+	fprintf(stderr, "connecting to %s\n", i.socket);
+	strcpy(sockaddr.sun_path, i.socket);
+	sockaddr.sun_family = AF_UNIX;
+	if (connect(h.socket_fd,(struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
+		perror("connect");
+		goto error;
+	}
+	h.protocol = 0;
+	return h;
+error:
+	if (h.socket_fd >= 0)
+		close(h.socket_fd);
+	h.socket_fd = -1;
+	return h;
+}
+
+daemon_reply daemon_send(daemon_handle h, daemon_request rq)
+{
+	daemon_reply reply;
+	assert(h.socket_fd >= 0);
+
+	if (!rq.buffer) {
+		/* TODO: build the buffer from rq.cft */
+	}
+
+	assert(rq.buffer);
+	write_buffer(h.socket_fd, rq.buffer, strlen(rq.buffer));
+
+	if (read_buffer(h.socket_fd, &reply.buffer)) {
+		/* TODO: parse reply.buffer into reply.cft */
+	} else
+		reply.error = 1;
+
+	return reply;
+}
+
+void daemon_close(daemon_handle h) {
+}
/cvs/lvm2/LVM2/daemons/common/daemon-shared.c,v  -->  standard output
revision 1.1
--- LVM2/daemons/common/daemon-shared.c
+++ -	2011-06-14 02:34:19.142467000 +0000
@@ -0,0 +1,68 @@
+#include <errno.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+
+/*
+ * Read a single message from a (socket) filedescriptor. Messages are delimited
+ * by blank lines. This call will block until all of a message is received. The
+ * memory will be allocated from heap. Upon error, all memory is freed and the
+ * buffer pointer is set to NULL.
+ */
+int read_buffer(int fd, char **buffer) {
+	int bytes = 0;
+	int buffersize = 32;
+	*buffer = malloc(buffersize + 1);
+
+	while (1) {
+		int result = read(fd, (*buffer) + bytes, buffersize - bytes);
+		if (result > 0)
+			bytes += result;
+		if (result == 0)
+			goto fail; /* we should never encounter EOF here */
+		if (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
+			goto fail;
+
+		if (bytes == buffersize) {
+			buffersize += 1024;
+			char *new = realloc(*buffer, buffersize + 1);
+			if (new)
+				*buffer = new;
+			else
+				goto fail;
+		} else {
+			(*buffer)[bytes] = 0;
+			char *end;
+			if ((end = strstr((*buffer) + bytes - 2, "\n\n"))) {
+				*end = 0;
+				break; /* success, we have the full message now */
+			}
+			/* TODO call select here if we encountered EAGAIN/EWOULDBLOCK */
+		}
+	}
+	return 1;
+fail:
+	free(*buffer);
+	*buffer = NULL;
+	return 0;
+}
+
+/*
+ * Write a buffer to a filedescriptor. Keep trying. Blocks (even on
+ * SOCK_NONBLOCK) until all of the write went through.
+ *
+ * TODO use select on EWOULDBLOCK/EAGAIN to avoid useless spinning
+ */
+int write_buffer(int fd, char *buffer, int length) {
+	int written = 0;
+	while (1) {
+		int result = write(fd, buffer + written, length - written);
+		if (result > 0)
+			written += result;
+		if (result < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
+			break; /* too bad */
+		if (written == length)
+			return 1; /* done */
+	}
+	return 0;
+}
/cvs/lvm2/LVM2/daemons/common/daemon-shared.h,v  -->  standard output
revision 1.1
--- LVM2/daemons/common/daemon-shared.h
+++ -	2011-06-14 02:34:19.240114000 +0000
@@ -0,0 +1,2 @@
+int read_buffer(int fd, char **buffer);
+int write_buffer(int fd, char *buffer, int length);
--- LVM2/daemons/common/daemon-client.h	2011/05/15 11:02:29	1.2
+++ LVM2/daemons/common/daemon-client.h	2011/06/14 02:34:18	1.3
@@ -12,6 +12,8 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include "config.h" // should become part of libdevmapper later
+
 #ifndef _LVM_DAEMON_COMMON_CLIENT_H
 #define _LVM_DAEMON_COMMON_CLIENT_H
 
@@ -28,13 +30,14 @@
 } daemon_info;
 
 typedef struct {
-	char *request;
+	char *buffer;
+	struct config_node *cft;
 } daemon_request;
 
 typedef struct {
 	int error; /* 0 for success */
-	char *reply; /* textual reply */
-	struct config_tree *cft; /* parsed reply, if available */
+	char *buffer; /* textual reply */
+	struct config_node *cft; /* parsed reply, if available */
 } daemon_reply;
 
 /*
--- LVM2/daemons/common/daemon-server.c	2011/05/15 11:02:29	1.3
+++ LVM2/daemons/common/daemon-server.c	2011/06/14 02:34:18	1.4
@@ -107,8 +107,9 @@
 		fprintf(stderr, "setting CLOEXEC on socket fd %d failed: %s\n", fd, strerror(errno));
 	fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
 
+	fprintf(stderr, "creating %s\n", s.socket_path);
 	memset(&sockaddr, 0, sizeof(sockaddr));
-	memcpy(sockaddr.sun_path, s.socket_path, strlen(s.socket_path));
+	strcpy(sockaddr.sun_path, s.socket_path);
 	sockaddr.sun_family = AF_UNIX;
 
 	if (bind(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
@@ -128,6 +129,7 @@
 error:
 	if (fd >= 0) {
 		close(fd);
+		unlink(s.socket_path);
 		fd = -1;
 	}
 	goto out;
@@ -198,6 +200,60 @@
 	setsid();
 }
 
+struct thread_baton {
+	daemon_state s;
+	client_handle client;
+};
+
+void *client_thread(void *baton)
+{
+	struct thread_baton *b = baton;
+	request req;
+	while (1) {
+		if (!read_buffer(b->client.socket_fd, &req.buffer))
+			goto fail;
+
+		/* TODO parse the buffer into req.cft */
+		response res = b->s.handler(b->s, b->client, req);
+
+		if (!res.buffer) {
+			/* TODO fill in the buffer from res.cft */
+		}
+
+		write_buffer(b->client.socket_fd, res.buffer, strlen(res.buffer));
+
+		free(res.buffer);
+		free(req.buffer);
+	}
+fail:
+	/* TODO what should we really do here? */
+	return NULL;
+}
+
+int handle_connect(daemon_state s)
+{
+	struct sockaddr_un sockaddr;
+	client_handle client;
+	socklen_t sl = sizeof(sockaddr);
+	int client_fd = accept(s.socket_fd, (struct sockaddr *) &sockaddr, &sl);
+	if (client_fd < 0)
+		return 0;
+
+	struct thread_baton *baton = malloc(sizeof(struct thread_baton));
+	if (!baton)
+		return 0;
+
+	client.socket_fd = client_fd;
+	client.read_buf = 0;
+	client.private = 0;
+	baton->s = s;
+	baton->client = client;
+
+	if (pthread_create(&baton->client.thread_id, NULL, client_thread, baton))
+		return 0;
+	return 1;
+}
+
 void daemon_start(daemon_state s)
 {
 	int failed = 0;
@@ -230,6 +286,8 @@
 	signal(SIGINT, &_exit_handler);
 	signal(SIGHUP, &_exit_handler);
 	signal(SIGQUIT, &_exit_handler);
+	signal(SIGTERM, &_exit_handler);
+	signal(SIGPIPE, SIG_IGN);
 
 #ifdef linux
 	if (s.avoid_oom && !_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN))
@@ -247,9 +305,20 @@
 		kill(getppid(), SIGTERM);
 
 	while (!_shutdown_requested && !failed) {
-		/* TODO: do work */
+		int status;
+		fd_set in;
+		FD_ZERO(&in);
+		FD_SET(s.socket_fd, &in);
+		if (select(FD_SETSIZE, &in, NULL, NULL, NULL) < 0 && errno != EINTR)
+			perror("select error");
+		if (FD_ISSET(s.socket_fd, &in))
+			if (!handle_connect(s))
+				syslog(LOG_ERR, "Failed to handle a client connection.");
 	}
 
+	if (s.socket_fd >= 0)
+		unlink(s.socket_path);
+
 	syslog(LOG_NOTICE, "%s shutting down", s.name);
 	closelog();
 	remove_lockfile(s.pidfile);
--- LVM2/daemons/common/daemon-server.h	2011/05/15 11:02:29	1.4
+++ LVM2/daemons/common/daemon-server.h	2011/06/14 02:34:18	1.5
@@ -13,6 +13,7 @@
  */
 
 #include "daemon-client.h"
+#include "config.h" // XXX will be in libdevmapper.h later
 
 #ifndef _LVM_DAEMON_COMMON_SERVER_H
 #define _LVM_DAEMON_COMMON_SERVER_H
@@ -25,12 +26,14 @@
 } client_handle;
 
 typedef struct {
-	struct config_tree *cft;
+	struct config_node *cft;
+	char *buffer;
 } request;
 
 typedef struct {
 	int error;
-	struct config_tree *cft;
+	struct config_node *cft;
+	char *buffer;
 } response;
 
 struct daemon_state;


^ permalink raw reply	[flat|nested] 4+ messages in thread

* LVM2/daemons/common daemon-client.h daemon-ser ...
@ 2011-05-15 11:02 mornfall
  0 siblings, 0 replies; 4+ messages in thread
From: mornfall @ 2011-05-15 11:02 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mornfall@sourceware.org	2011-05-15 11:02:29

Modified files:
	daemons/common : daemon-client.h daemon-server.c daemon-server.h 

Log message:
	More work on the common daemon framework. Make things compile, too.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-client.h.diff?cvsroot=lvm2&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.h.diff?cvsroot=lvm2&r1=1.3&r2=1.4

--- LVM2/daemons/common/daemon-client.h	2011/05/13 08:07:28	1.1
+++ LVM2/daemons/common/daemon-client.h	2011/05/15 11:02:29	1.2
@@ -32,7 +32,7 @@
 } daemon_request;
 
 typedef struct {
-	int errno; /* 0 for success */
+	int error; /* 0 for success */
 	char *reply; /* textual reply */
 	struct config_tree *cft; /* parsed reply, if available */
 } daemon_reply;
@@ -51,7 +51,7 @@
  * the daemon is synchronous. The function handles the IO details and parses the
  * response, handling common error conditions. See "daemon_reply" for details.
  */
-daemon_reply daemon_request(daemon_handle h, daemon_request r);
+daemon_reply daemon_send(daemon_handle h, daemon_request r);
 
 /* Shut down the communication to the daemon. Compulsory. */
 void daemon_close(daemon_handle h);
--- LVM2/daemons/common/daemon-server.c	2011/05/13 09:34:12	1.2
+++ LVM2/daemons/common/daemon-server.c	2011/05/15 11:02:29	1.3
@@ -18,11 +18,16 @@
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <sys/resource.h>
+#include <netinet/in.h>
+#include <sys/un.h>
 #include <unistd.h>
 #include <signal.h>
 
 #include <syslog.h>
+#include "daemon-server.h"
+#include "libdevmapper.h"
 
+#if 0
 /* Create a device monitoring thread. */
 static int _pthread_create(pthread_t *t, void *(*fun)(void *), void *arg, int stacksize)
 {
@@ -34,6 +39,7 @@
 	pthread_attr_setstacksize(&attr, stacksize);
 	return pthread_create(t, &attr, fun, arg);
 }
+#endif
 
 static volatile sig_atomic_t _shutdown_requested = 0;
 
@@ -44,6 +50,7 @@
 
 #ifdef linux
 #  define OOM_ADJ_FILE "/proc/self/oom_adj"
+#  include <stdio.h>
 
 /* From linux/oom.h */
 #  define OOM_DISABLE (-17)
@@ -72,7 +79,7 @@
 	}
 
 	fprintf(fp, "%i", val);
-	if (dm_fclose(fp))
+	if (fclose(fp))
 		perror(OOM_ADJ_FILE ": fclose failed");
 
 	return 1;
@@ -91,13 +98,13 @@
 	/* Open local socket */
 	fd = socket(PF_UNIX, SOCK_STREAM, 0);
 	if (fd < 0) {
-		log_error("Can't create local socket: %m");
+		perror("Can't create local socket.");
 		goto error;
 	}
 
 	/* Set Close-on-exec & non-blocking */
 	if (fcntl(fd, F_SETFD, 1))
-		DEBUGLOG("setting CLOEXEC on socket fd %d failed: %s\n", fd, strerror(errno));
+		fprintf(stderr, "setting CLOEXEC on socket fd %d failed: %s\n", fd, strerror(errno));
 	fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
 
 	memset(&sockaddr, 0, sizeof(sockaddr));
@@ -105,11 +112,11 @@
 	sockaddr.sun_family = AF_UNIX;
 
 	if (bind(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
-		log_error("can't bind local socket: %m");
+		perror("can't bind local socket.");
 		goto error;
 	}
 	if (listen(fd, 1) != 0) {
-		log_error("listen local: %m");
+		perror("listen local");
 		goto error;
 	}
 
@@ -129,7 +136,7 @@
 static void remove_lockfile(const char *file)
 {
 	if (unlink(file))
-		perror(file ": unlink failed");
+		perror("unlink failed");
 }
 
 static void _daemonise(void)
@@ -158,7 +165,7 @@
 
 	default:
 		/* Wait for response from child */
-		while (!waitpid(pid, &child_status, WNOHANG) && !_exit_now) {
+		while (!waitpid(pid, &child_status, WNOHANG) && !_shutdown_requested) {
 			tval.tv_sec = 0;
 			tval.tv_usec = 250000;	/* .25 sec */
 			select(0, NULL, NULL, NULL, &tval);
@@ -168,16 +175,7 @@
 			exit(0);
 
 		/* Problem with child.  Determine what it is by exit code */
-		switch (WEXITSTATUS(child_status)) {
-		case EXIT_DESC_CLOSE_FAILURE:
-		case EXIT_DESC_OPEN_FAILURE:
-		case EXIT_FIFO_FAILURE:
-		case EXIT_CHDIR_FAILURE:
-		default:
-			fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status));
-			break;
-		}
-
+		fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status));
 		exit(WEXITSTATUS(child_status));
 	}
 
@@ -200,7 +198,7 @@
 	setsid();
 }
 
-void daemon_start(daemon_state s, handle_request r)
+void daemon_start(daemon_state s)
 {
 	int failed = 0;
 	/*
--- LVM2/daemons/common/daemon-server.h	2011/05/13 09:34:12	1.3
+++ LVM2/daemons/common/daemon-server.h	2011/05/15 11:02:29	1.4
@@ -12,8 +12,10 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef _LVM_DAEMON_COMMON_CLIENT_H
-#define _LVM_DAEMON_COMMON_CLIENT_H
+#include "daemon-client.h"
+
+#ifndef _LVM_DAEMON_COMMON_SERVER_H
+#define _LVM_DAEMON_COMMON_SERVER_H
 
 typedef struct {
 	int socket_fd; /* the fd we use to talk to the client */
@@ -23,6 +25,26 @@
 } client_handle;
 
 typedef struct {
+	struct config_tree *cft;
+} request;
+
+typedef struct {
+	int error;
+	struct config_tree *cft;
+} response;
+
+struct daemon_state;
+
+/*
+ * The callback. Called once per request issued, in the respective client's
+ * thread. It is presented by a parsed request (in the form of a config tree).
+ * The output is a new config tree that is serialised and sent back to the
+ * client. The client blocks until the request processing is done and reply is
+ * sent.
+ */
+typedef response (*handle_request)(struct daemon_state s, client_handle h, request r);
+
+typedef struct daemon_state {
 	/*
 	 * The maximal stack size for individual daemon threads. This is
 	 * essential for daemons that need to be locked into memory, since
@@ -36,6 +58,9 @@
 	const char *name;
 	const char *pidfile;
 	const char *socket_path;
+	int log_level;
+	handle_request handler;
+	int (*setup_post)(struct daemon_state *st);
 
 	/* Global runtime info maintained by the framework. */
 	int socket_fd;
@@ -43,29 +68,12 @@
 	void *private; /* the global daemon state */
 } daemon_state;
 
-typedef struct {
-	struct config_tree *cft;
-} request;
-
-typedef struct {
-	struct config_tree *cft;
-} response;
-
-/*
- * The callback. Called once per request issued, in the respective client's
- * thread. It is presented by a parsed request (in the form of a config tree).
- * The output is a new config tree that is serialised and sent back to the
- * client. The client blocks until the request processing is done and reply is
- * sent.
- */
-typedef response (*handle_request)(daemon_state s, client_handle h, request r);
-
 /*
  * Start serving the requests. This does all the daemonisation, socket setup
  * work and so on. This function takes over the process, and upon failure, it
  * will terminate execution. It may be called at most once.
  */
-void daemon_start(daemon_state s, handle_request r);
+void daemon_start(daemon_state s);
 
 /*
  * Take over from an already running daemon. This function handles connecting


^ permalink raw reply	[flat|nested] 4+ messages in thread

* LVM2/daemons/common daemon-client.h daemon-ser ...
@ 2011-05-13  8:07 mornfall
  0 siblings, 0 replies; 4+ messages in thread
From: mornfall @ 2011-05-13  8:07 UTC (permalink / raw)
  To: lvm-devel, lvm2-cvs

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	mornfall@sourceware.org	2011-05-13 08:07:29

Added files:
	daemons/common : daemon-client.h daemon-server.h 

Log message:
	First stab at the prototypes of the daemon-common functionality (to be
	eventually shared by dmeventd, lvmetad and clvmd).

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-client.h.diff?cvsroot=lvm2&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.h.diff?cvsroot=lvm2&r1=NONE&r2=1.1

/cvs/lvm2/LVM2/daemons/common/daemon-client.h,v  -->  standard output
revision 1.1
--- LVM2/daemons/common/daemon-client.h
+++ -	2011-05-13 08:07:30.026952000 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DAEMON_COMMON_CLIENT_H
+#define _LVM_DAEMON_COMMON_CLIENT_H
+
+typedef struct {
+	int socket_fd; /* the fd we use to talk to the daemon */
+	int protocol;  /* version of the protocol the daemon uses */
+	char *read_buf;
+} daemon_handle;
+
+typedef struct {
+	const char *path; /* the binary of the daemon */
+	const char *socket; /* path to the comms socket */
+	unsigned autostart:1; /* start the daemon if not running? */
+} daemon_info;
+
+typedef struct {
+	char *request;
+} daemon_request;
+
+typedef struct {
+	int errno; /* 0 for success */
+	char *reply; /* textual reply */
+	struct config_tree *cft; /* parsed reply, if available */
+} daemon_reply;
+
+/*
+ * Open the communication channel to the daemon. If the daemon is not running,
+ * it may be autostarted based on the binary path provided in the info (this
+ * will only happen if autostart is set to true). If the call fails for any
+ * reason, daemon_handle_valid(h) for the response will return false. Otherwise,
+ * the connection is good to start serving requests.
+ */
+daemon_handle daemon_open(daemon_info i);
+
+/*
+ * Send a request to the daemon, waiting for the reply. All communication with
+ * the daemon is synchronous. The function handles the IO details and parses the
+ * response, handling common error conditions. See "daemon_reply" for details.
+ */
+daemon_reply daemon_request(daemon_handle h, daemon_request r);
+
+/* Shut down the communication to the daemon. Compulsory. */
+void daemon_close(daemon_handle h);
+
+#endif
/cvs/lvm2/LVM2/daemons/common/daemon-server.h,v  -->  standard output
revision 1.1
--- LVM2/daemons/common/daemon-server.h
+++ -	2011-05-13 08:07:30.411524000 +0000
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_DAEMON_COMMON_CLIENT_H
+#define _LVM_DAEMON_COMMON_CLIENT_H
+
+typedef struct {
+	int socket_fd; /* the fd we use to talk to the client */
+	pthread_t thread_id;
+	char *read_buf;
+	void *private; /* this holds per-client state */
+} client_handle;
+
+typedef struct {
+	void *private; /* the global daemon state */
+} daemon_state;
+
+typedef struct {
+	struct config_tree *cft;
+} request;
+
+typedef struct {
+	struct config_tree *cft;
+} response;
+
+/*
+ * The callback. Called once per request issued, in the respective client's
+ * thread. It is presented by a parsed request (in the form of a config tree).
+ * The output is a new config tree that is serialised and sent back to the
+ * client. The client blocks until the request processing is done and reply is
+ * sent.
+ */
+typedef response (*handle_request)(daemon_state s, client_handle h, request r);
+
+/*
+ * Start serving the requests. This does all the daemonisation, socket setup
+ * work and so on.
+ */
+void daemon_start(daemon_state s, handle_request r);
+
+/*
+ * Take over from an already running daemon. This function handles connecting
+ * to the running daemon and telling it we are going to take over. The takeover
+ * request may be customised by passing in a non-NULL request.
+ *
+ * The takeover sequence: the old daemon stops accepting new clients, then it
+ * waits until all current client connections are closed. When that happens, it
+ * serializes its current state and sends that as a reply, which is then
+ * returned by this function (therefore, this function won't return until the
+ * previous instance has shut down).
+ *
+ * The daemon, after calling daemon_takeover is expected to set up its
+ * daemon_state using the reply from this function and call daemon_start as
+ * usual.
+ */
+daemon_reply daemon_takeover(daemon_info i, daemon_request r);
+
+/* Call this to request a clean shutdown of the daemon. Async safe. */
+void daemon_stop();
+
+#endif


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-07-18 14:46 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-18 14:46 LVM2/daemons/common daemon-client.h daemon-ser mornfall
  -- strict thread matches above, loose matches on Subject: below --
2011-06-14  2:34 mornfall
2011-05-15 11:02 mornfall
2011-05-13  8:07 mornfall

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).