transmission 2.83
[tomato.git] / release / src-rt-6.x.4708 / router / transmission / libtransmission / log.c
blob096a55952bc8b9bcdf31f0cdabe1836508fb0492
1 /*
2 * This file Copyright (C) 2010-2014 Mnemosyne LLC
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
7 * $Id: utils.c 13863 2013-01-24 23:59:52Z jordan $
8 */
10 #include <assert.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h> /* getenv() */
15 #include <event2/buffer.h>
17 #include "transmission.h"
18 #include "log.h"
19 #include "platform.h" /* tr_lock */
20 #include "utils.h"
22 tr_log_level __tr_message_level = TR_LOG_ERROR;
24 static bool myQueueEnabled = false;
25 static tr_log_message * myQueue = NULL;
26 static tr_log_message ** myQueueTail = &myQueue;
27 static int myQueueLength = 0;
29 #ifndef WIN32
30 /* make null versions of these win32 functions */
31 static inline int IsDebuggerPresent (void) { return false; }
32 static inline void OutputDebugStringA (const void * unused UNUSED) { }
33 #endif
35 /***
36 ****
37 ***/
39 tr_log_level
40 tr_logGetLevel (void)
42 return __tr_message_level;
45 /***
46 ****
47 ***/
49 static tr_lock*
50 getMessageLock (void)
52 static tr_lock * l = NULL;
54 if (!l)
55 l = tr_lockNew ();
57 return l;
60 void*
61 tr_logGetFile (void)
63 static bool initialized = false;
64 static FILE * file = NULL;
66 if (!initialized)
68 int fd = 0;
69 const char * str = getenv ("TR_DEBUG_FD");
71 if (str && *str)
72 fd = atoi (str);
74 switch (fd)
76 case 1:
77 file = stdout;
78 break;
80 case 2:
81 file = stderr;
82 break;
84 default:
85 file = NULL;
86 break;
89 initialized = true;
92 return file;
95 void
96 tr_logSetLevel (tr_log_level level)
98 __tr_message_level = level;
101 void
102 tr_logSetQueueEnabled (bool isEnabled)
104 assert (tr_isBool (isEnabled));
106 myQueueEnabled = isEnabled;
109 bool
110 tr_logGetQueueEnabled (void)
112 return myQueueEnabled;
115 tr_log_message *
116 tr_logGetQueue (void)
118 tr_log_message * ret;
119 tr_lockLock (getMessageLock ());
121 ret = myQueue;
122 myQueue = NULL;
123 myQueueTail = &myQueue;
124 myQueueLength = 0;
126 tr_lockUnlock (getMessageLock ());
127 return ret;
130 void
131 tr_logFreeQueue (tr_log_message * list)
133 tr_log_message * next;
135 while (NULL != list)
137 next = list->next;
138 free (list->message);
139 free (list->name);
140 free (list);
141 list = next;
149 char*
150 tr_logGetTimeStr (char * buf, int buflen)
152 char tmp[64];
153 struct tm now_tm;
154 struct timeval tv;
155 time_t seconds;
156 int milliseconds;
158 tr_gettimeofday (&tv);
160 seconds = tv.tv_sec;
161 tr_localtime_r (&seconds, &now_tm);
162 strftime (tmp, sizeof (tmp), "%Y-%m-%d %H:%M:%S.%%03d %Z", &now_tm);
163 milliseconds = tv.tv_usec / 1000;
164 tr_snprintf (buf, buflen, tmp, milliseconds);
166 return buf;
169 bool
170 tr_logGetDeepEnabled (void)
172 static int8_t deepLoggingIsActive = -1;
174 if (deepLoggingIsActive < 0)
175 deepLoggingIsActive = IsDebuggerPresent () || (tr_logGetFile ()!=NULL);
177 return deepLoggingIsActive != 0;
180 void
181 tr_logAddDeep (const char * file,
182 int line,
183 const char * name,
184 const char * fmt,
185 ...)
187 FILE * fp = tr_logGetFile ();
188 if (fp || IsDebuggerPresent ())
190 va_list args;
191 char timestr[64];
192 char * message;
193 struct evbuffer * buf = evbuffer_new ();
194 char * base = tr_basename (file);
196 evbuffer_add_printf (buf, "[%s] ",
197 tr_logGetTimeStr (timestr, sizeof (timestr)));
198 if (name)
199 evbuffer_add_printf (buf, "%s ", name);
200 va_start (args, fmt);
201 evbuffer_add_vprintf (buf, fmt, args);
202 va_end (args);
203 evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
204 /* FIXME (libevent2) ifdef this out for nonwindows platforms */
205 message = evbuffer_free_to_str (buf);
206 OutputDebugStringA (message);
207 if (fp)
208 fputs (message, fp);
210 tr_free (message);
211 tr_free (base);
215 /***
216 ****
217 ***/
219 void
220 tr_logAddMessage (const char * file,
221 int line,
222 tr_log_level level,
223 const char * name,
224 const char * fmt,
225 ...)
227 const int err = errno; /* message logging shouldn't affect errno */
228 char buf[1024];
229 va_list ap;
230 tr_lockLock (getMessageLock ());
232 /* build the text message */
233 *buf = '\0';
234 va_start (ap, fmt);
235 evutil_vsnprintf (buf, sizeof (buf), fmt, ap);
236 va_end (ap);
238 OutputDebugStringA (buf);
240 if (*buf)
242 if (tr_logGetQueueEnabled ())
244 tr_log_message * newmsg;
245 newmsg = tr_new0 (tr_log_message, 1);
246 newmsg->level = level;
247 newmsg->when = tr_time ();
248 newmsg->message = tr_strdup (buf);
249 newmsg->file = file;
250 newmsg->line = line;
251 newmsg->name = tr_strdup (name);
253 *myQueueTail = newmsg;
254 myQueueTail = &newmsg->next;
255 ++myQueueLength;
257 if (myQueueLength > TR_LOG_MAX_QUEUE_LENGTH)
259 tr_log_message * old = myQueue;
260 myQueue = old->next;
261 old->next = NULL;
262 tr_logFreeQueue (old);
263 --myQueueLength;
264 assert (myQueueLength == TR_LOG_MAX_QUEUE_LENGTH);
267 else
269 FILE * fp;
270 char timestr[64];
272 fp = tr_logGetFile ();
273 if (fp == NULL)
274 fp = stderr;
276 tr_logGetTimeStr (timestr, sizeof (timestr));
278 if (name)
279 fprintf (fp, "[%s] %s: %s\n", timestr, name, buf);
280 else
281 fprintf (fp, "[%s] %s\n", timestr, buf);
282 fflush (fp);
286 tr_lockUnlock (getMessageLock ());
287 errno = err;