0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 00:31:02 +08:00
easy_profiler/profiler_gui/file_reader.cpp

242 lines
6.8 KiB
C++
Raw Normal View History

//
// Created by vzarubkin on 29.10.19.
//
#include <fstream>
#include <QFile>
#include <easy/writer.h>
#include "common_functions.h"
#include "globals.h"
#include "file_reader.h"
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
FileReader::FileReader()
{
}
FileReader::~FileReader()
{
interrupt();
}
const bool FileReader::isFile() const
{
return m_isFile;
}
const bool FileReader::isSaving() const
{
return m_jobType == JobType::Saving;
}
const bool FileReader::isLoading() const
{
return m_jobType == JobType::Loading;
}
const bool FileReader::isSnapshot() const
{
return m_isSnapshot;
}
bool FileReader::done() const
{
return m_bDone.load(std::memory_order_acquire);
}
int FileReader::progress() const
{
return m_progress.load(std::memory_order_acquire);
}
unsigned int FileReader::size() const
{
return m_size.load(std::memory_order_acquire);
}
const QString& FileReader::filename() const
{
return m_filename;
}
void FileReader::load(const QString& _filename)
{
interrupt();
m_jobType = JobType::Loading;
m_isFile = true;
m_isSnapshot = false;
m_filename = _filename;
m_thread = std::thread([this] (bool _enableStatistics)
{
const auto size = fillTreesFromFile(m_progress, m_filename.toStdString().c_str(), m_beginEndTime, m_serializedBlocks,
m_serializedDescriptors, m_descriptors, m_blocks, m_blocksTree,
m_bookmarks, m_descriptorsNumberInFile, m_version, m_pid,
_enableStatistics, m_errorMessage);
m_size.store(size, std::memory_order_release);
m_progress.store(100, std::memory_order_release);
m_bDone.store(true, std::memory_order_release);
}, EASY_GLOBALS.enable_statistics);
}
void FileReader::load(std::stringstream& _stream)
{
interrupt();
m_jobType = JobType::Loading;
m_isFile = false;
m_isSnapshot = false;
m_filename.clear();
#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__llvm__)
// gcc 4 has a known bug which has been solved in gcc 5:
// std::stringstream has no swap() method :(
// have to copy all contents... Use gcc 5 or higher!
#pragma message "Warning: in gcc 4 and lower std::stringstream has no swap()! Memory consumption may increase! Better use gcc 5 or higher instead."
m_stream.str(_stream.str());
#else
m_stream.swap(_stream);
#endif
m_thread = std::thread([this] (bool _enableStatistics)
{
std::ofstream cache_file(NETWORK_CACHE_FILE, std::fstream::binary);
if (cache_file.is_open())
{
cache_file << m_stream.str();
cache_file.close();
}
const auto size = fillTreesFromStream(m_progress, m_stream, m_beginEndTime, m_serializedBlocks, m_serializedDescriptors,
m_descriptors, m_blocks, m_blocksTree, m_bookmarks, m_descriptorsNumberInFile,
m_version, m_pid, _enableStatistics, m_errorMessage);
m_size.store(size, std::memory_order_release);
m_progress.store(100, std::memory_order_release);
m_bDone.store(true, std::memory_order_release);
}, EASY_GLOBALS.enable_statistics);
}
void FileReader::save(const QString& _filename, profiler::timestamp_t _beginTime, profiler::timestamp_t _endTime,
const profiler::SerializedData& _serializedDescriptors,
const profiler::descriptors_list_t& _descriptors, profiler::block_id_t descriptors_count,
const profiler::thread_blocks_tree_t& _trees, const profiler::bookmarks_t& bookmarks,
profiler::block_getter_fn block_getter, profiler::processid_t _pid, bool snapshotMode)
{
interrupt();
m_jobType = JobType::Saving;
m_isFile = true;
m_isSnapshot = snapshotMode;
m_filename = _filename;
auto serializedDescriptors = std::ref(_serializedDescriptors);
auto descriptors = std::ref(_descriptors);
auto trees = std::ref(_trees);
auto bookmarksRef = std::ref(bookmarks);
m_thread = std::thread([=] (profiler::block_getter_fn getter)
{
const QString tmpFile = m_filename + ".tmp";
const auto result = writeTreesToFile(m_progress, tmpFile.toStdString().c_str(), serializedDescriptors,
descriptors, descriptors_count, trees, bookmarksRef, getter,
_beginTime, _endTime, _pid, m_errorMessage);
if (result == 0 || !m_errorMessage.str().empty())
{
// Remove temporary file in case of error
QFile::remove(tmpFile);
}
else
{
// Remove old file if exists
{
QFile out(m_filename);
if (out.exists())
out.remove();
}
QFile::rename(tmpFile, m_filename);
}
m_progress.store(100, std::memory_order_release);
m_bDone.store(true, std::memory_order_release);
}, std::move(block_getter));
}
void FileReader::interrupt()
{
join();
m_bDone.store(false, std::memory_order_release);
m_size.store(0, std::memory_order_release);
m_serializedBlocks.clear();
m_serializedDescriptors.clear();
m_descriptors.clear();
m_blocks.clear();
m_blocksTree.clear();
m_bookmarks.clear();
m_descriptorsNumberInFile = 0;
m_version = 0;
m_pid = 0;
m_jobType = JobType::Idle;
m_isSnapshot = false;
profiler_gui::clear_stream(m_stream);
profiler_gui::clear_stream(m_errorMessage);
}
void FileReader::get(profiler::SerializedData& _serializedBlocks, profiler::SerializedData& _serializedDescriptors,
profiler::descriptors_list_t& _descriptors, profiler::blocks_t& _blocks,
profiler::thread_blocks_tree_t& _trees, profiler::bookmarks_t& bookmarks,
profiler::BeginEndTime& beginEndTime, uint32_t& _descriptorsNumberInFile, uint32_t& _version,
profiler::processid_t& _pid, QString& _filename)
{
if (done())
{
m_serializedBlocks.swap(_serializedBlocks);
m_serializedDescriptors.swap(_serializedDescriptors);
profiler::descriptors_list_t(std::move(m_descriptors)).swap(_descriptors);
m_blocks.swap(_blocks);
m_blocksTree.swap(_trees);
m_bookmarks.swap(bookmarks);
m_filename.swap(_filename);
beginEndTime = m_beginEndTime;
_descriptorsNumberInFile = m_descriptorsNumberInFile;
_version = m_version;
_pid = m_pid;
}
}
void FileReader::join()
{
m_progress.store(-100, std::memory_order_release);
if (m_thread.joinable())
{
m_thread.join();
}
m_progress.store(0, std::memory_order_release);
}
QString FileReader::getError() const
{
return QString(m_errorMessage.str().c_str());
}