]> git.cworth.org Git - apitrace/blob - log.cpp
Time call durations.
[apitrace] / log.cpp
1 /****************************************************************************
2  *
3  * Copyright 2008-2009 VMware, Inc.
4  *
5  * This program is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  ****************************************************************************/
19
20
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <windows.h>
27
28 #include <zlib.h>
29
30 #include "log.hpp"
31
32
33 #ifdef WIN32
34 #ifndef PATH_MAX
35 #define PATH_MAX _MAX_PATH
36 #endif
37 #ifndef snprintf
38 #define snprintf _snprintf
39 #endif
40 #ifndef vsnprintf
41 #define vsnprintf _vsnprintf
42 #endif
43 #endif
44
45
46 namespace Log {
47
48
49 static gzFile g_gzFile = NULL;
50 static char g_szFileName[PATH_MAX];
51 static CRITICAL_SECTION CriticalSection;
52
53 static void _Close(void) {
54     if(g_gzFile != NULL) {
55         gzclose(g_gzFile);
56         g_gzFile = NULL;
57         DeleteCriticalSection(&CriticalSection);
58     }
59 }
60
61 static void _Open(const char *szName, const char *szExtension) {
62     _Close();
63     
64     static unsigned dwCounter = 0;
65
66     for(;;) {
67         FILE *file;
68         
69         if(dwCounter)
70             snprintf(g_szFileName, PATH_MAX, "%s.%u.%s.gz", szName, dwCounter, szExtension);
71         else
72             snprintf(g_szFileName, PATH_MAX, "%s.%s.gz", szName, szExtension);
73         
74         file = fopen(g_szFileName, "rb");
75         if(file == NULL)
76             break;
77         
78         fclose(file);
79         
80         ++dwCounter;
81     }
82
83     g_gzFile = gzopen(g_szFileName, "wb");
84     InitializeCriticalSection(&CriticalSection);
85 }
86
87 static inline void _ReOpen(void) {
88     /* XXX */
89 }
90
91 static inline void Write(const char *sBuffer, size_t dwBytesToWrite) {
92     if(g_gzFile == NULL)
93         return;
94     
95     gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
96 }
97
98 static inline void Write(const char *szText) {
99     Write(szText, strlen(szText));
100 }
101
102 static inline void 
103 Escape(const char *s) {
104     /* FIXME */
105     Write(s);
106 }
107
108 static inline void 
109 Indent(unsigned level) {
110     for(unsigned i = 0; i < level; ++i)
111         Write("\t");
112 }
113
114 static inline void 
115 NewLine(void) {
116     Write("\r\n");
117 }
118
119 static inline void 
120 Tag(const char *name) {
121     Write("<");
122     Write(name);
123     Write("/>");
124 }
125
126 static inline void 
127 BeginTag(const char *name) {
128     Write("<");
129     Write(name);
130     Write(">");
131 }
132
133 static inline void 
134 BeginTag(const char *name, 
135          const char *attr1, const char *value1) {
136     Write("<");
137     Write(name);
138     Write(" ");
139     Write(attr1);
140     Write("=\"");
141     Escape(value1);
142     Write("\">");
143 }
144
145 static inline void 
146 BeginTag(const char *name, 
147          const char *attr1, const char *value1,
148          const char *attr2, const char *value2) {
149     Write("<");
150     Write(name);
151     Write(" ");
152     Write(attr1);
153     Write("=\"");
154     Escape(value1);
155     Write("\" ");
156     Write(attr2);
157     Write("=\"");
158     Escape(value2);
159     Write("\">");
160 }
161
162 static inline void 
163 BeginTag(const char *name, 
164               const char *attr1, const char *value1,
165               const char *attr2, const char *value2,
166               const char *attr3, const char *value3) {
167     Write("<");
168     Write(name);
169     Write(" ");
170     Write(attr1);
171     Write("=\"");
172     Escape(value1);
173     Write("\" ");
174     Write(attr2);
175     Write("=\"");
176     Escape(value2);
177     Write("\" ");
178     Write(attr3);
179     Write("=\"");
180     Escape(value3);
181     Write("\">");
182 }
183
184 static inline void
185 EndTag(const char *name) {
186     Write("</");
187     Write(name);
188     Write(">");
189 }
190
191 void Open(const char *name) {
192     _Open(name, "xml");
193     Write("<?xml version='1.0' encoding='UTF-8'?>");
194     NewLine();
195     Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
196     NewLine();
197     BeginTag("trace");
198     NewLine();
199 }
200
201 void ReOpen(void) {
202     _ReOpen();
203 }
204
205 void Close(void) {
206     EndTag("trace");
207     NewLine();
208     _Close();
209 }
210
211 void Text(const char *text) {
212     Escape(text);
213 }
214
215 static void TextChar(char c) {
216     char szText[2];
217     szText[0] = c;
218     szText[1] = 0;
219     Text(szText);
220 }
221
222 void TextF(const char *format, ...) {
223     char szBuffer[4196];
224     va_list ap;
225     va_start(ap, format);
226     vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
227     va_end(ap);
228     Text(szBuffer);
229 }
230
231 static LARGE_INTEGER frequency = {0};
232 static LARGE_INTEGER startcounter;
233
234 void BeginCall(const char *function) {
235     EnterCriticalSection(&CriticalSection); 
236     Indent(1);
237     BeginTag("call", "name", function);
238     NewLine();
239
240     if(!frequency.QuadPart)
241         QueryPerformanceFrequency(&frequency);
242     
243     QueryPerformanceCounter(&startcounter);
244 }
245
246 void EndCall(void) {
247     LARGE_INTEGER endcounter;
248     LONGLONG usecs;
249
250     QueryPerformanceCounter(&endcounter);
251     usecs = (endcounter.QuadPart - startcounter.QuadPart)*1000000/frequency.QuadPart;
252
253     Indent(2);
254     BeginTag("duration");
255     TextF("%llu", usecs);
256     EndTag("duration");
257     NewLine();
258
259     Indent(1);
260     EndTag("call");
261     NewLine();
262     gzflush(g_gzFile, Z_SYNC_FLUSH);
263     LeaveCriticalSection(&CriticalSection); 
264 }
265
266 void BeginArg(const char *type, const char *name) {
267     Indent(2);
268     BeginTag("arg", "type", type, "name", name);
269 }
270
271 void EndArg(void) {
272     EndTag("arg");
273     NewLine();
274 }
275
276 void BeginReturn(const char *type) {
277     Indent(2);
278     BeginTag("ret", "type", type);
279 }
280
281 void EndReturn(void) {
282     EndTag("ret");
283     NewLine();
284 }
285
286 void BeginElement(const char *type, const char *name) {
287     BeginTag("elem", "type", type, "name", name);
288 }
289
290 void BeginElement(const char *type) {
291     BeginTag("elem", "type", type);
292 }
293
294 void EndElement(void) {
295     EndTag("elem");
296 }
297
298 void BeginReference(const char *type, const void *addr) {
299     char saddr[256];
300     snprintf(saddr, sizeof(saddr), "%p", addr);
301     BeginTag("ref", "type", type, "addr", saddr);
302 }
303
304 void EndReference(void) {
305     EndTag("ref");
306 }
307
308 void DumpString(const char *str) {
309     const unsigned char *p = (const unsigned char *)str;
310     Log::Text("\"");
311     unsigned char c;
312     while((c = *p++) != 0) {
313         if(c == '\"')
314             Text("\\\"");
315         else if(c == '\\')
316             Text("\\\\");
317         else if(c >= 0x20 && c <= 0x7e)
318             TextChar(c);
319         else if(c == '\t')
320             Text("\\t");
321         else if(c == '\r')
322             Text("\\r");
323         else if(c == '\n')
324             Text("&#10;");
325         else {
326             unsigned char octal0 = c & 0x7;
327             unsigned char octal1 = (c >> 3) & 0x7;
328             unsigned char octal2 = (c >> 3) & 0x7;
329             if(octal2)
330                 TextF("\\%u%u%u", octal2, octal1, octal0);
331             else if(octal1)
332                 TextF("\\%u%u", octal1, octal0);
333             else
334                 TextF("\\%u", octal0);
335         }
336     }
337     Log::Text("\"");
338 }
339
340 void DumpWString(const wchar_t *str) {
341     const wchar_t *p = str;
342     Log::Text("L\"");
343     wchar_t c;
344     while((c = *p++) != 0) {
345         if(c == '\"')
346             Text("\\\"");
347         else if(c == '\\')
348             Text("\\\\");
349         else if(c >= 0x20 && c <= 0x7e)
350             TextChar((char)c);
351         else if(c == '\t')
352             Text("\\t");
353         else if(c == '\r')
354             Text("\\r");
355         else if(c == '\n')
356             Text("&#10;");
357         else {
358             unsigned octal0 = c & 0x7;
359             unsigned octal1 = (c >> 3) & 0x7;
360             unsigned octal2 = (c >> 3) & 0x7;
361             if(octal2)
362                 TextF("\\%u%u%u", octal2, octal1, octal0);
363             else if(octal1)
364                 TextF("\\%u%u", octal1, octal0);
365             else
366                 TextF("\\%u", octal0);
367         }
368     }
369     Log::Text("\"");
370 }
371
372 } /* namespace Log */