MythTV  master
filetransfer.cpp
Go to the documentation of this file.
1 // C++ headers
2 #include <utility>
3 
4 // Qt headers
5 #include <QCoreApplication>
6 #include <QDateTime>
7 #include <QFileInfo>
8 
9 // MythTV
10 #include "libmythbase/mythdate.h"
12 #include "libmythbase/mythsocket.h"
15 
16 // MythBackend
17 #include "filetransfer.h"
18 
20  bool usereadahead, std::chrono::milliseconds timeout) :
21  ReferenceCounter(QString("BEFileTransfer:%1").arg(filename)),
22  m_pginfo(new ProgramInfo(filename)),
23  m_rbuffer(MythMediaBuffer::Create(filename, false, usereadahead, timeout, true)),
24  m_sock(remote)
25 {
27  if (m_rbuffer && m_rbuffer->IsOpen())
28  m_rbuffer->Start();
29 }
30 
32  ReferenceCounter(QString("BEFileTransfer:%1").arg(filename)),
33  m_pginfo(new ProgramInfo(filename)),
34  m_rbuffer(MythMediaBuffer::Create(filename, write)),
35  m_sock(remote), m_writemode(write)
36 {
38 
39  if (write)
40  remote->SetReadyReadCallbackEnabled(false);
41  if (m_rbuffer)
42  m_rbuffer->Start();
43 }
44 
46 {
47  Stop();
48 
49  if (m_sock) // BEFileTransfer becomes responsible for deleting the socket
50  m_sock->DecrRef();
51 
52  if (m_rbuffer)
53  {
54  delete m_rbuffer;
55  m_rbuffer = nullptr;
56  }
57 
58  if (m_pginfo)
59  {
61  delete m_pginfo;
62  }
63 }
64 
66 {
67  return m_rbuffer && m_rbuffer->IsOpen();
68 }
69 
70 bool BEFileTransfer::ReOpen(const QString& newFilename)
71 {
72  if (!m_writemode)
73  return false;
74 
75  if (m_rbuffer)
76  return m_rbuffer->ReOpen(newFilename);
77 
78  return false;
79 }
80 
82 {
83  if (m_readthreadlive)
84  {
85  m_readthreadlive = false;
86  LOG(VB_FILE, LOG_INFO, "calling StopReads()");
87  if (m_rbuffer)
89  QMutexLocker locker(&m_lock);
90  m_readsLocked = true;
91  }
92 
93  if (m_writemode)
94  if (m_rbuffer)
96 
97  if (m_pginfo)
99 }
100 
102 {
103  LOG(VB_FILE, LOG_INFO, "calling StopReads()");
104  if (m_rbuffer)
105  m_rbuffer->StopReads();
106  QMutexLocker locker(&m_lock);
107  m_readsLocked = true;
108 
109  if (m_pginfo)
111 }
112 
114 {
115  LOG(VB_FILE, LOG_INFO, "calling StartReads()");
116  if (m_rbuffer)
118  {
119  QMutexLocker locker(&m_lock);
120  m_readsLocked = false;
121  }
122  m_readsUnlockedCond.wakeAll();
123 
124  if (m_pginfo)
126 }
127 
129 {
130  if (!m_readthreadlive || !m_rbuffer)
131  return -1;
132 
133  int tot = 0;
134  int ret = 0;
135 
136  QMutexLocker locker(&m_lock);
137  while (m_readsLocked)
138  m_readsUnlockedCond.wait(&m_lock, 100 /*ms*/);
139 
140  m_requestBuffer.resize(std::max((size_t)std::max(size,0) + 128, m_requestBuffer.size()));
141  char *buf = (m_requestBuffer).data();
142  while (tot < size && !m_rbuffer->GetStopReads() && m_readthreadlive)
143  {
144  int request = size - tot;
145 
146  ret = m_rbuffer->Read(buf, request);
147 
148  if (m_rbuffer->GetStopReads() || ret <= 0)
149  break;
150 
151  if (m_sock->Write(buf, (uint)ret) != ret)
152  {
153  tot = -1;
154  break;
155  }
156 
157  tot += ret;
158  if (ret < request)
159  break; // we hit eof
160  }
161 
162  if (m_pginfo)
164 
165  return (ret < 0) ? -1 : tot;
166 }
167 
169 {
170  if (!m_writemode || !m_rbuffer)
171  return -1;
172 
173  int tot = 0;
174  int ret = 0;
175 
176  QMutexLocker locker(&m_lock);
177 
178  m_requestBuffer.resize(std::max((size_t)std::max(size,0) + 128, m_requestBuffer.size()));
179  char *buf = (m_requestBuffer).data();
180  int attempts = 0;
181 
182  while (tot < size)
183  {
184  int request = size - tot;
185  int received = m_sock->Read(buf, (uint)request, 200ms);
186 
187  if (received != request)
188  {
189  LOG(VB_FILE, LOG_DEBUG,
190  QString("WriteBlock(): Read failed. Requested %1 got %2")
191  .arg(request).arg(received));
192  if (received < 0)
193  {
194  // An error occurred, abort immediately
195  break;
196  }
197  if (received == 0)
198  {
199  attempts++;
200  if (attempts > 3)
201  {
202  LOG(VB_FILE, LOG_ERR,
203  "WriteBlock(): Read tried too many times, aborting "
204  "(client or network too slow?)");
205  break;
206  }
207  continue;
208  }
209  }
210  attempts = 0;
211  ret = m_rbuffer->Write(buf, received);
212  if (ret <= 0)
213  {
214  LOG(VB_FILE, LOG_DEBUG,
215  QString("WriteBlock(): Write failed. Requested %1 got %2")
216  .arg(received).arg(ret));
217  break;
218  }
219 
220  tot += received;
221  }
222 
223  if (m_pginfo)
225 
226  return (ret < 0) ? -1 : tot;
227 }
228 
229 long long BEFileTransfer::Seek(long long curpos, long long pos, int whence)
230 {
231  if (m_pginfo)
233 
234  if (!m_rbuffer)
235  return -1;
236  if (!m_readthreadlive)
237  return -1;
238 
239  m_ateof = false;
240 
241  Pause();
242 
243  if (whence == SEEK_CUR)
244  {
245  long long desired = curpos + pos;
246  long long realpos = m_rbuffer->GetReadPosition();
247 
248  pos = desired - realpos;
249  }
250 
251  long long ret = m_rbuffer->Seek(pos, whence);
252 
253  Unpause();
254 
255  if (m_pginfo)
257 
258  return ret;
259 }
260 
262 {
263  if (m_pginfo)
265 
266  return m_rbuffer ? m_rbuffer->GetRealFileSize() : 0;
267 }
268 
270 {
271  if (!m_rbuffer)
272  return {};
273 
274  return m_rbuffer->GetFilename();
275 }
276 
278 {
279  if (m_pginfo)
281 
282  if (m_rbuffer)
283  m_rbuffer->SetOldFile(fast);
284 }
285 
286 /* vim: set expandtab tabstop=4 shiftwidth=4: */
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89
MythMediaBuffer::ReOpen
virtual bool ReOpen(const QString &="")
Definition: mythmediabuffer.h:145
MythMediaBuffer::Seek
long long Seek(long long Position, int Whence, bool HasLock=false)
Definition: mythmediabuffer.cpp:479
MythMediaBuffer::StopReads
void StopReads(void)
Definition: mythmediabuffer.cpp:669
mythburn.write
def write(text, progress=True)
Definition: mythburn.py:308
MythMediaBuffer::Write
int Write(const void *Buffer, uint Count)
Writes buffer to ThreadedFileWriter::Write(const void*,uint)
Definition: mythmediabuffer.cpp:1634
MythMediaBuffer
Definition: mythmediabuffer.h:59
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
ProgramInfo::UpdateInUseMark
void UpdateInUseMark(bool force=false)
Definition: programinfo.cpp:4984
BEFileTransfer::isOpen
bool isOpen(void)
Definition: filetransfer.cpp:65
BEFileTransfer::m_rbuffer
MythMediaBuffer * m_rbuffer
Definition: filetransfer.h:56
BEFileTransfer::ReOpen
bool ReOpen(const QString &newFilename="")
Definition: filetransfer.cpp:70
BEFileTransfer::GetFileName
QString GetFileName(void)
Definition: filetransfer.cpp:269
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:95
BEFileTransfer::m_pginfo
ProgramInfo * m_pginfo
Definition: filetransfer.h:55
MythMediaBuffer::GetStopReads
bool GetStopReads(void) const
Definition: mythmediabuffer.cpp:1788
BEFileTransfer::m_requestBuffer
std::vector< char > m_requestBuffer
Definition: filetransfer.h:60
MythSocket
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:25
MythMediaBuffer::GetFilename
QString GetFilename(void) const
Definition: mythmediabuffer.cpp:1749
MythMediaBuffer::GetRealFileSize
long long GetRealFileSize(void) const
Definition: mythmediabuffer.cpp:468
ProgramInfo::MarkAsInUse
void MarkAsInUse(bool inuse, const QString &usedFor="")
Tracks a recording's in use status, to prevent deletion and to allow the storage scheduler to perform...
Definition: programinfo.cpp:5175
mythdate.h
MythMediaBuffer::SetOldFile
void SetOldFile(bool Old)
Tell RingBuffer if this is an old file or not.
Definition: mythmediabuffer.cpp:1741
programinfo.h
mythlogging.h
BEFileTransfer::m_lock
QMutex m_lock
Definition: filetransfer.h:62
BEFileTransfer::SetTimeout
void SetTimeout(bool fast)
Definition: filetransfer.cpp:277
filetransfer.h
BEFileTransfer::~BEFileTransfer
~BEFileTransfer() override
Definition: filetransfer.cpp:45
MythSocket::SetReadyReadCallbackEnabled
void SetReadyReadCallbackEnabled(bool enabled)
Definition: mythsocket.h:48
MythSocket::Read
int Read(char *data, int size, std::chrono::milliseconds max_wait)
Definition: mythsocket.cpp:527
mythmediabuffer.h
BEFileTransfer::m_readsLocked
bool m_readsLocked
Definition: filetransfer.h:52
BEFileTransfer::Unpause
void Unpause(void)
Definition: filetransfer.cpp:113
MythMediaBuffer::Read
int Read(void *Buffer, int Count)
This is the public method for reading from a file, it calls the appropriate read method if the file i...
Definition: mythmediabuffer.cpp:1496
MythMediaBuffer::WriterFlush
void WriterFlush(void)
Calls ThreadedFileWriter::Flush(void)
Definition: mythmediabuffer.cpp:1707
MythSocket::Write
int Write(const char *data, int size)
Definition: mythsocket.cpp:514
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
BEFileTransfer::m_readsUnlockedCond
QWaitCondition m_readsUnlockedCond
Definition: filetransfer.h:53
BEFileTransfer::Seek
long long Seek(long long curpos, long long pos, int whence)
Definition: filetransfer.cpp:229
BEFileTransfer::RequestBlock
int RequestBlock(int size)
Definition: filetransfer.cpp:128
MythMediaBuffer::GetReadPosition
virtual long long GetReadPosition(void) const =0
MythMediaBuffer::Start
void Start(void)
Starts the read-ahead thread.
Definition: mythmediabuffer.cpp:617
BEFileTransfer::Pause
void Pause(void)
Definition: filetransfer.cpp:101
BEFileTransfer::GetFileSize
uint64_t GetFileSize(void)
Definition: filetransfer.cpp:261
BEFileTransfer::BEFileTransfer
BEFileTransfer(QString &filename, MythSocket *remote, bool usereadahead, std::chrono::milliseconds timeout)
Definition: filetransfer.cpp:19
BEFileTransfer::m_sock
MythSocket * m_sock
Definition: filetransfer.h:57
BEFileTransfer::WriteBlock
int WriteBlock(int size)
Definition: filetransfer.cpp:168
BEFileTransfer::m_readthreadlive
volatile bool m_readthreadlive
Definition: filetransfer.h:51
BEFileTransfer::m_writemode
bool m_writemode
Definition: filetransfer.h:64
kFileTransferInUseID
const QString kFileTransferInUseID
Definition: programtypes.cpp:21
MythMediaBuffer::StartReads
void StartReads(void)
Definition: mythmediabuffer.cpp:679
build_compdb.filename
filename
Definition: build_compdb.py:21
BEFileTransfer::Stop
void Stop(void)
Definition: filetransfer.cpp:81
mythsocket.h
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:26
uint
unsigned int uint
Definition: freesurround.h:24
MythMediaBuffer::IsOpen
virtual bool IsOpen(void) const =0
BEFileTransfer::m_ateof
bool m_ateof
Definition: filetransfer.h:58