#include "main.hpp"
CONF_DEF(config) {
ConfigKey port;
};
CONF_INIT(config) {
CONF_KEY_INIT(port, false, 4444);
}
static Config* global_config = NULL;
const int* main_fd = NULL;
int main(int argc, char **argv) {
EINTR_RETRY(close(STDIN_FILENO));
EINTR_RETRY(close(STDOUT_FILENO));
if (argc != 2) {
STDERR("Usage: %s <config-file>", argv[0]);
return 1;
}
Hooks::run(Hooks::INIT);
global_config = new Config(argv[1]);
if (!global_config->load()) {
log(error, "cannot load config '%s'", argv[1]);
delete global_config;
Hooks::run(Hooks::DEINIT);
return 1;
}
log(notice, "loaded config '%s'", argv[1]);
Hooks::run(Hooks::PRE_IO);
// open main socket
int fd = config? socket_listen(config->port.val.num): -1;
main_fd = &fd;
if (fd == -1) {
delete global_config;
Hooks::run(Hooks::DEINIT);
return 1;
}
// init
Poll* poll = Poll::getInst();
poll->add(fd, &CtxAcceptor::accept_handler, EVENT_IN|EVENT_CLOSE);
// main loop
time_t shutdown_at = 0;
shutdown_e shutdown_last = SHUTDOWN_NONE;
while (true) {
if (unlikely(SHUTDOWN)) {
if (fd != -1) { // closing main fd in any case (once)
log(info, "won't accept new connections");
poll->del(fd);
EINTR_RETRY(close(fd));
fd = -1;
}
if (!poll->refcount()) { // already everything closed?
break;
}
if (!shutdown_at) { // first encounter
shutdown_at = NOW;
}
if (SHUTDOWN == SHUTDOWN_GRACEFUL && shutdown_at < NOW-3) { // escalate after 3 secs
SHUTDOWN = SHUTDOWN_NOW;
}
if (SHUTDOWN == SHUTDOWN_NOW && shutdown_at < NOW-10) { // waited long enough
break;
}
if (SHUTDOWN != shutdown_last) { // broadcast if shutdown condition changed
shutdown_last = SHUTDOWN;
poll->wakeup();
}
} else if (unlikely(RECONFIGURE)) {
log(notice, "triggering config reload...");
reconfigure(global_config);
RECONFIGURE = 0;
CLEANUP = 0; // implicitly done upon config change
} else if (unlikely(CLEANUP)) {
log(notice, "triggering cache clean...");
Hooks::run(Hooks::CACHE_CLEAN);
CLEANUP = 0;
}
poll->wait(1000);
}
// done.
log(notice, "shutting down");
Hooks::run(Hooks::POST_IO); // joins pending config aios, pollers, etc
delete global_config;
Hooks::run(Hooks::DEINIT);
}