MythTV  master
filetransfer.cpp
Go to the documentation of this file.
1 #include <QFileInfo>
2 #include <QMutexLocker>
3 #include <utility>
4 
9 
10 #include "filetransfer.h"
11 
13  MythSocketManager *parent,
14  bool usereadahead, std::chrono::milliseconds timeout) :
15  SocketHandler(remote, parent, ""),
16  m_pginfo(new ProgramInfo(filename)),
17  m_rbuffer(MythMediaBuffer::Create(filename, false, usereadahead, timeout))
18 {
20 }
21 
23  MythSocketManager *parent, bool write) :
24  SocketHandler(remote, parent, ""),
25  m_pginfo(new ProgramInfo(filename)),
26  m_rbuffer(MythMediaBuffer::Create(filename, write)),
27  m_writemode(write)
28 {
30 
31  if (write)
32  {
33  remote->SetReadyReadCallbackEnabled(false);
35  }
36 }
37 
39 {
40  Stop();
41 
42  if (m_rbuffer)
43  {
44  delete m_rbuffer;
45  m_rbuffer = nullptr;
46  }
47 
48  if (m_pginfo)
49  {
51  delete m_pginfo;
52  }
53 }
54 
56 {
57  return m_rbuffer && m_rbuffer->IsOpen();
58 }
59 
60 bool FileTransfer::ReOpen(const QString& newFilename)
61 {
62  if (!m_writemode)
63  return false;
64 
65  if (m_rbuffer)
66  return m_rbuffer->ReOpen(newFilename);
67 
68  return false;
69 }
70 
72 {
73  if (m_readthreadlive)
74  {
75  m_readthreadlive = false;
76  LOG(VB_FILE, LOG_INFO, "calling StopReads()");
78  QMutexLocker locker(&m_lock);
79  m_readsLocked = true;
80  }
81 
82  if (m_writemode)
84 
85  if (m_pginfo)
87 }
88 
90 {
91  LOG(VB_FILE, LOG_INFO, "calling StopReads()");
93  QMutexLocker locker(&m_lock);
94  m_readsLocked = true;
95 
96  if (m_pginfo)
98 }
99 
101 {
102  LOG(VB_FILE, LOG_INFO, "calling StartReads()");
104  {
105  QMutexLocker locker(&m_lock);
106  m_readsLocked = false;
107  }
108  m_readsUnlockedCond.wakeAll();
109 
110  if (m_pginfo)
112 }
113 
115 {
116  if (!m_readthreadlive || !m_rbuffer)
117  return -1;
118 
119  int tot = 0;
120  int ret = 0;
121 
122  QMutexLocker locker(&m_lock);
123  while (m_readsLocked)
124  m_readsUnlockedCond.wait(&m_lock, 100 /*ms*/);
125 
126  m_requestBuffer.resize(std::max((size_t)std::max(size,0) + 128, m_requestBuffer.size()));
127  char *buf = (m_requestBuffer).data();
128  while (tot < size && !m_rbuffer->GetStopReads() && m_readthreadlive)
129  {
130  int request = size - tot;
131 
132  ret = m_rbuffer->Read(buf, request);
133 
134  if (m_rbuffer->GetStopReads() || ret <= 0)
135  break;
136 
137  if (GetSocket()->Write(buf, (uint)ret) != ret)
138  {
139  tot = -1;
140  break;
141  }
142 
143  tot += ret;
144  if (ret < request)
145  break; // we hit eof
146  }
147 
148  if (m_pginfo)
150 
151  return (ret < 0) ? -1 : tot;
152 }
153 
155 {
156  if (!m_writemode || !m_rbuffer)
157  return -1;
158 
159  int tot = 0;
160  int ret = 0;
161 
162  QMutexLocker locker(&m_lock);
163 
164  m_requestBuffer.resize(std::max((size_t)std::max(size,0) + 128, m_requestBuffer.size()));
165  char *buf = (m_requestBuffer).data();
166  int attempts = 0;
167 
168  while (tot < size)
169  {
170  int request = size - tot;
171  int received = GetSocket()->Read(buf, (uint)request, 200ms);
172 
173  if (received != request)
174  {
175  LOG(VB_FILE, LOG_DEBUG,
176  QString("WriteBlock(): Read failed. Requested %1 got %2")
177  .arg(request).arg(received));
178  if (received < 0)
179  {
180  // An error occurred, abort immediately
181  break;
182  }
183  if (received == 0)
184  {
185  attempts++;
186  if (attempts > 3)
187  {
188  LOG(VB_FILE, LOG_ERR,
189  "WriteBlock(): Read tried too many times, aborting "
190  "(client or network too slow?)");
191  break;
192  }
193  continue;
194  }
195  }
196  attempts = 0;
197  ret = m_rbuffer->Write(buf, received);
198  if (ret <= 0)
199  {
200  LOG(VB_FILE, LOG_DEBUG,
201  QString("WriteBlock(): Write failed. Requested %1 got %2")
202  .arg(received).arg(ret));
203  break;
204  }
205 
206  tot += received;
207  }
208 
209  if (m_pginfo)
211 
212  return (ret < 0) ? -1 : tot;
213 }
214 
215 long long FileTransfer::Seek(long long curpos, long long pos, int whence)
216 {
217  if (m_pginfo)
219 
220  if (!m_rbuffer)
221  return -1;
222  if (!m_readthreadlive)
223  return -1;
224 
225  m_ateof = false;
226 
227  Pause();
228 
229  if (whence == SEEK_CUR)
230  {
231  long long desired = curpos + pos;
232  long long realpos = m_rbuffer->GetReadPosition();
233 
234  pos = desired - realpos;
235  }
236 
237  long long ret = m_rbuffer->Seek(pos, whence);
238 
239  Unpause();
240 
241  if (m_pginfo)
243 
244  return ret;
245 }
246 
248 {
249  if (m_pginfo)
251 
252  return m_rbuffer->GetRealFileSize();
253 }
254 
256 {
257  if (!m_rbuffer)
258  return {};
259 
260  return m_rbuffer->GetFilename();
261 }
262 
264 {
265  if (m_pginfo)
267 
268  m_rbuffer->SetOldFile(fast);
269 }
270 
271 /* vim: set expandtab tabstop=4 shiftwidth=4: */
FileTransfer::Pause
void Pause(void)
Definition: filetransfer.cpp:89
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
FileTransfer::m_rbuffer
MythMediaBuffer * m_rbuffer
Definition: filetransfer.h:52
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
FileTransfer::Stop
void Stop(void)
Definition: filetransfer.cpp:71
MythMediaBuffer::StopReads
void StopReads(void)
Definition: mythmediabuffer.cpp:669
FileTransfer::m_lock
QMutex m_lock
Definition: filetransfer.h:57
MythMediaBuffer::WriterSetBlocking
bool WriterSetBlocking(bool Lock=true)
Calls ThreadedFileWriter::SetBlocking(bool)
Definition: mythmediabuffer.cpp:1718
FileTransfer::m_readthreadlive
volatile bool m_readthreadlive
Definition: filetransfer.h:47
mythburn.write
def write(text, progress=True)
Definition: mythburn.py:308
FileTransfer::GetFileName
QString GetFileName(void)
Definition: filetransfer.cpp:255
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
FileTransfer::~FileTransfer
~FileTransfer() override
Definition: filetransfer.cpp:38
ProgramInfo::UpdateInUseMark
void UpdateInUseMark(bool force=false)
Definition: programinfo.cpp:4984
FileTransfer::WriteBlock
int WriteBlock(int size)
Definition: filetransfer.cpp:154
MythSocketManager
Definition: mythsocketmanager.h:21
MythMediaBuffer::GetStopReads
bool GetStopReads(void) const
Definition: mythmediabuffer.cpp:1788
FileTransfer::m_readsLocked
bool m_readsLocked
Definition: filetransfer.h:48
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
MythMediaBuffer::SetOldFile
void SetOldFile(bool Old)
Tell RingBuffer if this is an old file or not.
Definition: mythmediabuffer.cpp:1741
FileTransfer::m_pginfo
ProgramInfo * m_pginfo
Definition: filetransfer.h:51
programinfo.h
mythlogging.h
FileTransfer::m_readsUnlockedCond
QWaitCondition m_readsUnlockedCond
Definition: filetransfer.h:49
SocketHandler::GetSocket
MythSocket * GetSocket(void)
Definition: sockethandler.h:29
FileTransfer::Seek
long long Seek(long long curpos, long long pos, int whence)
Definition: filetransfer.cpp:215
FileTransfer::m_writemode
bool m_writemode
Definition: filetransfer.h:59
MythSocket::SetReadyReadCallbackEnabled
void SetReadyReadCallbackEnabled(bool enabled)
Definition: mythsocket.h:48
filetransfer.h
FileTransfer::ReOpen
bool ReOpen(const QString &newFilename="")
Definition: filetransfer.cpp:60
MythSocket::Read
int Read(char *data, int size, std::chrono::milliseconds max_wait)
Definition: mythsocket.cpp:527
FileTransfer::Unpause
void Unpause(void)
Definition: filetransfer.cpp:100
FileTransfer::RequestBlock
int RequestBlock(int size)
Definition: filetransfer.cpp:114
mythmediabuffer.h
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
FileTransfer::FileTransfer
FileTransfer(QString &filename, MythSocket *remote, MythSocketManager *parent, bool usereadahead, std::chrono::milliseconds timeout)
Definition: filetransfer.cpp:12
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
FileTransfer::GetFileSize
uint64_t GetFileSize(void)
Definition: filetransfer.cpp:247
MythMediaBuffer::GetReadPosition
virtual long long GetReadPosition(void) const =0
SocketHandler
Definition: sockethandler.h:16
FileTransfer::m_requestBuffer
std::vector< char > m_requestBuffer
Definition: filetransfer.h:55
kFileTransferInUseID
const QString kFileTransferInUseID
Definition: programtypes.cpp:21
MythMediaBuffer::StartReads
void StartReads(void)
Definition: mythmediabuffer.cpp:679
FileTransfer::SetTimeout
void SetTimeout(bool fast)
Definition: filetransfer.cpp:263
build_compdb.filename
filename
Definition: build_compdb.py:21
FileTransfer::m_ateof
bool m_ateof
Definition: filetransfer.h:53
mythsocket.h
FileTransfer::isOpen
bool isOpen(void)
Definition: filetransfer.cpp:55
uint
unsigned int uint
Definition: freesurround.h:24
MythMediaBuffer::IsOpen
virtual bool IsOpen(void) const =0