24#define LOC QString("TFW(%1:%2): ").arg(m_filename).arg(m_fd)
80 if (!newFilename.isEmpty())
106 LOG(VB_GENERAL, LOG_ERR,
LOC +
114 LOG(VB_FILE, LOG_INFO,
LOC +
"Open() successful");
117 _setmode(
m_fd, _O_BINARY);
203 while (written < count)
211 LOG(VB_GENERAL, LOG_ERR,
LOC +
212 "Maximum buffer size exceeded."
213 "\n\t\t\tfile will be truncated, no further writing "
215 "\n\t\t\tThis generally indicates your disk performance "
216 "\n\t\t\tis insufficient to deal with the number of on-going "
217 "\n\t\t\trecordings, or you have a disk failure.");
223 LOG(VB_GENERAL, LOG_WARNING,
LOC +
224 "Maximum buffer size exceeded."
225 "\n\t\t\tThis generally indicates your disk performance "
226 "\n\t\t\tis insufficient or you have a disk failure.");
232 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
233 QString(
"Taking a long time waiting to write.. "
234 "buffer size %1 (needing %2, %3 to go)")
265 const char *cdata = (
const char*) data + written;
266 buf->
data.insert(buf->
data.end(), cdata, cdata+towrite);
280 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"Write(*, %1) total %2 cnt %3")
306 LOG(VB_GENERAL, LOG_WARNING,
LOC +
307 QString(
"Taking a long time to flush.. buffer size %1")
327 LOG(VB_GENERAL, LOG_WARNING,
LOC +
328 QString(
"Taking a long time to flush.. buffer size %1")
359#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
413 signal(SIGXFSZ, SIG_IGN);
423 minWriteTimer.
start();
424 lastRegisterTimer.
start();
426 uint64_t total_written = 0LL;
455 auto mwte = minWriteTimer.
elapsed();
474 minWriteTimer.
start();
478 const void *data = (buf->
data).data();
481 bool write_ok =
true;
485 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"write(%1) cnt %2 total %3")
496 int ret =
write(
m_fd, (
char *)data + tot, sz - tot);
502 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Got EAGAIN.");
507 LOG(VB_GENERAL, LOG_ERR,
LOC +
"File I/O " +
508 QString(
" errcnt: %1").arg(errcnt) +
ENO);
511 if ((errcnt >= 3) || (ENOSPC == errno) || (EFBIG == errno))
521 total_written += ret;
522 LOG(VB_FILE, LOG_DEBUG,
LOC +
523 QString(
"total written so far: %1 bytes")
524 .arg(total_written));
535 if (lastRegisterTimer.
elapsed() >= 10s)
547 LOG(VB_GENERAL, LOG_WARNING,
LOC +
548 QString(
"write(%1) cnt %2 total %3 -- took a long time, %4 ms")
553 if (!write_ok && ((EFBIG == errno) || (ENOSPC == errno)))
560 "Maximum file size exceeded by '%1'"
562 "You must either change the process ulimits, configure"
564 "your operating system with \"Large File\" support, "
567 "a filesystem which supports 64-bit or 128-bit files."
569 "HINT: FAT32 is a 32-bit filesystem.";
573 "No space left on the device for file '%1'"
575 "file will be truncated, no further writing "
589 QDateTime cur_m_60 = cur.addSecs(-60);
594 if (((*it)->lastUsed < cur_m_60) ||
595 ((*it)->data.capacity() > 3 * (*it)->data.size() &&
596 (*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)