14#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
15#include <QtSystemDetection>
28#define LOC QString("TFW(%1:%2): ").arg(m_filename).arg(m_fd)
84 if (!newFilename.isEmpty())
110 LOG(VB_GENERAL, LOG_ERR,
LOC +
118 LOG(VB_FILE, LOG_INFO,
LOC +
"Open() successful");
121 _setmode(
m_fd, _O_BINARY);
207 while (written < count)
215 LOG(VB_GENERAL, LOG_ERR,
LOC +
216 "Maximum buffer size exceeded."
217 "\n\t\t\tfile will be truncated, no further writing "
219 "\n\t\t\tThis generally indicates your disk performance "
220 "\n\t\t\tis insufficient to deal with the number of on-going "
221 "\n\t\t\trecordings, or you have a disk failure.");
227 LOG(VB_GENERAL, LOG_WARNING,
LOC +
228 "Maximum buffer size exceeded."
229 "\n\t\t\tThis generally indicates your disk performance "
230 "\n\t\t\tis insufficient or you have a disk failure.");
236 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
237 QString(
"Taking a long time waiting to write.. "
238 "buffer size %1 (needing %2, %3 to go)")
269 const char *cdata = (
const char*) data + written;
270 buf->
data.insert(buf->
data.end(), cdata, cdata+towrite);
284 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"Write(*, %1) total %2 cnt %3")
310 LOG(VB_GENERAL, LOG_WARNING,
LOC +
311 QString(
"Taking a long time to flush.. buffer size %1")
316 return lseek(
m_fd, pos, whence);
331 LOG(VB_GENERAL, LOG_WARNING,
LOC +
332 QString(
"Taking a long time to flush.. buffer size %1")
363#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
417 signal(SIGXFSZ, SIG_IGN);
427 minWriteTimer.
start();
428 lastRegisterTimer.
start();
430 uint64_t total_written = 0LL;
459 auto mwte = minWriteTimer.
elapsed();
478 minWriteTimer.
start();
482 const void *data = (buf->
data).data();
485 bool write_ok =
true;
489 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"write(%1) cnt %2 total %3")
500 int ret =
write(
m_fd, (
char *)data + tot, sz - tot);
506 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Got EAGAIN.");
511 LOG(VB_GENERAL, LOG_ERR,
LOC +
"File I/O " +
512 QString(
" errcnt: %1").arg(errcnt) +
ENO);
515 if ((errcnt >= 3) || (ENOSPC == errno) || (EFBIG == errno))
525 total_written += ret;
526 LOG(VB_FILE, LOG_DEBUG,
LOC +
527 QString(
"total written so far: %1 bytes")
528 .arg(total_written));
539 if (lastRegisterTimer.
elapsed() >= 10s)
551 LOG(VB_GENERAL, LOG_WARNING,
LOC +
552 QString(
"write(%1) cnt %2 total %3 -- took a long time, %4 ms")
557 if (!write_ok && ((EFBIG == errno) || (ENOSPC == errno)))
564 "Maximum file size exceeded by '%1'"
566 "You must either change the process ulimits, configure"
568 "your operating system with \"Large File\" support, "
571 "a filesystem which supports 64-bit or 128-bit files."
573 "HINT: FAT32 is a 32-bit filesystem.";
577 "No space left on the device for file '%1'"
579 "file will be truncated, no further writing "
593 QDateTime cur_m_60 = cur.addSecs(-60);
598 if (((*it)->lastUsed < cur_m_60) ||
599 ((*it)->data.capacity() > 3 * (*it)->data.size() &&
600 (*it)->data.capacity() > 64 * 1024LL))
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
void RegisterFileForWrite(const QString &file, uint64_t size=0LL)
void UnregisterFileForWrite(const QString &file)
A QElapsedTimer based timer to replace use of QTime as a timer.
std::chrono::milliseconds restart(void)
Returns milliseconds elapsed since last start() or restart() and resets the count.
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
void start(void)
starts measuring elapsed time.
void run(void) override
Runs ThreadedFileWriter::SyncLoop(void)
ThreadedFileWriter * m_parent
void run(void) override
Runs ThreadedFileWriter::DiskLoop(void)
ThreadedFileWriter * m_parent
void DiskLoop(void)
The thread run method that actually calls writes to disk.
void SetWriteBufferMinWriteSize(uint newMinSize=kMinWriteSize)
Sets the minumum number of bytes to write to disk in a single write.
QWaitCondition m_bufferHasData
TFWWriteThread * m_writeThread
void Sync(void) const
Flush data written to the file descriptor to disk.
bool SetBlocking(bool block=true)
Set write blocking mode While in blocking mode, ThreadedFileWriter::Write will wait for buffers to be...
QWaitCondition m_bufferEmpty
long long Seek(long long pos, int whence)
Seek to a position within stream; May be unsafe.
static const uint kMaxBufferSize
friend class TFWSyncThread
bool Open(void)
Opens the file we will be writing to.
void Flush(void)
Allow DiskLoop() to flush buffer completely ignoring low watermark.
static const uint kMinWriteSize
Minimum to write to disk in a single write, when not flushing buffer.
void TrimEmptyBuffers(void)
friend class TFWWriteThread
QWaitCondition m_bufferWasFreed
int Write(const void *data, uint count)
Writes data to the end of the write buffer.
QList< TFWBuffer * > m_emptyBuffers
bool ReOpen(const QString &newFilename="")
Reopens the file we are writing to or opens a new file.
void SyncLoop(void)
The thread run method that calls Sync(void).
static const uint kMaxBlockSize
Maximum block size to write at a time.
QList< TFWBuffer * > m_writeBuffers
~ThreadedFileWriter()
Commits all writes and closes the file.
QWaitCondition m_bufferSyncWait
TFWSyncThread * m_syncThread
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define ENO
This can be appended to the LOG args with "+".
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
def write(text, progress=True)