]> git.cworth.org Git - apitrace/commitdiff
Merge branch 'master' into compression
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Wed, 24 Aug 2011 18:58:47 +0000 (19:58 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Wed, 24 Aug 2011 18:58:47 +0000 (19:58 +0100)
Conflicts:
os.hpp
os_posix.cpp
os_win32.cpp
trace_writer.cpp

1  2 
CMakeLists.txt
trace_file.cpp
trace_local_writer.cpp
trace_writer.cpp
trace_writer.hpp

diff --cc CMakeLists.txt
Simple merge
diff --cc trace_file.cpp
index 74cc3829e2b4ce5a18a3d69beb614e90b87ed6de,0000000000000000000000000000000000000000..2a9705cd3350ffc49dacd604cde9ae137e47e82c
mode 100644,000000..100644
--- /dev/null
@@@ -1,387 -1,0 +1,339 @@@
- #include <set>
 +#include "trace_file.hpp"
 +
 +#include <assert.h>
 +#include <string.h>
 +
 +#include <zlib.h>
 +#include <snappy.h>
 +
 +#include "os.hpp"
 +
 +#include <iostream>
- static void cleanupHandler(int sig);
- class FileCleanup
- {
- public:
-     FileCleanup()
-     {
-         OS::CatchInterrupts(cleanupHandler);
-     }
-     ~FileCleanup()
-     {
-         flush();
-         m_files.clear();
-     }
-     void addFile(Trace::File *file)
-     {
-         m_files.insert(file);
-     }
-     void removeFile(Trace::File *file)
-     {
-         m_files.erase(file);
-     }
-     void flush()
-     {
-         std::set<Trace::File*>::const_iterator itr;
-         for (itr = m_files.begin(); itr != m_files.end(); ++itr) {
-             (*itr)->flush(File::FlushDeep);
-         }
-     }
- private:
-     std::set<Trace::File*> m_files;
- };
- static FileCleanup s_cleaner;
- static void cleanupHandler(int sig)
- {
-     s_cleaner.flush();
- }
 +
 +using namespace Trace;
 +
 +#define SNAPPY_BYTE1 'a'
 +#define SNAPPY_BYTE2 't'
 +
-     if (m_isOpened) {
-         s_cleaner.addFile(this);
-     }
 +File::File(const std::string &filename,
 +           File::Mode mode)
 +    : m_filename(filename),
 +      m_mode(mode),
 +      m_isOpened(false)
 +{
 +    if (!m_filename.empty()) {
 +        open(m_filename, m_mode);
 +    }
 +}
 +
 +
 +File::~File()
 +{
 +    close();
 +}
 +
 +bool File::isOpened() const
 +{
 +    return m_isOpened;
 +}
 +
 +File::Mode File::mode() const
 +{
 +    return m_mode;
 +}
 +
 +std::string File::filename() const
 +{
 +    return m_filename;
 +}
 +
 +bool File::open(const std::string &filename, File::Mode mode)
 +{
 +    if (m_isOpened) {
 +        close();
 +    }
 +    m_isOpened = rawOpen(filename, mode);
 +    m_mode = mode;
 +
-         s_cleaner.removeFile(this);
 +    return m_isOpened;
 +}
 +
 +bool File::write(const void *buffer, int length)
 +{
 +    if (!m_isOpened || m_mode != File::Write) {
 +        return false;
 +    }
 +    return rawWrite(buffer, length);
 +}
 +
 +bool File::read(void *buffer, int length)
 +{
 +    if (!m_isOpened || m_mode != File::Read) {
 +        return false;
 +    }
 +    return rawRead(buffer, length);
 +}
 +
 +void File::close()
 +{
 +    if (m_isOpened) {
 +        rawClose();
 +        m_isOpened = false;
 +    }
 +}
 +
 +void File::flush(FlushType type)
 +{
 +    rawFlush(type);
 +}
 +
 +int File::getc()
 +{
 +    if (!m_isOpened || m_mode != File::Read) {
 +        return 0;
 +    }
 +    return rawGetc();
 +}
 +
 +bool File::isZLibCompressed(const std::string &filename)
 +{
 +    std::fstream stream(filename.c_str(),
 +                        std::fstream::binary | std::fstream::in);
 +    if (!stream.is_open())
 +        return false;
 +
 +    unsigned char byte1, byte2;
 +    stream >> byte1;
 +    stream >> byte2;
 +    stream.close();
 +
 +    return (byte1 == 0x1f && byte2 == 0x8b);
 +}
 +
 +
 +bool File::isSnappyCompressed(const std::string &filename)
 +{
 +    std::fstream stream(filename.c_str(),
 +                        std::fstream::binary | std::fstream::in);
 +    if (!stream.is_open())
 +        return false;
 +
 +    unsigned char byte1, byte2;
 +    stream >> byte1;
 +    stream >> byte2;
 +    stream.close();
 +
 +    return (byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);
 +}
 +
 +
 +ZLibFile::ZLibFile(const std::string &filename,
 +                   File::Mode mode)
 +    : File(filename, mode),
 +      m_gzFile(NULL)
 +{
 +}
 +
 +ZLibFile::~ZLibFile()
 +{
 +}
 +
 +bool ZLibFile::rawOpen(const std::string &filename, File::Mode mode)
 +{
 +    m_gzFile = gzopen(filename.c_str(),
 +                      (mode == File::Write) ? "wb" : "rb");
 +    return m_gzFile != NULL;
 +}
 +
 +bool ZLibFile::rawWrite(const void *buffer, int length)
 +{
 +    return gzwrite(m_gzFile, buffer, length) != -1;
 +}
 +
 +bool ZLibFile::rawRead(void *buffer, int length)
 +{
 +    return gzread(m_gzFile, buffer, length) != -1;
 +}
 +
 +int ZLibFile::rawGetc()
 +{
 +    return gzgetc(m_gzFile);
 +}
 +
 +void ZLibFile::rawClose()
 +{
 +    if (m_gzFile) {
 +        gzclose(m_gzFile);
 +        m_gzFile = NULL;
 +    }
 +}
 +
 +void ZLibFile::rawFlush(FlushType type)
 +{
 +    gzflush(m_gzFile, Z_SYNC_FLUSH);
 +}
 +
 +SnappyFile::SnappyFile(const std::string &filename,
 +                              File::Mode mode)
 +    : File(),
 +      m_cache(0),
 +      m_cachePtr(0),
 +      m_cacheSize(0)
 +{
 +    m_compressedCache = new char[SNAPPY_CHUNK_SIZE];
 +}
 +
 +SnappyFile::~SnappyFile()
 +{
 +    delete [] m_compressedCache;
 +}
 +
 +bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
 +{
 +    std::ios_base::openmode fmode = std::fstream::binary;
 +    if (mode == File::Write) {
 +        fmode |= (std::fstream::out | std::fstream::trunc);
 +        createCache(SNAPPY_CHUNK_SIZE);
 +    } else if (mode == File::Read) {
 +        fmode |= std::fstream::in;
 +    }
 +
 +    m_stream.open(filename.c_str(), fmode);
 +
 +    //read in the initial buffer if we're reading
 +    if (m_stream.is_open() && mode == File::Read) {
 +        // read the snappy file identifier
 +        unsigned char byte1, byte2;
 +        m_stream >> byte1;
 +        m_stream >> byte2;
 +        assert(byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);
 +
 +        flushCache();
 +    } else if (m_stream.is_open() && mode == File::Write) {
 +        // write the snappy file identifier
 +        m_stream << SNAPPY_BYTE1;
 +        m_stream << SNAPPY_BYTE2;
 +    }
 +    return m_stream.is_open();
 +}
 +
 +bool SnappyFile::rawWrite(const void *buffer, int length)
 +{
 +    if (freeCacheSize() > length) {
 +        memcpy(m_cachePtr, buffer, length);
 +        m_cachePtr += length;
 +    } else if (freeCacheSize() == length) {
 +        memcpy(m_cachePtr, buffer, length);
 +        m_cachePtr += length;
 +        flushCache();
 +    } else {
 +        int sizeToWrite = length;
 +
 +        while (sizeToWrite >= freeCacheSize()) {
 +            int endSize = freeCacheSize();
 +            int offset = length - sizeToWrite;
 +            memcpy(m_cachePtr, (char*)buffer + offset, endSize);
 +            sizeToWrite -= endSize;
 +            m_cachePtr += endSize;
 +            flushCache();
 +        }
 +        if (sizeToWrite) {
 +            int offset = length - sizeToWrite;
 +            memcpy(m_cachePtr, (char*)buffer + offset, sizeToWrite);
 +            m_cachePtr += sizeToWrite;
 +        }
 +    }
 +
 +    return true;
 +}
 +
 +bool SnappyFile::rawRead(void *buffer, int length)
 +{
 +    if (m_stream.eof()) {
 +        return false;
 +    }
 +    if (freeCacheSize() > length) {
 +        memcpy(buffer, m_cachePtr, length);
 +        m_cachePtr += length;
 +    } else if (freeCacheSize() == length) {
 +        memcpy(buffer, m_cachePtr, length);
 +        m_cachePtr += length;
 +        flushCache();
 +    } else {
 +        int sizeToRead = length;
 +        int offset = 0;
 +        while (sizeToRead) {
 +            int chunkSize = std::min(freeCacheSize(), sizeToRead);
 +            offset = length - sizeToRead;
 +            memcpy((char*)buffer + offset, m_cachePtr, chunkSize);
 +            m_cachePtr += chunkSize;
 +            sizeToRead -= chunkSize;
 +            if (sizeToRead > 0)
 +                flushCache();
 +            if (!m_cacheSize)
 +                break;
 +        }
 +    }
 +
 +    return true;
 +}
 +
 +int SnappyFile::rawGetc()
 +{
 +    int c = 0;
 +    if (!rawRead(&c, 1))
 +        return -1;
 +    return c;
 +}
 +
 +void SnappyFile::rawClose()
 +{
 +    flushCache();
 +    m_stream.close();
 +    delete [] m_cache;
 +    m_cache = NULL;
 +    m_cachePtr = NULL;
 +}
 +
 +void SnappyFile::rawFlush(FlushType type)
 +{
 +    if (type == FlushDeep) {
 +        flushCache();
 +    }
 +    m_stream.flush();
 +}
 +
 +void SnappyFile::flushCache()
 +{
 +    if (m_mode == File::Write) {
 +        size_t compressedLength;
 +
 +        ::snappy::RawCompress(m_cache, SNAPPY_CHUNK_SIZE - freeCacheSize(),
 +                              m_compressedCache, &compressedLength);
 +
 +        m_stream << compressedLength;
 +        m_stream.write(m_compressedCache, compressedLength);
 +        m_cachePtr = m_cache;
 +    } else if (m_mode == File::Read) {
 +        if (m_stream.eof())
 +            return;
 +        //assert(m_cachePtr == m_cache + m_cacheSize);
 +        size_t compressedLength;
 +        m_stream >> compressedLength;
 +        m_stream.read((char*)m_compressedCache, compressedLength);
 +        ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
 +                                        &m_cacheSize);
 +        if (m_cache)
 +            delete [] m_cache;
 +        createCache(m_cacheSize);
 +        ::snappy::RawUncompress(m_compressedCache, compressedLength,
 +                                m_cache);
 +    }
 +}
 +
 +void SnappyFile::createCache(size_t size)
 +{
 +    m_cache = new char[size];
 +    m_cachePtr = m_cache;
 +    m_cacheSize = size;
 +}
index 0000000000000000000000000000000000000000,ae6a6b66699bf6b215643609f188ec00229f6bfd..ea6c111eb8756ff6b0fa2386bebf5560d71d766a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,157 +1,156 @@@
 -#include <zlib.h>
 -
+ /**************************************************************************
+  *
+  * Copyright 2007-2011 VMware, Inc.
+  * All Rights Reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+  * of this software and associated documentation files (the "Software"), to deal
+  * in the Software without restriction, including without limitation the rights
+  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  * copies of the Software, and to permit persons to whom the Software is
+  * furnished to do so, subject to the following conditions:
+  *
+  * The above copyright notice and this permission notice shall be included in
+  * all copies or substantial portions of the Software.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  * THE SOFTWARE.
+  *
+  **************************************************************************/
+ #include <assert.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
 -    if (!g_gzFile) {
+ #include "os.hpp"
++#include "trace_file.hpp"
+ #include "trace_writer.hpp"
+ #include "trace_format.hpp"
+ namespace Trace {
+ static void exceptionCallback(void)
+ {
+     OS::DebugMessage("apitrace: flushing trace due to an exception\n");
+     localWriter.flush();
+ }
+ LocalWriter::LocalWriter() :
+     acquired(0)
+ {}
+ LocalWriter::~LocalWriter()
+ {
+     OS::ResetExceptionCallback();
+ }
+ void
+ LocalWriter::open(void) {
+     static unsigned dwCounter = 0;
+     const char *szExtension = "trace";
+     char szFileName[PATH_MAX];
+     const char *lpFileName;
+     lpFileName = getenv("TRACE_FILE");
+     if (lpFileName) {
+         strncpy(szFileName, lpFileName, PATH_MAX);
+     }
+     else {
+         char szProcessName[PATH_MAX];
+         char szCurrentDir[PATH_MAX];
+         OS::GetProcessName(szProcessName, PATH_MAX);
+         OS::GetCurrentDir(szCurrentDir, PATH_MAX);
+         for (;;) {
+             FILE *file;
+             if (dwCounter)
+                 snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
+             else
+                 snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
+             file = fopen(szFileName, "rb");
+             if (file == NULL)
+                 break;
+             fclose(file);
+             ++dwCounter;
+         }
+     }
+     OS::DebugMessage("apitrace: tracing to %s\n", szFileName);
+     Writer::open(szFileName);
+     OS::SetExceptionCallback(exceptionCallback);
+ #if 0
+     // For debugging the exception handler
+     *((int *)0) = 0;
+ #endif
+ }
+ unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
+     OS::AcquireMutex();
+     ++acquired;
 -            if (g_gzFile) {
 -                gzflush(g_gzFile, Z_SYNC_FLUSH);
 -            }
++    if (!m_file->isOpened()) {
+         open();
+     }
+     return Writer::beginEnter(sig);
+ }
+ void LocalWriter::endEnter(void) {
+     Writer::endEnter();
+     --acquired;
+     OS::ReleaseMutex();
+ }
+ void LocalWriter::beginLeave(unsigned call) {
+     OS::AcquireMutex();
+     ++acquired;
+     Writer::beginLeave(call);
+ }
+ void LocalWriter::endLeave(void) {
+     Writer::endLeave();
+     --acquired;
+     OS::ReleaseMutex();
+ }
+ void LocalWriter::flush(void) {
+     /*
+      * Do nothing if the mutex is already acquired (e.g., if a segfault happen
+      * while writing the file) to prevent dead-lock.
+      */
+     if (!acquired) {
+         OS::AcquireMutex();
++        if (m_file->isOpened()) {
++            m_file->flush();
++        }
+         OS::ReleaseMutex();
+     }
+ }
+ LocalWriter localWriter;
+ } /* namespace Trace */
Simple merge
Simple merge