--- deliantra/server/common/logger.C 2008/05/06 16:55:25 1.19 +++ deliantra/server/common/logger.C 2010/04/29 07:32:34 1.26 @@ -1,22 +1,21 @@ /* * 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 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 GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 GNU General Public License - * along with this program. If not, see . + * 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 */ @@ -41,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 ? '=' : ' '; @@ -83,6 +90,9 @@ char *buf = line.buf; + if (logsync != 2) + SMUTEX_LOCK (fdlock); + while (char *end = strchr (buf, '\n')) { iov [1].iov_base = buf; @@ -100,6 +110,9 @@ pfx [PREFIX_LEN - 1] = '+'; } + if (logsync != 2) + SMUTEX_UNLOCK (fdlock); + sfree (line.buf, line.len); } @@ -124,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; } @@ -138,6 +155,7 @@ log_cleanup () { logsync = 1; + SMUTEX_UNLOCK (fdlock); for (;;) { @@ -151,13 +169,15 @@ break; usleep (10000); + SMUTEX_LOCK (fdlock); + SMUTEX_UNLOCK (fdlock); } } static void af_child () { - logsync = 1; + logsync = 2; } static struct logthread : thread @@ -171,7 +191,7 @@ } logthread; void -LOG (int flags, const char *format, ...) +LOG (int flags, const_utf8_string format, ...) { int level = flags & 15; @@ -223,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."); + } +} +