/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see .
*/
#ifndef LOGRING_H
#define LOGRING_H
#include
#include
#include
#include
/**
@brief The LogRing class
Fixed-capacity, always-on in-memory ring of the most recent log
lines. Discussion #644 (step 3): the ring exists as forward-compatible
infrastructure for a future crash-flush (step 4, not implemented
here) as well as an on-demand "what just happened" snapshot, so its
entries are stored pre-formatted as plain bytes in storage
preallocated once at construction -- append() never allocates.
Entries are fixed-size slots rather than a byte-packed ring: with
kCapacityEntries * kEntryBytes chosen to land exactly on the 2 MiB
budget, this keeps wraparound trivial (whole-slot overwrite, so a
slot is always either fully the old entry or fully the new one --
no torn entries) at the cost of truncating any single line to
kEntryBytes, independently of the logger's own (larger) per-message
truncation.
Thread-safe via a plain QMutex. This is *not* the lock-free design
discussion #644 specifies for a signal-handler crash path (step 4)
-- no signal handler is installed by this code, so nothing calls
into the ring from inside a signal context.
*/
class LogRing
{
public:
static constexpr int kCapacityEntries = 4096;
static constexpr int kEntryBytes = 512; // 4096 * 512 = 2 MiB total
LogRing();
/// Append one already-formatted, already-truncated log line.
/// Bytes beyond kEntryBytes - 1 are dropped with a truncation marker.
void append(const QByteArray &line);
/// Snapshot of the entries currently held, oldest first.
QVector snapshot() const;
void clear();
private:
struct Entry {
char data[kEntryBytes] = {};
int length = 0;
};
mutable QMutex m_mutex;
std::vector m_entries; // preallocated once, capacity fixed
int m_next_index = 0;
int m_count = 0;
};
#endif // LOGRING_H