Memory-mapped daily log file storage. More...
| Header: | #include <LogStorage> |
| Since: | 1.0 |
| Inherits: | QObject |
| QList<QByteArray> | readDayFileLines(QIODevice &device) |
LogStorage provides efficient log file management using memory-mapped files. Creates daily rotating log files in a configurable directory. Supports appending new entries, reading recent logs, clearing, and reloading.
The storage never changes the size of a file while it holds a view of that file. Windows refuses to truncate or shrink a file that any view or section maps (ERROR_USER_MAPPED_FILE), and two LogStorage instances can map the same day file at the same time. So:
A day file is whole lines, then zeros up to maxSize. A reader of a day file uses readDayFileLines(), which stops at the first zero. A reader that reads to the end of the file reads all of the zeros.
All public methods are thread-safe. One mutex guards the mapped view, the line index and the file handle, so two threads cannot copy to the same offset, and readLogs() never sees a half-written line. Node::log() can run on any thread that holds the node, while a LogWidget reads on the GUI thread. The class emits logChanged() after it releases the lock, and prints its own warnings after it releases the lock. So a slot or a message handler that calls back into the same LogStorage does not deadlock.
The lock is per instance. Two LogStorage instances that map the same day file do not share it.
See also LogHandler.
[static] QList<QByteArray> LogStorage::readDayFileLines(QIODevice &device)Reads the lines of a day file from device, from its current position.
A day file holds whole lines, then zeros up to its full size (see rotateLog()). The zeros are not data, and they are most of the file, which is maxSize bytes long. So this function reads in chunks and stops at the first NUL byte. It reads at most one chunk of the zeros. rebuildIndex() uses the same rule for the end of the data.
Returns each line without its '\\n' and without a trailing '\\r'. Empty lines are not returned. A read error ends the read, so the function always returns.