24 #if HAVE_POSIX_FADVISE < 1 26 #define POSIX_FADV_SEQUENTIAL 0 27 #define POSIX_FADV_WILLNEED 0 28 #define POSIX_FADV_DONTNEED 0 43 #define LOC QString("FileRingBuf(%1): ").arg(filename) 46 bool write,
bool readahead,
int timeout_ms)
60 LOG(VB_GENERAL, LOG_ERR,
61 QString(
"RingBuffer::RingBuffer(): Failed to open " 62 "remote file (%1) for write").arg(
filename));
83 else if (timeout_ms >= 0)
112 QFileInfo fileInfo(filename);
113 if (fileInfo.exists() && !fileInfo.isReadable())
115 LOG(VB_GENERAL, LOG_ERR,
LOC +
116 "File exists but is not readable by MythTV!");
125 bool no_subtitle =
false;
140 QString vidFileName = fileInfo.fileName();
141 QString dirName = fileInfo.absolutePath();
143 QString baseName = vidFileName;
144 int suffixPos = vidFileName.lastIndexOf(QChar(
'.'));
146 baseName = vidFileName.left(suffixPos);
152 const QString findBaseName = baseName
161 el += findBaseName + *eit;
167 dir.setPath(dirName);
169 const QStringList candidates = dir.entryList(el);
171 QStringList::const_iterator cit = candidates.begin();
172 for (; cit != candidates.end(); ++cit)
174 QFileInfo fi(dirName +
"/" + *cit);
176 return fi.absoluteFilePath();
184 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"OpenFile(%1, %2 ms)")
185 .arg(lfilename).arg(retry_ms));
217 uint openAttempts = 0;
245 if (ret == 0 && openAttempts > 5 &&
264 LOG(VB_FILE, LOG_DEBUG,
LOC +
265 QString(
"OpenFile(): fadvise sequential " 271 LOG(VB_FILE, LOG_DEBUG,
LOC +
272 QString(
"OpenFile(): fadvise willneed " 292 oldfile = fi.lastModified().toUTC()
294 QString extension = fi.completeSuffix().toLower();
300 LOG(VB_GENERAL, LOG_ERR,
LOC +
301 QString(
"OpenFile(): Could not open."));
307 LOG(VB_GENERAL, LOG_ERR,
LOC +
308 QString(
"OpenFile(): File too small (%1B).")
316 LOG(VB_GENERAL, LOG_ERR,
LOC +
317 "OpenFile(): Improper permissions.");
322 LOG(VB_GENERAL, LOG_ERR,
LOC +
323 "OpenFile(): Cannot seek in file.");
330 LOG(VB_FILE, LOG_INFO,
331 LOC + QString(
"OpenFile() made %1 attempts in %2 ms")
332 .arg(openAttempts).arg(openTimer.
elapsed()));
338 QString dirName =
".";
340 int dirPos =
filename.lastIndexOf(QChar(
'/'));
343 tmpSubName =
filename.mid(dirPos + 1);
347 QString baseName = tmpSubName;
348 QString extension = tmpSubName;
349 QStringList auxFiles;
351 int suffixPos = tmpSubName.lastIndexOf(QChar(
'.'));
354 baseName = tmpSubName.left(suffixPos);
355 int extnleng = tmpSubName.size() - baseName.size() - 1;
356 extension = tmpSubName.right(extnleng);
361 QStringList::const_iterator eit =
subExt.begin();
362 for (; eit !=
subExt.end(); ++eit)
363 auxFiles += baseName + *eit;
368 retry_ms, &auxFiles);
371 LOG(VB_GENERAL, LOG_ERR,
LOC +
372 QString(
"RingBuffer::RingBuffer(): Failed to open remote " 406 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Tried to ReOpen a read only file.");
455 unsigned zerocnt = 0;
459 LOG(VB_GENERAL, LOG_ERR,
LOC +
460 "Invalid file descriptor in 'safe_read()'");
471 uint toread = sz - tot;
478 int ret = fstat(
fd2, &sb);
479 if (ret == 0 && S_ISREG(sb.st_mode))
486 LOG(VB_FILE, LOG_DEBUG,
LOC +
"not reading, reached EOF");
492 if (toread < (sz-tot))
495 LOG(VB_FILE, LOG_DEBUG,
496 LOC + QString(
"About to reach EOF, reading %1 wanted %2")
497 .arg(toread).arg(sz-tot));
504 LOG(VB_FILE, LOG_DEBUG,
LOC +
505 QString(
"read(%1) -- begin").arg(toread));
506 ret =
read(
fd2, (
char *)data + tot, toread);
507 LOG(VB_FILE, LOG_DEBUG,
LOC +
508 QString(
"read(%1) -> %2 end").arg(toread).arg(ret));
515 LOG(VB_GENERAL, LOG_ERR,
516 LOC +
"File I/O problem in 'safe_read()'" +
ENO);
570 int ret = rf->
Read(data, sz);
573 LOG(VB_GENERAL, LOG_ERR,
LOC +
574 "safe_read(RemoteFile* ...): read failed");
583 LOG(VB_FILE, LOG_INFO,
LOC +
584 "safe_read(RemoteFile* ...): at EOF");
612 ret = fstat(
fd2, &sb);
613 if (ret == 0 && S_ISREG(sb.st_mode))
644 ((whence == SEEK_SET && pos ==
readpos) ||
645 (whence == SEEK_CUR && pos == 0)))
655 long long new_pos = (SEEK_SET==whence) ? pos :
readpos + pos;
660 (SEEK_SET==whence || SEEK_CUR==whence))
664 LOG(VB_FILE, LOG_INFO,
LOC +
665 QString(
"Seek(): rbrpos: %1 rbwpos: %2" 666 "\n\t\t\treadpos: %3 internalreadpos: %4")
669 bool used_opt =
false;
676 int internal_backbuf =
678 internal_backbuf = min(internal_backbuf, free - min_safety);
679 long long sba =
readpos - new_pos;
680 LOG(VB_FILE, LOG_INFO,
LOC +
681 QString(
"Seek(): internal_backbuf: %1 sba: %2")
682 .arg(internal_backbuf).arg(sba));
683 if (internal_backbuf >= sba)
688 LOG(VB_FILE, LOG_INFO,
LOC +
689 QString(
"Seek(): OPT1 rbrpos: %1 rbwpos: %2" 690 "\n\t\t\treadpos: %3 internalreadpos: %4")
699 LOG(VB_FILE, LOG_INFO,
LOC +
700 QString(
"Seek(): OPT2 rbrpos: %1 sba: %2")
720 LOG(VB_FILE, LOG_DEBUG,
LOC +
721 QString(
"Seek(): fadvise willneed " 726 LOG(VB_FILE, LOG_INFO,
LOC +
727 QString(
"Seek to %1 from ignore pos %2 returned %3")
765 long long off_end = 0xDEADBEEF;
766 if (SEEK_END == whence)
776 new_pos = fi.size() - off_end;
788 off_end = fi.size() - new_pos;
792 if (off_end != 0xDEADBEEF)
794 LOG(VB_FILE, LOG_INFO,
LOC +
795 QString(
"Seek(): Offset from end: %1").arg(off_end));
798 if (off_end == 250000)
800 LOG(VB_FILE, LOG_INFO,
LOC +
801 QString(
"Seek(): offset from end: %1").arg(off_end) +
802 "\n\t\t\t -- ignoring read ahead thread until next seek.");
814 QString cmd = QString(
"Seek(%1, SEEK_SET) ign ")
819 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
828 QString cmd2 = QString(
"Seek(%1, SEEK_SET) int ")
830 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd2 +
" Failed" +
ENO);
834 QString cmd2 = QString(
"Seek(%1, %2) int ")
836 .arg((SEEK_SET == whence) ?
"SEEK_SET" :
837 ((SEEK_CUR == whence) ?
"SEEK_CUR" :
"SEEK_END"));
838 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd2 +
" succeeded");
871 ret = lseek64(
fd2, pos, whence);
887 QString cmd = QString(
"Seek(%1, %2)").arg(pos)
888 .arg((whence == SEEK_SET) ?
"SEEK_SET" :
889 ((whence == SEEK_CUR) ?
"SEEK_CUR" :
"SEEK_END"));
890 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
def write(text, progress=True)
bool IsOpen(void) const override
Returns true if open for either reading or writing.
A QElapsedTimer based timer to replace use of QTime as a timer.
bool ReOpen(QString newFilename="") override
void StartReads(void)
????
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
long long internalreadpos
void CalcReadAheadThresh(void)
Calculates fill_min, fill_threshold, and readblocksize from the estimated effective bitrate of the st...
def read(device=None, features=[])
long long GetRealFileSize(void)
GetRealFileSize: returns the current remote file's size.
int safe_read(void *data, uint sz) override
static int posix_fadvise(int, off_t, off_t, int)
long long WriterSeek(long long pos, int whence, bool has_lock=false)
Calls ThreadedFileWriter::Seek(long long,int).
bool OpenFile(const QString &lfilename, uint retry_ms=kDefaultOpenTimeout) override
Opens a file for reading.
FileRingBuffer(const QString &lfilename, bool write, bool readahead, int timeout_ms)
long long SeekInternal(long long pos, int whence) override
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
long long GetReadPosition(void) const override
Returns how far into the file we have read.
int Read(void *data, int size)
static bool check_permissions(const QString &filename)
Returns false iff file exists and has incorrect permissions.
#define ENO
This can be appended to the LOG args with "+".
long long GetFileSize(void) const
GetFileSize: returns the remote file's size at the time it was first opened Will query the server in ...
static QString local_sub_filename(QFileInfo &fileInfo)
int elapsed(void) const
Returns milliseconds elapsed since last start() or restart()
#define POSIX_FADV_WILLNEED
bool Open(void)
Opens the file we will be writing to.
#define LOG(_MASK_, _LEVEL_, _STRING_)
static QStringList subExtNoCheck
LiveTVChain * livetvchain
#define POSIX_FADV_SEQUENTIAL
bool ReOpen(QString newFilename)
QWaitCondition generalWait
Condition to signal that the read ahead thread is running.
This class supports the writing of recordings to disk.
bool ReOpen(QString newFilename="")
Reopens the file we are writing to or opens a new file.
static bool is_subtitle_possible(const QString &extension)
void ResetReadAhead(long long newinternal)
Restart the read-ahead thread at the 'newinternal' position.
QStringList GetAuxiliaryFiles(void) const
Implements a file/stream reader/writer.
long long Seek(long long pos, int whence, long long curpos=-1)
static void usleep(unsigned long time)
bool IsRegisteredFileForWrite(const QString &file)
static QStringList subExt
void start(void)
starts measuring elapsed time.
long long GetRealFileSizeInternal(void) const override