static struct connection_list *anvil_connections;
static HASH_TABLE(struct anvil_connection_key *, struct anvil_connection *)
anvil_connections_hash;
+static unsigned int anvil_global_kick_count = 0;
+static unsigned int anvil_global_cmd_counter = 0;
+static unsigned int anvil_global_connect_dump_count = 0;
static void anvil_connection_destroy(struct connection *_conn);
unsigned int count;
i_assert(kick->cmd_refcount > 0);
+ i_assert(anvil_global_kick_count > 0);
+ anvil_global_kick_count--;
+ anvil_refresh_proctitle_delayed();
if (error != NULL)
;
else if (reply[0] == '+' && str_to_uint(reply+1, &count) == 0)
guid_128_to_string(result.conn_guid));
}
+ anvil_global_kick_count++;
kick->cmd_refcount++;
admin_cmd_send(result.service, result.pid, str_c(cmd),
kick_user_callback, kick);
time_t stamp;
pid_t pid;
+ anvil_global_cmd_counter++;
+ anvil_refresh_proctitle_delayed();
+
args++;
if (strcmp(cmd, "CONNECT") == 0) {
if (args[0] == NULL || args[1] == NULL) {
}
connect_limit_disconnect(connect_limit, pid, &key, conn_guid);
} else if (strcmp(cmd, "CONNECT-DUMP") == 0) {
+ anvil_global_connect_dump_count++;
connect_limit_dump(connect_limit, conn->conn.output);
} else if (strcmp(cmd, "KICK-USER") == 0) {
if (args[0] == NULL) {
cmd->context = context;
}
+void anvil_get_global_counts(unsigned int *connection_count_r,
+ unsigned int *kicks_pending_count_r,
+ unsigned int *cmd_counter_r,
+ unsigned int *connect_dump_counter_r)
+{
+ *connection_count_r = anvil_connections->connections_count;
+ *kicks_pending_count_r = anvil_global_kick_count;
+ *cmd_counter_r = anvil_global_cmd_counter;
+ *connect_dump_counter_r = anvil_global_connect_dump_count;
+}
+
static struct connection_settings anvil_connections_set = {
.dont_send_version = TRUE,
.input_max_size = MAX_INBUF_SIZE,
#include "common.h"
#include "array.h"
+#include "str.h"
#include "env-util.h"
#include "fdpass.h"
#include "ioloop.h"
+#include "process-title.h"
#include "restrict-access.h"
#include "master-service.h"
#include "master-service-settings.h"
#include <unistd.h>
#define ANVIL_CLIENT_POOL_MAX_CONNECTIONS 100
+#define ANVIL_PROCTITLE_REFRESH_INTERVAL_MSECS 1000
struct connect_limit *connect_limit;
struct penalty *penalty;
bool anvil_restarted;
+static bool verbose_proctitle = FALSE;
static struct io *log_fdpass_io;
static struct admin_client_pool *admin_pool;
+static struct timeout *to_refresh;
+static unsigned int prev_cmd_counter = 0;
+static unsigned int prev_connect_dump_counter = 0;
+
+static void anvil_refresh_proctitle(void *context ATTR_UNUSED)
+{
+ unsigned int connections_count;
+ unsigned int kicks_pending_count;
+ unsigned int cmd_counter, cmd_diff;
+ unsigned int connect_dump_counter, connect_dump_diff;
+ anvil_get_global_counts(&connections_count, &kicks_pending_count,
+ &cmd_counter, &connect_dump_counter);
+ if (cmd_counter >= prev_cmd_counter)
+ cmd_diff = cmd_counter - prev_cmd_counter;
+ else {
+ /* wrapped */
+ cmd_diff = (UINT_MAX - prev_cmd_counter + 1) + cmd_counter;
+ }
+ if (connect_dump_counter >= prev_connect_dump_counter) {
+ connect_dump_diff = connect_dump_counter -
+ prev_connect_dump_counter;
+ } else {
+ /* wrapped */
+ connect_dump_diff = (UINT_MAX - prev_connect_dump_counter + 1) +
+ connect_dump_counter;
+ }
+ prev_cmd_counter = cmd_counter;
+ prev_connect_dump_counter = connect_dump_counter;
+
+ process_title_set(t_strdup_printf(
+ "[%u connections, %u requests, %u user-lists, %u user-kicks]",
+ connections_count, cmd_diff,
+ connect_dump_diff, kicks_pending_count));
+
+ if (cmd_diff == 0 && connect_dump_diff == 0 && kicks_pending_count == 0)
+ timeout_remove(&to_refresh);
+}
+
+void anvil_refresh_proctitle_delayed(void)
+{
+ if (!verbose_proctitle)
+ return;
+
+ if (to_refresh != NULL)
+ return;
+ to_refresh = timeout_add(ANVIL_PROCTITLE_REFRESH_INTERVAL_MSECS,
+ anvil_refresh_proctitle, NULL);
+}
#undef admin_cmd_send
void admin_cmd_send(const char *service, pid_t pid, const char *cmd,
/* delay dying until all of our clients are gone */
master_service_set_die_with_master(master_service, FALSE);
+ verbose_proctitle = set->verbose_proctitle;
anvil_restarted = getenv("ANVIL_RESTARTED") != NULL;
anvil_connections_init();
admin_clients_init();
admin_client_pool_deinit(&admin_pool);
admin_clients_deinit();
anvil_connections_deinit();
+ timeout_remove(&to_refresh);
}
int main(int argc, char *argv[])
{
const enum master_service_flags service_flags =
- MASTER_SERVICE_FLAG_DONT_SEND_STATS |
- MASTER_SERVICE_FLAG_UPDATE_PROCTITLE;
+ MASTER_SERVICE_FLAG_DONT_SEND_STATS;
const char *error;
master_service = master_service_init("anvil", service_flags,