--- deliantra/server/common/logger.C 2009/10/12 14:00:57 1.20 +++ deliantra/server/common/logger.C 2016/11/16 23:41:59 1.30 @@ -1,24 +1,22 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. - * - * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team - * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team - * Copyright (©) 1992,2007 Frank Tore Johansen - * + * + * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * * Deliantra is free software: you can redistribute it and/or modify it under * the terms of the Affero GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the Affero GNU General Public License * and the GNU General Public License along with this program. If not, see * . - * + * * The authors can be reached via e-mail to */ @@ -42,37 +40,45 @@ int flags; }; +typedef std::vector > logvector; + static SMUTEX(mutex); +static SMUTEX(fdlock); static SCOND(cond); static int logfd = STDERR_FILENO; static int logsync = 1; -static std::vector > queue; +static logvector queue; -void set_logfd (int fd) +int log_setfd (int fd) { - SMUTEX_LOCK (mutex); + SMUTEX_LOCK (fdlock); + int old = logfd; logfd = fd < 0 ? STDERR_FILENO : fd; - SMUTEX_UNLOCK (mutex); + SMUTEX_UNLOCK (fdlock); + + return old; } -#define PREFIX_LEN sizeof ("0000-00-00 00:00:00.0000+") - 1 +#define PREFIX_LEN sizeof ("0000-00-00 00:00:00.0000 L+") - 1 static void log_sync (logline &line) { + static const char levelchar [16+1] = "EWIDt???????????"; struct tm lt; char pfx [PREFIX_LEN]; localtime_r (&line.tv.tv_sec, <); - sprintf (pfx, "%04d-%02d-%02d %02d:%02d:%02d.%04d", + sprintf (pfx, "%04d-%02d-%02d %02d:%02d:%02d.%04d %c", lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec, - (int)(line.tv.tv_usec / 100) + (int)(line.tv.tv_usec / 100), + levelchar [line.flags & 15] ); pfx [PREFIX_LEN - 1] = line.flags & logSync ? '=' : ' '; @@ -84,6 +90,9 @@ char *buf = line.buf; + if (logsync != 2) + SMUTEX_LOCK (fdlock); + while (char *end = strchr (buf, '\n')) { iov [1].iov_base = buf; @@ -101,6 +110,9 @@ pfx [PREFIX_LEN - 1] = '+'; } + if (logsync != 2) + SMUTEX_UNLOCK (fdlock); + sfree (line.buf, line.len); } @@ -125,7 +137,11 @@ // we have bigger problems. if (idx == queue.size ()) { - queue.clear (); + if (idx < 32) + queue.clear (); + else + logvector ().swap (queue); // free memory, hopefully + idx = 0; } @@ -139,6 +155,7 @@ log_cleanup () { logsync = 1; + SMUTEX_UNLOCK (fdlock); for (;;) { @@ -152,13 +169,15 @@ break; usleep (10000); + SMUTEX_LOCK (fdlock); + SMUTEX_UNLOCK (fdlock); } } static void af_child () { - logsync = 1; + logsync = 2; } static struct logthread : thread @@ -172,7 +191,7 @@ } logthread; void -LOG (int flags, const char *format, ...) +LOG (int flags, const_utf8_string format, ...) { int level = flags & 15; @@ -224,3 +243,25 @@ } } +static int suspended; + +void +log_suspend () +{ + if (!suspended++) + { + LOG (llevDebug, "logging suspended."); + SMUTEX_LOCK (fdlock); + } +} + +void +log_resume () +{ + if (!--suspended) + { + SMUTEX_UNLOCK (fdlock); + LOG (llevDebug, "logging resumed."); + } +} +