From 94bbdce6b742ab2f62cfa9513e13f27a0f78973b Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Mon, 22 Jun 2020 01:41:52 +0200 Subject: Split idle into top-level task and per-server tasks --- server.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 5 deletions(-) (limited to 'server.c') diff --git a/server.c b/server.c index 4a45b53..145bcf9 100644 --- a/server.c +++ b/server.c @@ -56,11 +56,11 @@ server_refdump(struct server *server) uring_task_refdump(&server->task); uring_task_refdump(&server->exec_task); uring_task_refdump(&server->ann_task); + uring_task_refdump(&server->idle_task); list_for_each_entry(local, &server->locals, list) uring_task_refdump(&local->task); list_for_each_entry(proxy, &server->proxys, list) proxy_refdump(proxy); - idle_refdump(server->idle); rcon_refdump(server->rcon); } @@ -98,7 +98,6 @@ server_delete(struct cfg *cfg, struct server *server) verbose("Removing server %s", server->name); server->state = SERVER_STATE_DEAD; - idle_delete(cfg, server); rcon_delete(cfg, server); list_for_each_entry_safe(local, ltmp, &server->locals, list) @@ -120,6 +119,7 @@ server_delete(struct cfg *cfg, struct server *server) list_for_each_entry_safe(dns, dtmp, &server->dnslookups, list) gai_cancel(&dns->gcb); + uring_task_destroy(cfg, &server->idle_task); uring_poll_cancel(cfg, &server->exec_task); uring_task_put(cfg, &server->exec_task); uring_task_destroy(cfg, &server->task); @@ -363,7 +363,7 @@ server_exec(struct cfg *cfg, struct server *server, const char *cmd) CLONE_VM | CLONE_VFORK | CLONE_PIDFD | SIGCHLD, (void *)cmd, &pidfd); if (r != 0) { - error("clone: %m"); + error("clone: %m: %i", r); return false; } @@ -456,6 +456,84 @@ server_stop(struct cfg *cfg, struct server *server) return false; } +static void +server_idle_free(struct uring_task *task) +{ + assert_return(task); + + debug(DBG_ANN, "called"); +} + +void +server_set_active_players(struct cfg *cfg, struct server *server, int count) +{ + assert_return(cfg && server); + assert_task_alive(DBG_IDLE, &server->idle_task); + + debug(DBG_IDLE, "%s: currently %i active players", + server->name, count); + + if (count < 0) + return; + + server->state = SERVER_STATE_RUNNING; + if (count > 0) + server->idle_count = 0; + else if (count == 0) + server->idle_count++; + + if (server->idle_count > server->idle_timeout) { + verbose("stopping idle server %s", server->name); + server_stop(cfg, server); + } +} + +static void +server_idle_connected_cb(struct cfg *cfg, struct connection *conn, bool connected) +{ + struct server *server = container_of(conn, struct server, idle_conn); + + assert_return(cfg && conn); + assert_task_alive(DBG_IDLE, &server->idle_task); + + if (!connected) { + debug(DBG_IDLE, + "idle check connection to remote server (%s) failed", + server->name); + server->idle_count = 0; + server->state = SERVER_STATE_STOPPED; + return; + } + + debug(DBG_IDLE, "connected to remote %s\n", conn->remote.addrstr); + idle_check_get_player_count(cfg, server, conn); +} + +bool +server_idle_check(struct cfg *cfg, struct server *server) +{ + assert_return(cfg && server, false); + + if (server->state == SERVER_STATE_INIT || + server->state == SERVER_STATE_DEAD) + return false; + + if (server->idle_timeout < 1) + return false; + + if (list_empty(&server->remotes)) + return false; + + if (!list_empty(&server->proxys)) { + server->idle_count = 0; + return true; + } + + connect_any(cfg, &server->idle_task, &server->remotes, + &server->idle_conn, server_idle_connected_cb); + return true; +} + static void server_announce_free(struct uring_task *task) { @@ -658,7 +736,6 @@ server_commit(struct cfg *cfg, struct server *server) server_local_open(cfg, server, local); } - idle_init(cfg, server); server->state = SERVER_STATE_CFG_OK; server_check_running(cfg, server); @@ -856,18 +933,25 @@ server_new(struct cfg *cfg, const char *name) server->name = xstrdup(name); server->stop_method = SERVER_STOP_METHOD_UNDEFINED; server->start_method = SERVER_START_METHOD_UNDEFINED; + server->idle_timeout = 0; + uring_task_init(cfg, &server->task, "server", uring_parent(cfg), server_free); uring_task_set_buf(&server->task, &server->tbuf); + uring_task_init(cfg, &server->ann_task, "announce", &server->task, server_announce_free); uring_task_set_buf(&server->ann_task, &server->ann_buf); saddr_set_ipv4(&server->ann_task.saddr, cinet_addr(224,0,2,60), htons(4445)); + uring_task_init(cfg, &server->exec_task, "exec", &server->task, server_exec_free); + + uring_task_init(cfg, &server->idle_task, "idle", &server->task, server_idle_free); + uring_task_set_buf(&server->idle_task, &server->idle_buf); + list_init(&server->remotes); list_init(&server->locals); list_init(&server->proxys); list_init(&server->rcons); list_init(&server->dnslookups); - server->idle_timeout = 0; list_add(&server->list, &cfg->servers); return server; -- cgit v1.2.3