LCOV - code coverage report
Current view: top level - source/lib/file/common - trace.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 41 98 41.8 %
Date: 2023-01-19 00:18:29 Functions: 12 28 42.9 %

          Line data    Source code
       1             : /* Copyright (C) 2019 Wildfire Games.
       2             :  *
       3             :  * Permission is hereby granted, free of charge, to any person obtaining
       4             :  * a copy of this software and associated documentation files (the
       5             :  * "Software"), to deal in the Software without restriction, including
       6             :  * without limitation the rights to use, copy, modify, merge, publish,
       7             :  * distribute, sublicense, and/or sell copies of the Software, and to
       8             :  * permit persons to whom the Software is furnished to do so, subject to
       9             :  * the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included
      12             :  * in all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      15             :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      16             :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      17             :  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
      18             :  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
      19             :  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      20             :  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      21             :  */
      22             : 
      23             : /*
      24             :  * IO event recording
      25             :  */
      26             : 
      27             : #include "precompiled.h"
      28             : #include "lib/file/common/trace.h"
      29             : 
      30             : #include <cstdio>
      31             : #include <sstream>
      32             : 
      33             : #include "lib/allocators/pool.h"
      34             : #include "lib/timer.h"    // timer_Time
      35             : #include "lib/sysdep/sysdep.h"    // sys_OpenFile
      36             : 
      37             : 
      38          83 : /*virtual*/ ITrace::~ITrace()
      39             : {
      40             : 
      41          83 : }
      42             : 
      43             : 
      44             : //-----------------------------------------------------------------------------
      45             : 
      46           2 : TraceEntry::TraceEntry(EAction action, const Path& pathname, size_t size)
      47           2 : : m_timestamp((float)timer_Time())
      48             : , m_action(action)
      49             : , m_pathname(pathname)
      50           2 : , m_size(size)
      51             : {
      52           2 : }
      53             : 
      54             : 
      55           3 : TraceEntry::TraceEntry(const std::wstring& text)
      56             : {
      57             :     // swscanf is far too awkward to get working cross-platform,
      58             :     // so use iostreams here instead
      59             : 
      60             :     wchar_t dummy;
      61             :     wchar_t action;
      62             : 
      63           6 :     std::wstringstream stream(text);
      64           3 :     stream >> m_timestamp;
      65             : 
      66           3 :     stream >> dummy;
      67           3 :     ENSURE(dummy == ':');
      68             : 
      69           3 :     stream >> action;
      70           3 :     ENSURE(action == 'L' || action == 'S');
      71           3 :     m_action = (EAction)action;
      72             : 
      73           3 :     stream >> dummy;
      74           3 :     ENSURE(dummy == '"');
      75             : 
      76           6 :     Path::String pathname;
      77           3 :     std::getline(stream, pathname, L'"');
      78           3 :     m_pathname = Path(pathname);
      79             : 
      80           3 :     stream >> m_size;
      81             : 
      82           3 :     ENSURE(stream.get() == '\n');
      83             :     // NOTE: Don't use good() here - it fails due to a bug in older libc++ versions
      84           3 :     ENSURE(!stream.bad() && !stream.fail());
      85           3 :     ENSURE(stream.get() == WEOF);
      86           3 : }
      87             : 
      88             : 
      89           2 : std::wstring TraceEntry::EncodeAsText() const
      90             : {
      91             :     // Ensure timestamp gets correctly encoded.
      92           2 :     char* oldLocale = setlocale(LC_ALL, "C");
      93             : 
      94           2 :     const wchar_t action = (wchar_t)m_action;
      95             :     wchar_t buf[1000];
      96           2 :     swprintf_s(buf, ARRAY_SIZE(buf), L"%#010f: %c \"%ls\" %lu\n", m_timestamp, action, m_pathname.string().c_str(), (unsigned long)m_size);
      97           2 :     setlocale(LC_ALL, oldLocale);
      98           2 :     return buf;
      99             : }
     100             : 
     101             : 
     102             : //-----------------------------------------------------------------------------
     103             : 
     104         166 : class Trace_Dummy : public ITrace
     105             : {
     106             : public:
     107          83 :     Trace_Dummy(size_t UNUSED(maxSize))
     108          83 :     {
     109             : 
     110          83 :     }
     111             : 
     112        2836 :     virtual void NotifyLoad(const Path& UNUSED(pathname), size_t UNUSED(size))
     113             :     {
     114        2836 :     }
     115             : 
     116          96 :     virtual void NotifyStore(const Path& UNUSED(pathname), size_t UNUSED(size))
     117             :     {
     118          96 :     }
     119             : 
     120           0 :     virtual Status Load(const OsPath& UNUSED(pathname))
     121             :     {
     122           0 :         return INFO::OK;
     123             :     }
     124             : 
     125           0 :     virtual Status Store(const OsPath& UNUSED(pathname)) const
     126             :     {
     127           0 :         return INFO::OK;
     128             :     }
     129             : 
     130           0 :     virtual const TraceEntry* Entries() const
     131             :     {
     132           0 :         return 0;
     133             :     }
     134             : 
     135           0 :     virtual size_t NumEntries() const
     136             :     {
     137           0 :         return 0;
     138             :     }
     139             : };
     140             : 
     141             : 
     142             : //-----------------------------------------------------------------------------
     143             : 
     144             : class Trace : public ITrace
     145             : {
     146             : public:
     147           0 :     Trace(size_t maxSize)
     148           0 :     {
     149           0 :         (void)pool_create(&m_pool, maxSize, sizeof(TraceEntry));
     150           0 :     }
     151             : 
     152           0 :     virtual ~Trace()
     153           0 :     {
     154           0 :         for(size_t i = 0; i < NumEntries(); i++)
     155             :         {
     156           0 :             TraceEntry* entry = (TraceEntry*)(uintptr_t(m_pool.da.base) + i*m_pool.el_size);
     157           0 :             entry->~TraceEntry();
     158             :         }
     159             : 
     160           0 :         (void)pool_destroy(&m_pool);
     161           0 :     }
     162             : 
     163           0 :     virtual void NotifyLoad(const Path& pathname, size_t size)
     164             :     {
     165           0 :         new(Allocate()) TraceEntry(TraceEntry::Load, pathname, size);
     166           0 :     }
     167             : 
     168           0 :     virtual void NotifyStore(const Path& pathname, size_t size)
     169             :     {
     170           0 :         new(Allocate()) TraceEntry(TraceEntry::Store, pathname, size);
     171           0 :     }
     172             : 
     173           0 :     virtual Status Load(const OsPath& pathname)
     174             :     {
     175           0 :         pool_free_all(&m_pool);
     176             : 
     177           0 :         errno = 0;
     178           0 :         FILE* file = sys_OpenFile(pathname, "rt");
     179           0 :         if(!file)
     180           0 :             WARN_RETURN(StatusFromErrno());
     181             : 
     182             :         for(;;)
     183             :         {
     184             :             wchar_t text[500];
     185           0 :             if(!fgetws(text, ARRAY_SIZE(text)-1, file))
     186           0 :                 break;
     187           0 :             new(Allocate()) TraceEntry(text);
     188           0 :         }
     189           0 :         fclose(file);
     190             : 
     191           0 :         return INFO::OK;
     192             :     }
     193             : 
     194           0 :     virtual Status Store(const OsPath& pathname) const
     195             :     {
     196           0 :         errno = 0;
     197           0 :         FILE* file = sys_OpenFile(pathname, "at");
     198           0 :         if(!file)
     199           0 :             WARN_RETURN(StatusFromErrno());
     200           0 :         for(size_t i = 0; i < NumEntries(); i++)
     201             :         {
     202           0 :             std::wstring text = Entries()[i].EncodeAsText();
     203           0 :             fputws(text.c_str(), file);
     204             :         }
     205           0 :         (void)fclose(file);
     206           0 :         return INFO::OK;
     207             :     }
     208             : 
     209           0 :     virtual const TraceEntry* Entries() const
     210             :     {
     211           0 :         return (const TraceEntry*)m_pool.da.base;
     212             :     }
     213             : 
     214           0 :     virtual size_t NumEntries() const
     215             :     {
     216           0 :         return m_pool.da.pos / m_pool.el_size;
     217             :     }
     218             : 
     219             : private:
     220           0 :     void* Allocate()
     221             :     {
     222           0 :         void* p = pool_alloc(&m_pool, 0);
     223           0 :         ENSURE(p);
     224           0 :         return p;
     225             :     }
     226             : 
     227             :     Pool m_pool;
     228             : };
     229             : 
     230             : 
     231          83 : PITrace CreateDummyTrace(size_t maxSize)
     232             : {
     233          83 :     return PITrace(new Trace_Dummy(maxSize));
     234             : }
     235             : 
     236           0 : PITrace CreateTrace(size_t maxSize)
     237             : {
     238           0 :     return PITrace(new Trace(maxSize));
     239           3 : }

Generated by: LCOV version 1.13