AuroraRuntime/Source/Logging/Sinks/RingBuffer.cpp

158 lines
3.6 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RingBuffer.cpp
Date: 2022-1-24
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "RingBuffer.hpp"
namespace Aurora::Logging::Sinks
{
RingBufferSink::RingBufferSink(AuUInt32 count) : maxCount_(count)
{
}
bool RingBufferSink::Init()
{
AuTryReserve(this->logBuffer_, this->maxCount_);
return true;
}
void RingBufferSink::OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg)
{}
bool RingBufferSink::OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg)
{
bool drop {};
TryAddMsg(level, msg, drop);
return false;
}
bool RingBufferSink::TryAddMsg(AuUInt8 level, const ConsoleMessage &msg, bool &drop)
{
AU_LOCK_GUARD(this->logMutex_);
try
{
auto nextIndex = this->index_++;
if (this->logBuffer_.size() < this->maxCount_)
{
if (nextIndex >= this->logBuffer_.size())
{
return AuTryInsert(this->logBuffer_, msg);
}
}
this->logBuffer_[nextIndex % this->logBuffer_.size()] = msg;
}
catch (...)
{
return false;
}
return true;
}
void RingBufferSink::SaveToPath(const AuString &path, bool binary)
{
auto file = AuIOFS::OpenWriteUnique(path);
if (!file)
{
return;
}
for (const auto &message : Export())
{
if (binary)
{
AuByteBuffer buffer;
message.Write(buffer);
file->Write(AuMemoryViewRead(buffer));
}
else
{
file->Write(message.ToPersistentString());
file->Write(AuLocale::NewLine());
}
}
}
AuList<ConsoleMessage> RingBufferSink::Export()
{
AU_LOCK_GUARD(this->logMutex_);
AuList<ConsoleMessage> messages;
auto nextIndex = this->index_;
if (nextIndex >= this->logBuffer_.size())
{
auto nextIndex = (this->index_ + 1) % this->logBuffer_.size();
for (AU_ITERATE_N_TO_X(i, nextIndex, this->logBuffer_.size()))
{
messages.push_back(this->logBuffer_[i]);
}
for (AU_ITERATE_N_TO_X(i, 0, nextIndex))
{
messages.push_back(this->logBuffer_[i]);
}
}
else
{
for (AU_ITERATE_N_TO_X(i, 0, this->logBuffer_.size()))
{
messages.push_back(this->logBuffer_[i]);
}
}
return messages;
}
void RingBufferSink::PreviewRingBuffer(AuConsumer<AuPair<const AuList<ConsoleMessage> &, AuUInt32>> callback)
{
if (!callback)
{
return;
}
AU_LOCK_GUARD(this->logMutex_);
callback(AuMakePair(AuConstReference(this->logBuffer_), this->index_));
}
void RingBufferSink::OnFlush()
{
}
IBasicSinkRB *NewRingBufferNew(AuUInt32 maxLogEntries)
{
try
{
auto logger = _new RingBufferSink(maxLogEntries);
if (!logger)
{
return nullptr;
}
if (!logger->Init())
{
return nullptr;
}
return logger;
}
catch (...)
{
return {};
}
}
void NewRingBufferRelease(IBasicSink *logger)
{
AuSafeDelete<RingBufferSink *>(logger);
}
}