--- deliantra/server/common/logger.C 2009/10/12 14:00:57 1.20
+++ deliantra/server/common/logger.C 2012/10/29 23:55:52 1.29
@@ -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 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.");
+ }
+}
+