]> git.cworth.org Git - apitrace/blobdiff - log.cpp
Prepend process name to the log's filename.
[apitrace] / log.cpp
diff --git a/log.cpp b/log.cpp
index 20df332ad9908e6c96c7874bfe40762058b85397..7e219700988acad8e12ba6f0324885aa49a193f1 100644 (file)
--- a/log.cpp
+++ b/log.cpp
@@ -1,6 +1,6 @@
 /****************************************************************************
  *
- * Copyright 2008 Jose Fonseca
+ * Copyright 2008-2009 VMware, Inc.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
  ****************************************************************************/
 
 
+#include <stdarg.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <windows.h>
+
+#include <zlib.h>
 
 #include "log.hpp"
 
 
+#ifdef WIN32
+#ifndef PATH_MAX
+#define PATH_MAX _MAX_PATH
+#endif
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
+#ifndef vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+#endif
+
+
 namespace Log {
 
 
-static HANDLE g_hFile = INVALID_HANDLE_VALUE;
-static TCHAR g_szFileName[MAX_PATH];
+static gzFile g_gzFile = NULL;
+static char g_szFileName[PATH_MAX];
+static CRITICAL_SECTION CriticalSection;
 
 static void _Close(void) {
-    if(g_hFile != INVALID_HANDLE_VALUE) {
-        CloseHandle(g_hFile);
-        g_hFile = INVALID_HANDLE_VALUE;
+    if(g_gzFile != NULL) {
+        gzclose(g_gzFile);
+        g_gzFile = NULL;
+        DeleteCriticalSection(&CriticalSection);
     }
 }
 
-static void _Open(const TCHAR *szName, const TCHAR *szExtension) {
+static void _Open(const char *szName, const char *szExtension) {
     _Close();
     
-    DWORD dwCounter = 0;
-    do {
-        if(dwCounter)
-            _sntprintf(g_szFileName, MAX_PATH, TEXT("%s.%u.%s"), szName, dwCounter, szExtension);
-        else
-            _sntprintf(g_szFileName, MAX_PATH, TEXT("%s.%s"), szName, szExtension);
-
-        g_hFile = CreateFile(g_szFileName,
-                             GENERIC_WRITE,
-                             FILE_SHARE_WRITE,
-                             NULL,
-                             CREATE_NEW,
-                             FILE_ATTRIBUTE_NORMAL,
-                             NULL);
-        ++dwCounter;
-    } while(g_hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS);
-}
+    static unsigned dwCounter = 0;
 
-static void _ReOpen(void) {
-    _Close();
-    
-    g_hFile = CreateFile(g_szFileName,
-                         GENERIC_WRITE,
-                         FILE_SHARE_WRITE,
-                         NULL,
-                         OPEN_EXISTING,
-                         FILE_ATTRIBUTE_NORMAL,
-                         NULL);
-}
+    char szProcessPath[PATH_MAX];
+    char *lpProcessName;
+    char *lpProcessExt;
 
-static void Write(const char *sBuffer, DWORD dwBytesToWrite) {
-    if(g_hFile == INVALID_HANDLE_VALUE)
-        return;
-    
-    DWORD dwBytesWritten = 0;
-    
-    while (dwBytesWritten < dwBytesToWrite) {
-        OVERLAPPED overlapped;
-        memset(&overlapped, 0, sizeof(OVERLAPPED));
+    GetModuleFileNameA(NULL, szProcessPath, sizeof(szProcessPath)/sizeof(szProcessPath[0]));
 
-        /* Write to end of file */
-        overlapped.Offset = 0xffffffff;
-        overlapped.OffsetHigh = 0xffffffff;
+    lpProcessName = strrchr(szProcessPath, '\\');
+    lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
+    lpProcessExt = strrchr(lpProcessName, '.');
+    if(lpProcessExt)
+       *lpProcessExt = '\0';
+
+    for(;;) {
+        FILE *file;
         
-        if(WriteFile(g_hFile,
-                     sBuffer + dwBytesWritten,
-                     dwBytesToWrite - dwBytesWritten,
-                     &dwBytesWritten,
-                     &overlapped) == FALSE) {
-            _Close();
-            _Open(TEXT("extra"), TEXT("xml"));
-            return;
-        }
+        if(dwCounter)
+            snprintf(g_szFileName, PATH_MAX, "%s.%s.%u.%s.gz", lpProcessName, szName, dwCounter, szExtension);
+        else
+            snprintf(g_szFileName, PATH_MAX, "%s.%s.%s.gz", lpProcessName, szName, szExtension);
+        
+        file = fopen(g_szFileName, "rb");
+        if(file == NULL)
+            break;
+        
+        fclose(file);
+        
+        ++dwCounter;
     }
-}
 
-static void Write(const char *szText) {
-    Write(szText, (DWORD)strlen(szText));
+    g_gzFile = gzopen(g_szFileName, "wb");
+    InitializeCriticalSection(&CriticalSection);
 }
 
-void Open(const TCHAR *szName) {
-    _Open(szName, TEXT("xml"));
-    Write("<?xml version='1.0' encoding='UTF-8'?>");
-    NewLine();
-    Write("<?xml-stylesheet type='text/xsl' href='d3dtrace.xsl'?>");
-    NewLine();
-    Write("<trace>");
-    NewLine();
+static inline void _ReOpen(void) {
+    /* XXX */
 }
 
-void ReOpen(void) {
-    _ReOpen();
+static inline void Write(const char *sBuffer, size_t dwBytesToWrite) {
+    if(g_gzFile == NULL)
+        return;
+    
+    gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
 }
 
-void Close(void) {
-    Write("</trace>");
-    NewLine();
-    _Close();
+static inline void Write(const char *szText) {
+    Write(szText, strlen(szText));
 }
 
-static void Escape(const char *s) {
+static inline void 
+Escape(const char *s) {
     /* FIXME */
     Write(s);
 }
 
+static inline void 
+Indent(unsigned level) {
+    for(unsigned i = 0; i < level; ++i)
+        Write("\t");
+}
 
-DWORD g_dwIndent = 0;
-
-void NewLine(void) {
+static inline void 
+NewLine(void) {
     Write("\r\n");
-    for(unsigned i = 0; i < g_dwIndent; ++i)
-        Write("\t");        
 }
 
-void Tag(const char *name) {
+static inline void 
+Tag(const char *name) {
     Write("<");
     Write(name);
     Write("/>");
 }
 
-void BeginTag(const char *name) {
+static inline void 
+BeginTag(const char *name) {
     Write("<");
     Write(name);
     Write(">");
-    ++g_dwIndent;
 }
 
-void BeginTag(const char *name, 
-              const char *attr1, const char *value1) {
+static inline void 
+BeginTag(const char *name, 
+         const char *attr1, const char *value1) {
     Write("<");
     Write(name);
     Write(" ");
@@ -155,12 +152,12 @@ void BeginTag(const char *name,
     Write("=\"");
     Escape(value1);
     Write("\">");
-    ++g_dwIndent;
 }
 
-void BeginTag(const char *name, 
-              const char *attr1, const char *value1,
-              const char *attr2, const char *value2) {
+static inline void 
+BeginTag(const char *name, 
+         const char *attr1, const char *value1,
+         const char *attr2, const char *value2) {
     Write("<");
     Write(name);
     Write(" ");
@@ -172,10 +169,10 @@ void BeginTag(const char *name,
     Write("=\"");
     Escape(value2);
     Write("\">");
-    ++g_dwIndent;
 }
 
-void BeginTag(const char *name, 
+static inline void 
+BeginTag(const char *name, 
               const char *attr1, const char *value1,
               const char *attr2, const char *value2,
               const char *attr3, const char *value3) {
@@ -194,16 +191,35 @@ void BeginTag(const char *name,
     Write("=\"");
     Escape(value3);
     Write("\">");
-    ++g_dwIndent;
 }
 
-void EndTag(const char *name) {
-    --g_dwIndent;
+static inline void
+EndTag(const char *name) {
     Write("</");
     Write(name);
     Write(">");
 }
 
+void Open(const char *name) {
+    _Open(name, "xml");
+    Write("<?xml version='1.0' encoding='UTF-8'?>");
+    NewLine();
+    Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
+    NewLine();
+    BeginTag("trace");
+    NewLine();
+}
+
+void ReOpen(void) {
+    _ReOpen();
+}
+
+void Close(void) {
+    EndTag("trace");
+    NewLine();
+    _Close();
+}
+
 void Text(const char *text) {
     Escape(text);
 }
@@ -224,17 +240,43 @@ void TextF(const char *format, ...) {
     Text(szBuffer);
 }
 
+static LARGE_INTEGER frequency = {0};
+static LARGE_INTEGER startcounter;
+
 void BeginCall(const char *function) {
+    EnterCriticalSection(&CriticalSection); 
+    Indent(1);
     BeginTag("call", "name", function);
     NewLine();
+
+    if(!frequency.QuadPart)
+       QueryPerformanceFrequency(&frequency);
+    
+    QueryPerformanceCounter(&startcounter);
 }
 
 void EndCall(void) {
+    LARGE_INTEGER endcounter;
+    LONGLONG usecs;
+
+    QueryPerformanceCounter(&endcounter);
+    usecs = (endcounter.QuadPart - startcounter.QuadPart)*1000000/frequency.QuadPart;
+
+    Indent(2);
+    BeginTag("duration");
+    TextF("%llu", usecs);
+    EndTag("duration");
+    NewLine();
+
+    Indent(1);
     EndTag("call");
     NewLine();
+    gzflush(g_gzFile, Z_SYNC_FLUSH);
+    LeaveCriticalSection(&CriticalSection); 
 }
 
 void BeginArg(const char *type, const char *name) {
+    Indent(2);
     BeginTag("arg", "type", type, "name", name);
 }
 
@@ -244,6 +286,7 @@ void EndArg(void) {
 }
 
 void BeginReturn(const char *type) {
+    Indent(2);
     BeginTag("ret", "type", type);
 }
 
@@ -266,7 +309,7 @@ void EndElement(void) {
 
 void BeginReference(const char *type, const void *addr) {
     char saddr[256];
-    _snprintf(saddr, sizeof(saddr), "%p", addr);
+    snprintf(saddr, sizeof(saddr), "%p", addr);
     BeginTag("ref", "type", type, "addr", saddr);
 }
 
@@ -290,7 +333,7 @@ void DumpString(const char *str) {
         else if(c == '\r')
             Text("\\r");
         else if(c == '\n')
-            Text("\\n");
+            Text("&#10;");
         else {
             unsigned char octal0 = c & 0x7;
             unsigned char octal1 = (c >> 3) & 0x7;
@@ -306,4 +349,36 @@ void DumpString(const char *str) {
     Log::Text("\"");
 }
 
+void DumpWString(const wchar_t *str) {
+    const wchar_t *p = str;
+    Log::Text("L\"");
+    wchar_t c;
+    while((c = *p++) != 0) {
+        if(c == '\"')
+            Text("\\\"");
+        else if(c == '\\')
+            Text("\\\\");
+        else if(c >= 0x20 && c <= 0x7e)
+            TextChar((char)c);
+        else if(c == '\t')
+            Text("\\t");
+        else if(c == '\r')
+            Text("\\r");
+        else if(c == '\n')
+            Text("&#10;");
+        else {
+            unsigned octal0 = c & 0x7;
+            unsigned octal1 = (c >> 3) & 0x7;
+            unsigned octal2 = (c >> 3) & 0x7;
+            if(octal2)
+                TextF("\\%u%u%u", octal2, octal1, octal0);
+            else if(octal1)
+                TextF("\\%u%u", octal1, octal0);
+            else
+                TextF("\\%u", octal0);
+        }
+    }
+    Log::Text("\"");
+}
+
 } /* namespace Log */