summaryrefslogtreecommitdiffstats
path: root/libdaemon/server/daemon-server.h
blob: df7ed8e056e7961d751c326d2c2a2cc4a6d32ca5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * Copyright (C) 2011-2012 Red Hat, Inc.
 *
 * 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_SERVER_H
#define _LVM_DAEMON_COMMON_SERVER_H

#include "daemon-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 {
	struct dm_config_tree *cft;
	char *buffer;
} request;

typedef struct {
	int error;
	struct dm_config_tree *cft;
	char *buffer;
} response;

struct daemon_state;

/*
 * Craft a simple reply, without the need to construct a config_tree. See
 * daemon_send_simple in daemon-client.h for the description of the parameters.
 */
response daemon_reply_simple(const char *id, ...);

static inline int daemon_request_int(request r, const char *path, int def) {
	if (!r.cft)
		return def;
	return dm_config_find_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 dm_config_find_str(r.cft->root, path, def);
}

/*
 * 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 {
	uint32_t log_config[32];
	void *backend_state[32];
	const char *name;
} log_state;

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
	 * pthread's default is 10M per thread.
	 */
	int thread_stack_size;

	/* Flags & attributes affecting the behaviour of the daemon. */
	unsigned avoid_oom:1;
	unsigned foreground:1;
	const char *name;
	const char *pidfile;
	const char *socket_path;
	const char *protocol;
	int protocol_version;

	handle_request handler;
	int (*daemon_init)(struct daemon_state *st);
	int (*daemon_fini)(struct daemon_state *st);

	/* Global runtime info maintained by the framework. */
	int socket_fd;

	log_state *log;
	void *private; /* the global daemon state */
} daemon_state;

/*
 * 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);

/*
 * 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(void);

enum { DAEMON_LOG_OUTLET_SYSLOG = 1,
       DAEMON_LOG_OUTLET_STDERR = 2,
       DAEMON_LOG_OUTLET_SOCKET = 4 };

/* Log a message of a given type. */
void daemon_log(log_state *s, int type, const char *message);

/* Log a config (sub)tree, using a given message type, each line prefixed with "prefix". */
void daemon_log_cft(log_state *s, int type, const char *prefix,
                    const struct dm_config_node *n);

/* Log a multi-line block, prefixing each line with "prefix". */
void daemon_log_multi(log_state *s, int type, const char *prefix, const char *message);

/* Log a formatted message as "type". See also daemon-log.h. */
void daemon_logf(log_state *s, int type, const char *format, ...);

/*
 * Configure log_state to send messages of type "type" to the log outlet
 * "outlet", iff "enable" is true.
 */
void daemon_log_enable(log_state *s, int outlet, int type, int enable);

/*
 * Set up logging on a given outlet using a list of message types (comma
 * separated) to log using that outlet. The list is expected to look like this,
 * "info,wire,debug". Returns 0 upon encountering an unknown message type.
 */
int daemon_log_parse(log_state *s, int outlet, const char *types, int enable);

#endif