]> git.cworth.org Git - apitrace/commitdiff
Some initial thoughts on the on-demand loading api.
authorZack Rusin <zack@kde.org>
Fri, 26 Aug 2011 03:22:30 +0000 (23:22 -0400)
committerZack Rusin <zack@kde.org>
Sat, 27 Aug 2011 05:44:01 +0000 (01:44 -0400)
CMakeLists.txt
loadertest.cpp [new file with mode: 0644]
trace_file.cpp
trace_file.hpp
trace_loader.cpp [new file with mode: 0644]
trace_loader.hpp [new file with mode: 0644]
trace_parser.cpp
trace_parser.hpp
trace_snappyfile.cpp
trace_snappyfile.hpp

index e840f21d193608b386d33edf84f72ea3511e1ea9..2ee433a51dd1814eb0f518f22139c0fba416b351 100755 (executable)
@@ -187,6 +187,7 @@ add_library (common
     trace_writer.cpp
     trace_local_writer.cpp
     trace_model_writer.cpp
+    trace_loader.cpp
     image.cpp
     image_bmp.cpp
     image_pnm.cpp
@@ -204,6 +205,8 @@ link_libraries (common)
 add_executable (tracedump tracedump.cpp)
 install (TARGETS tracedump RUNTIME DESTINATION bin) 
 
+add_executable (loadertest loadertest.cpp)
+install (TARGETS loadertest RUNTIME DESTINATION bin)
 
 ##############################################################################
 # API tracers
diff --git a/loadertest.cpp b/loadertest.cpp
new file mode 100644 (file)
index 0000000..48bdac9
--- /dev/null
@@ -0,0 +1,41 @@
+#include "trace_loader.hpp"
+
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+    int i;
+
+    for (i = 1; i < argc; ++i) {
+        Trace::Loader loader;
+
+        if (!loader.open(argv[i])) {
+            std::cerr << "error: failed to open " << argv[i] << "\n";
+            return 1;
+        }
+
+        std::cout << "Number of frames = "
+                  << loader.numberOfFrames()
+                  << std::endl;
+        std::cout << "Number of calls in frame 0 = "
+                  << loader.numberOfCallsInFrame(0)
+                  << std::endl;
+        int lastFrame = loader.numberOfFrames() - 1;
+        std::cout << "Number of calls in frame "
+                  << lastFrame << " = "
+                  << loader.numberOfCallsInFrame(lastFrame)
+                  << std::endl;
+
+
+        std::vector<Trace::Call*> frame = loader.frame(
+                 0);
+        std::vector<Trace::Call*>::const_iterator itr;
+        for (itr = frame.begin(); itr != frame.end(); ++itr) {
+           (*itr)->dump(std::cout, true);
+        }
+    }
+
+
+    return 0;
+}
+
index e20685812c5c6230c9e6f582f7ea2441bf5dfede..d4e74b9ab45a6ff54b748b6eddb44ccabd27fb4b 100644 (file)
@@ -56,6 +56,16 @@ File::~File()
     close();
 }
 
+
+File::Offset File::currentOffset()
+{
+    return File::Offset();
+}
+
+void File::setCurrentOffset(const File::Offset &offset)
+{
+}
+
 bool File::isZLibCompressed(const std::string &filename)
 {
     std::fstream stream(filename.c_str(),
@@ -133,3 +143,9 @@ void ZLibFile::rawFlush()
 {
     gzflush(m_gzFile, Z_SYNC_FLUSH);
 }
+
+
+bool ZLibFile::supportsOffsets() const
+{
+    return false;
+}
index a8b33459a024dc44d348f1c6cdd075d2e52a5439..fed30a0a8835f64a72c0d61f903279ae3f49b785 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <string>
 #include <fstream>
+#include <stdint.h>
 
 namespace Trace {
 
@@ -38,6 +39,15 @@ public:
         Read,
         Write
     };
+    struct Offset {
+        Offset()
+            : chunk(0),
+              offsetInChunk(0)
+        {}
+        uint64_t chunk;
+        uint32_t offsetInChunk;
+    };
+
 public:
     static bool isZLibCompressed(const std::string &filename);
     static bool isSnappyCompressed(const std::string &filename);
@@ -58,6 +68,9 @@ public:
     void flush(void);
     int getc();
 
+    virtual bool supportsOffsets() const = 0;
+    virtual File::Offset currentOffset();
+    virtual void setCurrentOffset(const File::Offset &offset);
 protected:
     virtual bool rawOpen(const std::string &filename, File::Mode mode) = 0;
     virtual bool rawWrite(const void *buffer, int length) = 0;
@@ -141,6 +154,8 @@ public:
              File::Mode mode = File::Read);
     virtual ~ZLibFile();
 
+
+    virtual bool supportsOffsets() const;
 protected:
     virtual bool rawOpen(const std::string &filename, File::Mode mode);
     virtual bool rawWrite(const void *buffer, int length);
diff --git a/trace_loader.cpp b/trace_loader.cpp
new file mode 100644 (file)
index 0000000..f2e6c6e
--- /dev/null
@@ -0,0 +1,126 @@
+#include "trace_loader.hpp"
+
+#include "trace_snappyfile.hpp"
+
+using namespace Trace;
+
+Loader::Loader()
+    : m_frameMarker(FrameMarker_SwapBuffers),
+      file(0)
+{
+}
+
+Loader::~Loader()
+{
+    close();
+}
+
+Loader::FrameMarker Loader::frameMarker() const
+{
+    return m_frameMarker;
+}
+
+void Loader::setFrameMarker(Loader::FrameMarker marker)
+{
+    m_frameMarker = marker;
+}
+
+int Loader::numberOfFrames() const
+{
+    return m_frameOffsets.size();
+}
+
+int Loader::numberOfCallsInFrame(int frameIdx)
+{
+    if (frameIdx > m_frameOffsets.size()) {
+        return 0;
+    }
+
+    return m_frameOffsets[frameIdx].numberOfCalls;
+}
+
+bool Loader::open(const char *filename)
+{
+    if (!m_parser.open(filename)) {
+        std::cerr << "error: failed to open " << filename << "\n";
+        return false;
+    }
+
+    Trace::Call *call;
+    File::Offset startOffset;
+    int numOfFrames = 0;
+    int numOfCalls = 0;
+
+    startOffset = m_parser.currentOffset();
+
+    while ((call = m_parser.parse_call())) {
+
+        ++numOfCalls;
+
+        if (isCallAFrameMarker(call)) {
+            File::Offset endOffset = m_parser.currentOffset();
+            FrameOffset frameOffset(startOffset, endOffset);
+
+            frameOffset.numberOfCalls = numOfCalls;
+            m_frameOffsets[numOfFrames] = frameOffset;
+            ++numOfFrames;
+
+            startOffset = endOffset;
+            numOfCalls = 0;
+        }
+        //call->dump(std::cout, color);
+        delete call;
+    }
+    return true;
+}
+
+void Loader::close()
+{
+    m_parser.close();
+}
+
+bool Loader::isCallAFrameMarker(const Trace::Call *call) const
+{
+    std::string name = call->name();
+
+    switch (m_frameMarker) {
+    case FrameMarker_SwapBuffers:
+        return  name.find("SwapBuffers") != std::string::npos ||
+                name == "CGLFlushDrawable" ||
+                name == "glFrameTerminatorGREMEDY";
+        break;
+    case FrameMarker_Flush:
+        return name == "glFlush";
+        break;
+    case FrameMarker_Finish:
+        return name == "glFinish";
+        break;
+    case FrameMarker_Clear:
+        return name == "glClear";
+        break;
+    }
+    return false;
+}
+
+std::vector<Trace::Call *> Trace::Loader::frame(int idx)
+{
+    int numOfCalls = numberOfCallsInFrame(idx);
+    if (numOfCalls) {
+        std::vector<Trace::Call*> calls(numOfCalls);
+        m_parser.setCurrentOffset(m_frameOffsets[idx].start);
+
+        Trace::Call *call;
+        int parsedCalls = 0;
+        while ((call = m_parser.parse_call())) {
+
+            if (isCallAFrameMarker(call)) {
+                break;
+            }
+
+            calls[parsedCalls] = call;
+            ++parsedCalls;
+        }
+        return calls;
+    }
+    return std::vector<Trace::Call*>();
+}
diff --git a/trace_loader.hpp b/trace_loader.hpp
new file mode 100644 (file)
index 0000000..7b746b9
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef TRACE_LOADER_HPP
+#define TRACE_LOADER_HPP
+
+#include "trace_file.hpp"
+#include "trace_parser.hpp"
+
+#include <string>
+#include <map>
+#include <queue>
+#include <vector>
+
+namespace Trace  {
+
+class Frame;
+
+class Loader
+{
+public:
+    enum FrameMarker {
+        FrameMarker_SwapBuffers,
+        FrameMarker_Flush,
+        FrameMarker_Finish,
+        FrameMarker_Clear
+    };
+public:
+    Loader();
+    ~Loader();
+
+    Loader::FrameMarker frameMarker() const;
+    void setFrameMarker(Loader::FrameMarker marker);
+
+    int numberOfFrames() const;
+    int numberOfCallsInFrame(int frameIdx);
+
+    bool open(const char *filename);
+    void close();
+
+    std::vector<Trace::Call*> frame(int idx);
+
+private:
+    struct FrameOffset {
+        FrameOffset()
+            : numberOfCalls(0)
+        {}
+        FrameOffset(const File::Offset &s,
+                    const File::Offset &e)
+            : start(s),
+              end(e),
+              numberOfCalls(0)
+        {}
+
+        File::Offset start;
+        File::Offset end;
+        int numberOfCalls;
+    };
+    bool isCallAFrameMarker(const Trace::Call *call) const;
+
+private:
+    Trace::Parser m_parser;
+    FrameMarker m_frameMarker;
+
+    std::map<int, Trace::Frame*> m_frameCache;
+    std::queue<Trace::Frame*> m_loadedFrames;
+
+    std::map<int, FrameOffset> m_frameOffsets;
+
+    Trace::File *file;
+};
+
+}
+
+#endif // TRACE_LOADER_HPP
index 47d5a7a865771e3025b2f1cc674bda2aea8c1173..44d1786ac207fe2fa576a88c9cfae90339013fdc 100644 (file)
@@ -84,9 +84,10 @@ deleteAll(Iter begin, Iter end)
 
 template <typename Container>
 inline void
-deleteAll(const Container &c)
+deleteAll(Container &c)
 {
     deleteAll(c.begin(), c.end());
+    c.clear();
 }
 
 void Parser::close(void) {
index 4fff9ad1157129e0da8458f8cca87e68687197ec..a000986c3631299292745dc213dca060406938d2 100644 (file)
 #include <iostream>
 #include <list>
 
+#include "trace_file.hpp"
 #include "trace_format.hpp"
 #include "trace_model.hpp"
 
 
 namespace Trace {
 
-class File;
-
 class Parser
 {
 protected:
@@ -73,6 +72,21 @@ public:
 
     Call *parse_call(void);
 
+    bool supportsOffsets() const
+    {
+        return file-supportsOffsets();
+    }
+
+    File::Offset currentOffset()
+    {
+        return file->currentOffset();
+    }
+
+    void setCurrentOffset(const File::Offset &offset)
+    {
+        file->setCurrentOffset(offset);
+    }
+
 protected:
     void parse_enter(void);
 
index a3481838dd1b23fd02cf4bd248780a156b8b9eb0..c13a97940d04c0e0372d42124f8ba2fddafc0723 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <snappy.h>
 
+#include <iostream>
+
 #include <assert.h>
 #include <string.h>
 
@@ -135,16 +137,13 @@ bool SnappyFile::rawWrite(const void *buffer, int length)
 
 bool SnappyFile::rawRead(void *buffer, int length)
 {
-    if (m_stream.eof()) {
+    if (endOfData()) {
         return false;
     }
-    if (freeCacheSize() > length) {
-        memcpy(buffer, m_cachePtr, length);
-        m_cachePtr += length;
-    } else if (freeCacheSize() == length) {
+
+    if (freeCacheSize() >= length) {
         memcpy(buffer, m_cachePtr, length);
         m_cachePtr += length;
-        flushCache();
     } else {
         int sizeToRead = length;
         int offset = 0;
@@ -202,9 +201,18 @@ void SnappyFile::flushCache()
         if (m_stream.eof())
             return;
         //assert(m_cachePtr == m_cache + m_cacheSize);
+        m_currentOffset.chunk = m_stream.tellg();
         size_t compressedLength;
         compressedLength = readCompressedLength();
         m_stream.read((char*)m_compressedCache, compressedLength);
+        /*
+         * The reason we peek here is because the last read will
+         * read all the way until the last character, but that will not
+         * trigger m_stream.eof() to be set, so by calling peek
+         * we assure that if we in fact have read the entire stream
+         * then the m_stream.eof() is always set.
+         */
+        m_stream.peek();
         ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
                                         &m_cacheSize);
         if (m_cache)
@@ -233,3 +241,28 @@ uint32_t SnappyFile::readCompressedLength()
     m_stream.read((char*)&len, sizeof len);
     return len;
 }
+
+bool SnappyFile::supportsOffsets() const
+{
+    return true;
+}
+
+File::Offset SnappyFile::currentOffset()
+{
+    m_currentOffset.offsetInChunk = m_cachePtr - m_cache;
+    return m_currentOffset;
+}
+
+void SnappyFile::setCurrentOffset(const File::Offset &offset)
+{
+    // to remove eof bit
+    m_stream.clear();
+    // seek to the start of a chunk
+    m_stream.seekg(offset.chunk, std::ios::beg);
+    // load the chunk
+    flushCache();
+    assert(m_cacheSize >= offset.offsetInChunk);
+    // seek within our cache to the correct location within the chunk
+    m_cachePtr = m_cache + offset.offsetInChunk;
+
+}
index 7fab8351d42711958644d33be1c30251ae3b6fa6..6c0c9add1f8fbe72e33703baccaf0075b57fea4f 100644 (file)
@@ -52,6 +52,9 @@ public:
                File::Mode mode = File::Read);
     virtual ~SnappyFile();
 
+    virtual bool supportsOffsets() const;
+    virtual File::Offset currentOffset();
+    virtual void setCurrentOffset(const File::Offset &offset);
 protected:
     virtual bool rawOpen(const std::string &filename, File::Mode mode);
     virtual bool rawWrite(const void *buffer, int length);
@@ -68,6 +71,11 @@ private:
         else
             return 0;
     }
+    inline bool endOfData() const
+    {
+        return m_stream.eof() && freeCacheSize() == 0;
+    }
+
     void flushCache();
     void createCache(size_t size);
     void writeCompressedLength(uint32_t  num);
@@ -79,6 +87,8 @@ private:
     size_t m_cacheSize;
 
     char *m_compressedCache;
+
+    File::Offset m_currentOffset;
 };
 
 }