This allows asking for services' current status in master process.
static struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
&doveadm_cmd_service_stop_ver2,
+ &doveadm_cmd_service_status_ver2,
&doveadm_cmd_stop_ver2,
&doveadm_cmd_reload_ver2,
&doveadm_cmd_stats_dump_ver2,
void doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv);
extern struct doveadm_cmd_ver2 doveadm_cmd_service_stop_ver2;
+extern struct doveadm_cmd_ver2 doveadm_cmd_service_status_ver2;
extern struct doveadm_cmd_ver2 doveadm_cmd_stop_ver2;
extern struct doveadm_cmd_ver2 doveadm_cmd_reload_ver2;
extern struct doveadm_cmd_ver2 doveadm_cmd_stats_reset_ver2;
#include "istream.h"
#include "write-full.h"
#include "doveadm.h"
+#include "doveadm-print.h"
#include <unistd.h>
#include <fcntl.h>
i_stream_destroy(&input);
}
+static void cmd_service_status(struct doveadm_cmd_context *cctx)
+{
+ const char *line, *const *services;
+
+ if (!doveadm_cmd_param_array(cctx, "service", &services))
+ services = NULL;
+
+ struct istream *input = master_service_send_cmd("SERVICE-STATUS");
+
+ doveadm_print_init("pager");
+ doveadm_print_header_simple("name");
+ doveadm_print_header_simple("process_count");
+ doveadm_print_header_simple("process_avail");
+ doveadm_print_header_simple("process_limit");
+ doveadm_print_header_simple("client_limit");
+ doveadm_print_header_simple("throttle_secs");
+ doveadm_print_header_simple("exit_failure_last");
+ doveadm_print_header_simple("exit_failures_in_sec");
+ doveadm_print_header_simple("last_drop_warning");
+ doveadm_print_header_simple("listen_pending");
+ doveadm_print_header_simple("listening");
+
+ alarm(5);
+ while ((line = i_stream_read_next_line(input)) != NULL) {
+ if (line[0] == '\0')
+ break;
+ T_BEGIN {
+ const char *const *args = t_strsplit_tabescaped(line);
+ if (str_array_length(args) >= 11 &&
+ (services == NULL ||
+ str_array_find(services, args[0]))) {
+ for (unsigned int i = 0; i < 11; i++)
+ doveadm_print(args[i]);
+ }
+ } T_END;
+ }
+ if (line == NULL) {
+ i_error("read(%s) failed: %s", i_stream_get_name(input),
+ i_stream_get_error(input));
+ doveadm_exit_code = EX_TEMPFAIL;
+ }
+ alarm(0);
+ i_stream_destroy(&input);
+}
+
struct doveadm_cmd_ver2 doveadm_cmd_stop_ver2 = {
.old_cmd = cmd_stop,
.name = "stop",
DOVEADM_CMD_PARAM('\0', "service", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
DOVEADM_CMD_PARAMS_END
};
+
+struct doveadm_cmd_ver2 doveadm_cmd_service_status_ver2 = {
+ .cmd = cmd_service_status,
+ .name = "service status",
+ .usage = "[<service> [...]]",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('\0', "service", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+};
/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */
#include "common.h"
+#include "array.h"
+#include "str.h"
+#include "strescape.h"
#include "ostream.h"
#include "connection.h"
#include "service.h"
struct connection conn;
};
+static void
+master_client_service_status_output(string_t *str,
+ const struct service *service)
+{
+ str_append_tabescaped(str, service->set->name);
+ str_printfa(str, "\t%u\t%u\t%u\t%u\t%u\t%ld\t%u\t%ld\t%c\t%c\n",
+ service->process_count, service->process_avail,
+ service->process_limit, service->client_limit,
+ service->to_throttle == NULL ? 0 : service->throttle_secs,
+ (long)service->exit_failure_last,
+ service->exit_failures_in_sec,
+ (long)service->last_drop_warning,
+ service->listen_pending ? 'y' : 'n',
+ service->listening ? 'y' : 'n');
+}
+
+static int
+master_client_service_status(struct master_client *client)
+{
+ struct service *const *servicep;
+ string_t *str = t_str_new(128);
+
+ array_foreach(&services->services, servicep) {
+ str_truncate(str, 0);
+ master_client_service_status_output(str, *servicep);
+ o_stream_nsend(client->conn.output, str_data(str), str_len(str));
+ }
+ o_stream_nsend_str(client->conn.output, "\n");
+ return 1;
+}
+
static int
master_client_stop(struct master_client *client, const char *const *args)
{
}
args++;
+ if (strcmp(cmd, "SERVICE-STATUS") == 0)
+ return master_client_service_status(client);
if (strcmp(cmd, "STOP") == 0)
return master_client_stop(client, args);
i_error("%s: Unknown command: %s", conn->name, cmd);