MythTV  master
programs/mythbackend/filetransfer.cpp
Go to the documentation of this file.
1 #include <QCoreApplication>
2 #include <QDateTime>
3 #include <QFileInfo>
4 #include <utility>
5 
6 #include "filetransfer.h"
7 #include "io/mythmediabuffer.h"
8 #include "mythdate.h"
9 #include "mythsocket.h"
10 #include "programinfo.h"
11 #include "mythlogging.h"
12 
14  bool usereadahead, int timeout_ms) :
15  ReferenceCounter(QString("FileTransfer:%1").arg(filename)),
16  m_rbuffer(MythMediaBuffer::Create(filename, false, usereadahead, timeout_ms, true)),
17  m_sock(remote)
18 {
21  if (m_rbuffer && m_rbuffer->IsOpen())
22  m_rbuffer->Start();
23 }
24 
26  ReferenceCounter(QString("FileTransfer:%1").arg(filename)),
27  m_rbuffer(MythMediaBuffer::Create(filename, write)),
28  m_sock(remote), m_writemode(write)
29 {
32 
33  if (write)
34  remote->SetReadyReadCallbackEnabled(false);
35  if (m_rbuffer)
36  m_rbuffer->Start();
37 }
38 
40 {
41  Stop();
42 
43  if (m_sock) // FileTransfer becomes responsible for deleting the socket
44  m_sock->DecrRef();
45 
46  if (m_rbuffer)
47  {
48  delete m_rbuffer;
49  m_rbuffer = nullptr;
50  }
51 
52  if (m_pginfo)
53  {
55  delete m_pginfo;
56  }
57 }
58 
59 bool FileTransfer::isOpen(void)
60 {
61  return m_rbuffer && m_rbuffer->IsOpen();
62 }
63 
64 bool FileTransfer::ReOpen(const QString& newFilename)
65 {
66  if (!m_writemode)
67  return false;
68 
69  if (m_rbuffer)
70  return m_rbuffer->ReOpen(newFilename);
71 
72  return false;
73 }
74 
75 void FileTransfer::Stop(void)
76 {
77  if (m_readthreadlive)
78  {
79  m_readthreadlive = false;
80  LOG(VB_FILE, LOG_INFO, "calling StopReads()");
81  if (m_rbuffer)
83  QMutexLocker locker(&m_lock);
84  m_readsLocked = true;
85  }
86 
87  if (m_writemode)
88  if (m_rbuffer)
90 
91  if (m_pginfo)
93 }
94 
95 void FileTransfer::Pause(void)
96 {
97  LOG(VB_FILE, LOG_INFO, "calling StopReads()");
98  if (m_rbuffer)
100  QMutexLocker locker(&m_lock);
101  m_readsLocked = true;
102 
103  if (m_pginfo)
105 }
106 
107 void FileTransfer::Unpause(void)
108 {
109  LOG(VB_FILE, LOG_INFO, "calling StartReads()");
110  if (m_rbuffer)
112  {
113  QMutexLocker locker(&m_lock);
114  m_readsLocked = false;
115  }
116  m_readsUnlockedCond.wakeAll();
117 
118  if (m_pginfo)
120 }
121 
122 int FileTransfer::RequestBlock(int size)
123 {
124  if (!m_readthreadlive || !m_rbuffer)
125  return -1;
126 
127  int tot = 0;
128  int ret = 0;
129 
130  QMutexLocker locker(&m_lock);
131  while (m_readsLocked)
132  m_readsUnlockedCond.wait(&m_lock, 100 /*ms*/);
133 
134  m_requestBuffer.resize(std::max((size_t)std::max(size,0) + 128, m_requestBuffer.size()));
135  char *buf = &m_requestBuffer[0];
136  while (tot < size && !m_rbuffer->GetStopReads() && m_readthreadlive)
137  {
138  int request = size - tot;
139 
140  ret = m_rbuffer->Read(buf, request);
141 
142  if (m_rbuffer->GetStopReads() || ret <= 0)
143  break;
144 
145  if (m_sock->Write(buf, (uint)ret) != ret)
146  {
147  tot = -1;
148  break;
149  }
150 
151  tot += ret;
152  if (ret < request)
153  break; // we hit eof
154  }
155 
156  if (m_pginfo)
158 
159  return (ret < 0) ? -1 : tot;
160 }
161 
162 int FileTransfer::WriteBlock(int size)
163 {
164  if (!m_writemode || !m_rbuffer)
165  return -1;
166 
167  int tot = 0;
168  int ret = 0;
169 
170  QMutexLocker locker(&m_lock);
171 
172  m_requestBuffer.resize(std::max((size_t)std::max(size,0) + 128, m_requestBuffer.size()));
173  char *buf = &m_requestBuffer[0];
174  int attempts = 0;
175 
176  while (tot < size)
177  {
178  int request = size - tot;
179  int received = m_sock->Read(buf, (uint)request, 200 /*ms */);
180 
181  if (received != request)
182  {
183  LOG(VB_FILE, LOG_DEBUG,
184  QString("WriteBlock(): Read failed. Requested %1 got %2")
185  .arg(request).arg(received));
186  if (received < 0)
187  {
188  // An error occurred, abort immediately
189  break;
190  }
191  if (received == 0)
192  {
193  attempts++;
194  if (attempts > 3)
195  {
196  LOG(VB_FILE, LOG_ERR,
197  "WriteBlock(): Read tried too many times, aborting "
198  "(client or network too slow?)");
199  break;
200  }
201  continue;
202  }
203  }
204  attempts = 0;
205  ret = m_rbuffer->Write(buf, received);
206  if (ret <= 0)
207  {
208  LOG(VB_FILE, LOG_DEBUG,
209  QString("WriteBlock(): Write failed. Requested %1 got %2")
210  .arg(received).arg(ret));
211  break;
212  }
213 
214  tot += received;
215  }
216 
217  if (m_pginfo)
219 
220  return (ret < 0) ? -1 : tot;
221 }
222 
223 long long FileTransfer::Seek(long long curpos, long long pos, int whence)
224 {
225  if (m_pginfo)
227 
228  if (!m_rbuffer)
229  return -1;
230  if (!m_readthreadlive)
231  return -1;
232 
233  m_ateof = false;
234 
235  Pause();
236 
237  if (whence == SEEK_CUR)
238  {
239  long long desired = curpos + pos;
240  long long realpos = m_rbuffer->GetReadPosition();
241 
242  pos = desired - realpos;
243  }
244 
245  long long ret = m_rbuffer->Seek(pos, whence);
246 
247  Unpause();
248 
249  if (m_pginfo)
251 
252  return ret;
253 }
254 
255 uint64_t FileTransfer::GetFileSize(void)
256 {
257  if (m_pginfo)
259 
260  return m_rbuffer ? m_rbuffer->GetRealFileSize() : 0;
261 }
262 
263 QString FileTransfer::GetFileName(void)
264 {
265  if (!m_rbuffer)
266  return QString();
267 
268  return m_rbuffer->GetFilename();
269 }
270 
271 void FileTransfer::SetTimeout(bool fast)
272 {
273  if (m_pginfo)
275 
276  if (m_rbuffer)
277  m_rbuffer->SetOldFile(fast);
278 }
279 
280 /* vim: set expandtab tabstop=4 shiftwidth=4: */
FileTransfer::Pause
void Pause(void)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:88
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
MythMediaBuffer::ReOpen
virtual bool ReOpen(const QString &="")
Definition: mythmediabuffer.h:135
FileTransfer::m_sock
MythSocket * m_sock
Definition: programs/mythbackend/filetransfer.h:57
MythMediaBuffer::Seek
long long Seek(long long Position, int Whence, bool HasLock=false)
Definition: mythmediabuffer.cpp:475
FileTransfer::Stop
void Stop(void)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:70
MythMediaBuffer::StopReads
void StopReads(void)
Definition: mythmediabuffer.cpp:665
FileTransfer::m_lock
QMutex m_lock
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:58
FileTransfer::m_readthreadlive
volatile bool m_readthreadlive
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:48
mythburn.write
def write(text, progress=True)
Definition: mythburn.py:308
FileTransfer::GetFileName
QString GetFileName(void)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:254
arg
arg(title).arg(filename).arg(doDelete))
MythMediaBuffer::Write
int Write(const void *Buffer, uint Count)
Writes buffer to ThreadedFileWriter::Write(const void*,uint)
Definition: mythmediabuffer.cpp:1617
MythMediaBuffer
Definition: mythmediabuffer.h:50
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
FileTransfer::~FileTransfer
~FileTransfer() override
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:37
ProgramInfo::UpdateInUseMark
void UpdateInUseMark(bool force=false)
Definition: programinfo.cpp:4708
FileTransfer::WriteBlock
int WriteBlock(int size)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:153
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
MythMediaBuffer::GetStopReads
bool GetStopReads(void) const
Definition: mythmediabuffer.cpp:1771
FileTransfer::m_readsLocked
bool m_readsLocked
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:49
MythSocket
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:27
FileTransfer::m_rbuffer
MythMediaBuffer * m_rbuffer
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:53
MythMediaBuffer::GetFilename
QString GetFilename(void) const
Definition: mythmediabuffer.cpp:1732
MythMediaBuffer::GetRealFileSize
long long GetRealFileSize(void) const
Definition: mythmediabuffer.cpp:464
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:4900
mythdate.h
MythMediaBuffer::SetOldFile
void SetOldFile(bool Old)
Tell RingBuffer if this is an old file or not.
Definition: mythmediabuffer.cpp:1724
programinfo.h
mythlogging.h
FileTransfer::m_readsUnlockedCond
QWaitCondition m_readsUnlockedCond
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:50
filetransfer.h
FileTransfer::Seek
long long Seek(long long curpos, long long pos, int whence)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:214
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:637
FileTransfer::m_writemode
bool m_writemode
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:60
MythSocket::SetReadyReadCallbackEnabled
void SetReadyReadCallbackEnabled(bool enabled)
Definition: mythsocket.h:49
FileTransfer::ReOpen
bool ReOpen(const QString &newFilename="")
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:59
FileTransfer::m_pginfo
ProgramInfo * m_pginfo
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:52
uint
unsigned int uint
Definition: compat.h:141
FileTransfer::Unpause
void Unpause(void)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:99
FileTransfer::RequestBlock
int RequestBlock(int size)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:113
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:1479
MythMediaBuffer::WriterFlush
void WriterFlush(void)
Calls ThreadedFileWriter::Flush(void)
Definition: mythmediabuffer.cpp:1690
MythSocket::Write
int Write(const char *data, int size)
Definition: mythsocket.cpp:530
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:68
FileTransfer::FileTransfer
FileTransfer(QString &filename, MythSocket *remote, MythSocketManager *parent, bool usereadahead, int timeout_ms)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:11
FileTransfer::GetFileSize
uint64_t GetFileSize(void)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:246
MythMediaBuffer::GetReadPosition
virtual long long GetReadPosition(void) const =0
MythMediaBuffer::Start
void Start(void)
Starts the read-ahead thread.
Definition: mythmediabuffer.cpp:613
kFileTransferInUseID
const QString kFileTransferInUseID
Definition: programtypes.cpp:18
MythMediaBuffer::StartReads
void StartReads(void)
Definition: mythmediabuffer.cpp:675
FileTransfer::m_requestBuffer
std::vector< char > m_requestBuffer
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:56
FileTransfer::SetTimeout
void SetTimeout(bool fast)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:262
FileTransfer::m_ateof
bool m_ateof
Definition: libs/libmythprotoserver/sockethandler/filetransfer.h:54
mythsocket.h
FileTransfer::isOpen
bool isOpen(void)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:54
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:27
MythMediaBuffer::IsOpen
virtual bool IsOpen(void) const =0
MythSocket::Read
int Read(char *data, int size, int max_wait_ms)
Definition: mythsocket.cpp:543