ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/logger.C
Revision: 1.20
Committed: Mon Oct 12 14:00:57 2009 UTC (14 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_82, rel-2_81
Changes since 1.19: +7 -6 lines
Log Message:
clarify license

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.16 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.11 *
4 root 1.19 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.13 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.11 *
8 root 1.20 * Deliantra is free software: you can redistribute it and/or modify it under
9     * the terms of the Affero GNU General Public License as published by the
10     * Free Software Foundation, either version 3 of the License, or (at your
11     * option) any later version.
12 pippijn 1.11 *
13 root 1.15 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.11 *
18 root 1.20 * You should have received a copy of the Affero GNU General Public License
19     * and the GNU General Public License along with this program. If not, see
20     * <http://www.gnu.org/licenses/>.
21 root 1.13 *
22 root 1.16 * The authors can be reached via e-mail to <support@deliantra.net>
23 pippijn 1.11 */
24 elmex 1.1
25 root 1.12 #include <cstdarg>
26 root 1.17 #include <cstring>
27    
28     #include <vector>
29    
30     #include <sys/uio.h>
31     #include <pthread.h>
32    
33     #include "global.h"
34     #include "dynbuf.h"
35     #include "util.h"
36    
37     struct logline
38     {
39     struct timeval tv;
40     char *buf; // includes PREFIX_LEN garbage bytes
41     int len;
42     int flags;
43     };
44    
45     static SMUTEX(mutex);
46     static SCOND(cond);
47     static int logfd = STDERR_FILENO;
48     static int logsync = 1;
49     static std::vector<logline, slice_allocator<logline> > queue;
50    
51     void set_logfd (int fd)
52     {
53     SMUTEX_LOCK (mutex);
54     logfd = fd < 0 ? STDERR_FILENO : fd;
55     SMUTEX_UNLOCK (mutex);
56     }
57    
58     #define PREFIX_LEN sizeof ("0000-00-00 00:00:00.0000+") - 1
59    
60     static void
61     log_sync (logline &line)
62     {
63 root 1.18 struct tm lt;
64 root 1.17 char pfx [PREFIX_LEN];
65    
66 root 1.18 localtime_r (&line.tv.tv_sec, &lt);
67    
68 root 1.17 sprintf (pfx, "%04d-%02d-%02d %02d:%02d:%02d.%04d",
69 root 1.18 lt.tm_year + 1900,
70     lt.tm_mon + 1,
71     lt.tm_mday,
72     lt.tm_hour,
73     lt.tm_min,
74     lt.tm_sec,
75 root 1.17 (int)(line.tv.tv_usec / 100)
76     );
77    
78     pfx [PREFIX_LEN - 1] = line.flags & logSync ? '=' : ' ';
79    
80     struct iovec iov [2];
81    
82     iov [0].iov_base = pfx;
83     iov [0].iov_len = PREFIX_LEN;
84    
85     char *buf = line.buf;
86    
87     while (char *end = strchr (buf, '\n'))
88     {
89     iov [1].iov_base = buf;
90     iov [1].iov_len = end - buf + 1;
91    
92     writev (STDERR_FILENO, iov, 2);
93     if (logfd != STDERR_FILENO)
94     writev (logfd, iov, 2);
95    
96     buf = end + 1;
97    
98     if (buf == line.buf + line.len)
99     break;
100    
101     pfx [PREFIX_LEN - 1] = '+';
102     }
103    
104     sfree (line.buf, line.len);
105     }
106    
107     static void *
108     logthread_proc (void *arg)
109     {
110     int idx = 0;
111    
112     for (;;)
113     {
114     logline line;
115    
116     SMUTEX_LOCK (mutex);
117    
118     while (queue.empty ())
119     SCOND_WAIT (cond, mutex);
120    
121     line = queue [idx++];
122    
123     // this algorithm could result in an ever-increasing vector
124     // size if we log faster than we can write, but if that happens
125     // we have bigger problems.
126     if (idx == queue.size ())
127     {
128     queue.clear ();
129     idx = 0;
130     }
131    
132     SMUTEX_UNLOCK (mutex);
133    
134     log_sync (line);
135     }
136     }
137    
138     void
139     log_cleanup ()
140     {
141     logsync = 1;
142    
143     for (;;)
144     {
145     int done;
146    
147     SMUTEX_LOCK (mutex);
148     done = queue.empty ();
149     SMUTEX_UNLOCK (mutex);
150    
151     if (done)
152     break;
153    
154     usleep (10000);
155     }
156     }
157    
158     static void
159     af_child ()
160     {
161     logsync = 1;
162     }
163    
164     static struct logthread : thread
165     {
166     logthread ()
167     {
168     pthread_atfork (0, 0, af_child);
169     start (logthread_proc);
170     logsync = 0;
171     }
172     } logthread;
173 elmex 1.1
174 root 1.4 void
175 root 1.12 LOG (int flags, const char *format, ...)
176 elmex 1.1 {
177 root 1.12 int level = flags & 15;
178    
179     if (level > settings.debug)
180     return;
181    
182 root 1.17 logline line;
183     gettimeofday (&line.tv, 0);
184 root 1.12
185 root 1.17 static dynbuf_text buf;
186 root 1.12
187     va_list ap;
188     va_start (ap, format);
189 root 1.17 buf.vprintf (format, ap);
190 root 1.12 va_end (ap);
191    
192 root 1.17 buf << '\n';
193    
194     line.buf = buf.linearise ();
195     line.len = buf.size ();
196 root 1.12
197 root 1.17 if (line.buf [line.len - 2] == '\n')
198     --line.len;
199 root 1.14
200 root 1.17 line.buf = salloc<char> (line.len, line.buf);
201    
202     buf.clear ();
203    
204     if (logsync)
205     flags |= logSync;
206 root 1.12
207     if (flags & logBacktrace)
208 root 1.17 {
209     line.buf [line.len - 1] = 0;
210     log_backtrace (line.buf);
211     line.buf [line.len - 1] = '\n';
212     }
213    
214     line.flags = flags;
215    
216     if (line.flags & logSync)
217     log_sync (line);
218     else
219     {
220     SMUTEX_LOCK (mutex);
221     queue.push_back (line);
222     SMUTEX_UNLOCK (mutex);
223     SCOND_SIGNAL (cond);
224     }
225 elmex 1.1 }
226 root 1.17