Go to the documentation of this file.
8 #include "libmythbase/mythconfig.h"
21 #include <sys/types.h>
27 #if HAVE_POSIX_FADVISE < 1
45 #define LOC QString("FileRingBuf(%1): ").arg(m_filename)
47 static const QStringList
kSubExt {
".ass",
".srt",
".ssa",
".sub",
".txt"};
48 static const QStringList
kSubExtNoCheck {
".ass",
".srt",
".ssa",
".sub",
".txt",
".gif",
".png"};
65 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to open remote file (%1) for write").arg(
m_filename));
88 else if (Timeout >= 0ms)
117 QFileInfo fileInfo(Filename);
118 if (fileInfo.exists() && !fileInfo.isReadable())
120 LOG(VB_GENERAL, LOG_ERR, QString(
"FileRingBuf(%1): File exists but is not readable by MythTV!")
130 [Extension] (
const QString& ext) ->
bool
131 {return ext.contains(Extension);});
132 return (it !=
nullptr);
138 QString vidFileName =
FileInfo.fileName();
139 QString dirName =
FileInfo.absolutePath();
141 QString baseName = vidFileName;
142 int suffixPos = vidFileName.lastIndexOf(QChar(
'.'));
144 baseName = vidFileName.left(suffixPos);
150 const QString findBaseName = baseName.replace(
"[",
"?")
155 for (
const auto & ext :
kSubExt)
156 list += findBaseName + ext;
162 dir.setPath(dirName);
163 const QStringList candidates = dir.entryList(list);
164 for (
const auto & candidate : candidates)
166 QFileInfo
file(dirName +
"/" + candidate);
168 return file.absoluteFilePath();
176 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"OpenFile(%1, %2 ms)")
177 .arg(Filename).arg(Retry.count()));
197 bool islocal = (!
m_filename.startsWith(
"/dev")) &&
202 std::array<char,kReadTestSize> buf {};
208 uint openAttempts = 0;
229 ssize_t ret =
read(
m_fd2, buf.data(), buf.size());
252 LOG(VB_FILE, LOG_DEBUG,
LOC +
253 QString(
"OpenFile(): fadvise sequential "
258 LOG(VB_FILE, LOG_DEBUG,
LOC +
259 QString(
"OpenFile(): fadvise willneed "
271 }
while (openTimer.
elapsed() < Retry);
279 QString extension =
file.completeSuffix().toLower();
285 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"OpenFile(): Could not open."));
290 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"OpenFile(): File too small (%1B).")
296 LOG(VB_GENERAL, LOG_ERR,
LOC +
"OpenFile(): Improper permissions.");
300 LOG(VB_GENERAL, LOG_ERR,
LOC +
"OpenFile(): Cannot seek in file.");
305 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"OpenFile() made %1 attempts in %2 ms")
306 .arg(openAttempts).arg(openTimer.
elapsed().count()));
311 QString dirName =
".";
313 int dirPos =
m_filename.lastIndexOf(QChar(
'/'));
320 QStringList auxFiles;
322 int suffixPos = tmpSubName.lastIndexOf(QChar(
'.'));
325 QString baseName = tmpSubName.left(suffixPos);
326 int extnleng = tmpSubName.size() - baseName.size() - 1;
327 QString extension = tmpSubName.right(extnleng);
331 for (
const auto & ext :
kSubExt)
332 auxFiles += baseName + ext;
339 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"RingBuffer::RingBuffer(): Failed to open remote file (%1)")
368 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Tried to ReOpen a read only file.");
429 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid file descriptor in 'safe_read()'");
440 uint toread = Size - tot;
447 int ret = fstat(
m_fd2, &sb);
448 if (ret == 0 && S_ISREG(sb.st_mode))
455 LOG(VB_FILE, LOG_DEBUG,
LOC +
"not reading, reached EOF");
459 toread =
static_cast<uint>(std::min(sb.st_size - (
m_internalReadPos + tot),
static_cast<long long>(toread)));
460 if (toread < (Size - tot))
463 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"About to reach EOF, reading %1 wanted %2")
464 .arg(toread).arg(Size-tot));
471 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"read(%1) -- begin").arg(toread));
472 ret =
static_cast<int>(
read(
m_fd2,
static_cast<char*
>(
Buffer) + tot, toread));
473 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"read(%1) -> %2 end").arg(toread).arg(ret));
480 LOG(VB_GENERAL, LOG_ERR,
LOC +
"File I/O problem in 'safe_read()'" +
ENO);
488 tot +=
static_cast<uint>(ret);
520 return static_cast<int>(tot);
533 int ret = Remote->
Read(
Buffer,
static_cast<int>(Size));
536 LOG(VB_GENERAL, LOG_ERR,
LOC +
"safe_read(RemoteFile* ...): read failed");
539 LOG(VB_GENERAL, LOG_ERR,
LOC +
"safe_read() failed to seek reset");
545 LOG(VB_FILE, LOG_INFO,
LOC +
"safe_read(RemoteFile* ...): at EOF");
562 long long result = -1;
573 result = fstat(
m_fd2, &sb);
574 if (result == 0 && S_ISREG(sb.st_mode))
601 (Whence == SEEK_CUR && Position == 0)))
609 long long newposition = (SEEK_SET==Whence) ? Position :
m_readPos + Position;
617 LOG(VB_FILE, LOG_INFO,
LOC +
618 QString(
"Seek(): rbrpos: %1 rbwpos: %2\n\t\t\treadpos: %3 internalreadpos: %4")
620 bool used_opt =
false;
627 internal_backbuf = std::min(internal_backbuf, free - min_safety);
629 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek(): internal_backbuf: %1 sba: %2")
630 .arg(internal_backbuf).arg(sba));
631 if (internal_backbuf >= sba)
636 LOG(VB_FILE, LOG_INFO,
LOC +
637 QString(
"Seek(): OPT1 rbrPos: %1 rbwPos: %2"
638 "\n\t\t\treadpos: %3 internalreadpos: %4")
647 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek(): OPT2 rbrPos: %1 sba: %2")
667 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"Seek(): fadvise willneed failed: ") +
ENO);
670 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek to %1 from ignore pos %2 returned %3")
708 long long off_end = 0xDEADBEEF;
709 if (SEEK_END == Whence)
719 newposition = fi.size() - off_end;
731 off_end =
file.size() - newposition;
735 if (off_end != 0xDEADBEEF)
737 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek(): Offset from end: %1").arg(off_end));
740 if (off_end == 250000)
742 LOG(VB_FILE, LOG_INFO,
LOC +
743 QString(
"Seek(): offset from end: %1").arg(off_end) +
744 "\n\t\t\t -- ignoring read ahead thread until next seek.");
756 QString cmd = QString(
"Seek(%1, SEEK_SET) ign ")
761 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
770 QString cmd2 = QString(
"Seek(%1, SEEK_SET) int ")
772 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd2 +
" Failed" +
ENO);
776 QString cmd2 = QString(
"Seek(%1, %2) int ")
778 .arg((SEEK_SET == Whence) ?
"SEEK_SET" :
779 ((SEEK_CUR == Whence) ?
"SEEK_CUR" :
"SEEK_END"));
780 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd2 +
" succeeded");
813 ret = lseek64(
m_fd2, Position, Whence);
826 QString cmd = QString(
"Seek(%1, %2)").arg(Position)
827 .arg((Whence == SEEK_SET) ?
"SEEK_SET" :
828 ((Whence == SEEK_CUR) ?
"SEEK_CUR" :
"SEEK_END"));
829 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
bool ReOpen(const QString &Filename="") override
MythFileBuffer(const QString &Filename, bool Write, bool UseReadAhead, std::chrono::milliseconds Timeout)
#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 bool IsSubtitlePossible(const QString &Extension)
bool ReOpen(const QString &newFilename)
A QElapsedTimer based timer to replace use of QTime as a timer.
static constexpr int8_t O_LARGEFILE
long long GetRealFileSizeInternal(void) const override
def read(device=None, features=[])
static bool CheckPermissions(const QString &Filename)
static void usleep(std::chrono::microseconds time)
void start(void)
starts measuring elapsed time.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
int SafeRead(void *Buffer, uint Size) override
static constexpr int8_t O_STREAMING
bool OpenFile(const QString &Filename, std::chrono::milliseconds Retry=kDefaultOpenTimeout) override
long long SeekInternal(long long Position, int Whence) override
bool IsRegisteredFileForWrite(const QString &file)
long long GetReadPosition(void) const override
long long Seek(long long pos, int whence, long long curpos=-1)
static QString LocalSubtitleFilename(QFileInfo &FileInfo)
static int posix_fadvise(int, off_t, off_t, int)
QStringList GetAuxiliaryFiles(void) const
static constexpr int8_t POSIX_FADV_SEQUENTIAL
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static const QStringList kSubExt
This class supports the writing of recordings to disk.
std::chrono::seconds secsInPast(const QDateTime &past)
bool ReOpen(const QString &newFilename="")
Reopens the file we are writing to or opens a new file.
static const QStringList kSubExtNoCheck
~MythFileBuffer() override
static constexpr int8_t POSIX_FADV_WILLNEED
bool Open(void)
Opens the file we will be writing to.
static constexpr int8_t O_BINARY
bool IsOpen(void) const override
int Read(void *data, int size)
long long GetRealFileSize(void)
GetRealFileSize: returns the current remote file's size.