MythTV  master
libs/libmythprotoserver/sockethandler/filetransfer.cpp
Go to the documentation of this file.
1 #include <QFileInfo>
2 #include <QMutexLocker>
3 #include <utility>
4 
5 #include "filetransfer.h"
6 #include "io/mythmediabuffer.h"
7 #include "programinfo.h"
8 #include "mythsocket.h"
9 #include "mythlogging.h"
10 
12  MythSocketManager *parent,
13  bool usereadahead, int timeout_ms) :
14  SocketHandler(remote, parent, ""),
15  m_rbuffer(MythMediaBuffer::Create(filename, false, usereadahead, timeout_ms))
16 {
19 }
20 
22  MythSocketManager *parent, bool write) :
23  SocketHandler(remote, parent, ""),
24  m_rbuffer(MythMediaBuffer::Create(filename, write)),
25  m_writemode(write)
26 {
29 
30  if (write)
31  {
32  remote->SetReadyReadCallbackEnabled(false);
34  }
35 }
36 
38 {
39  Stop();
40 
41  if (m_rbuffer)
42  {
43  delete m_rbuffer;
44  m_rbuffer = nullptr;
45  }
46 
47  if (m_pginfo)
48  {
50  delete m_pginfo;
51  }
52 }
53 
55 {
56  return m_rbuffer && m_rbuffer->IsOpen();
57 }
58 
59 bool FileTransfer::ReOpen(const QString& newFilename)
60 {
61  if (!m_writemode)
62  return false;
63 
64  if (m_rbuffer)
65  return m_rbuffer->ReOpen(newFilename);
66 
67  return false;
68 }
69 
71 {
72  if (m_readthreadlive)
73  {
74  m_readthreadlive = false;
75  LOG(VB_FILE, LOG_INFO, "calling StopReads()");
77  QMutexLocker locker(&m_lock);
78  m_readsLocked = true;
79  }
80 
81  if (m_writemode)
83 
84  if (m_pginfo)
86 }
87 
89 {
90  LOG(VB_FILE, LOG_INFO, "calling StopReads()");
92  QMutexLocker locker(&m_lock);
93  m_readsLocked = true;
94 
95  if (m_pginfo)
97 }
98 
100 {
101  LOG(VB_FILE, LOG_INFO, "calling StartReads()");
103  {
104  QMutexLocker locker(&m_lock);
105  m_readsLocked = false;
106  }
107  m_readsUnlockedCond.wakeAll();
108 
109  if (m_pginfo)
111 }
112 
114 {
115  if (!m_readthreadlive || !m_rbuffer)
116  return -1;
117 
118  int tot = 0;
119  int ret = 0;
120 
121  QMutexLocker locker(&m_lock);
122  while (m_readsLocked)
123  m_readsUnlockedCond.wait(&m_lock, 100 /*ms*/);
124 
125  m_requestBuffer.resize(std::max((size_t)std::max(size,0) + 128, m_requestBuffer.size()));
126  char *buf = &m_requestBuffer[0];
127  while (tot < size && !m_rbuffer->GetStopReads() && m_readthreadlive)
128  {
129  int request = size - tot;
130 
131  ret = m_rbuffer->Read(buf, request);
132 
133  if (m_rbuffer->GetStopReads() || ret <= 0)
134  break;
135 
136  if (GetSocket()->Write(buf, (uint)ret) != ret)
137  {
138  tot = -1;
139  break;
140  }
141 
142  tot += ret;
143  if (ret < request)
144  break; // we hit eof
145  }
146 
147  if (m_pginfo)
149 
150  return (ret < 0) ? -1 : tot;
151 }
152 
154 {
155  if (!m_writemode || !m_rbuffer)
156  return -1;
157 
158  int tot = 0;
159  int ret = 0;
160 
161  QMutexLocker locker(&m_lock);
162 
163  m_requestBuffer.resize(std::max((size_t)std::max(size,0) + 128, m_requestBuffer.size()));
164  char *buf = &m_requestBuffer[0];
165  int attempts = 0;
166 
167  while (tot < size)
168  {
169  int request = size - tot;
170  int received = GetSocket()->Read(buf, (uint)request, 200 /*ms */);
171 
172  if (received != request)
173  {
174  LOG(VB_FILE, LOG_DEBUG,
175  QString("WriteBlock(): Read failed. Requested %1 got %2")
176  .arg(request).arg(received));
177  if (received < 0)
178  {
179  // An error occurred, abort immediately
180  break;
181  }
182  if (received == 0)
183  {
184  attempts++;
185  if (attempts > 3)
186  {
187  LOG(VB_FILE, LOG_ERR,
188  "WriteBlock(): Read tried too many times, aborting "
189  "(client or network too slow?)");
190  break;
191  }
192  continue;
193  }
194  }
195  attempts = 0;
196  ret = m_rbuffer->Write(buf, received);
197  if (ret <= 0)
198  {
199  LOG(VB_FILE, LOG_DEBUG,
200  QString("WriteBlock(): Write failed. Requested %1 got %2")
201  .arg(received).arg(ret));
202  break;
203  }
204 
205  tot += received;
206  }
207 
208  if (m_pginfo)
210 
211  return (ret < 0) ? -1 : tot;
212 }
213 
214 long long FileTransfer::Seek(long long curpos, long long pos, int whence)
215 {
216  if (m_pginfo)
218 
219  if (!m_rbuffer)
220  return -1;
221  if (!m_readthreadlive)
222  return -1;
223 
224  m_ateof = false;
225 
226  Pause();
227 
228  if (whence == SEEK_CUR)
229  {
230  long long desired = curpos + pos;
231  long long realpos = m_rbuffer->GetReadPosition();
232 
233  pos = desired - realpos;
234  }
235 
236  long long ret = m_rbuffer->Seek(pos, whence);
237 
238  Unpause();
239 
240  if (m_pginfo)
242 
243  return ret;
244 }
245 
247 {
248  if (m_pginfo)
250 
251  return m_rbuffer->GetRealFileSize();
252 }
253 
255 {
256  if (!m_rbuffer)
257  return QString();
258 
259  return m_rbuffer->GetFilename();
260 }
261 
263 {
264  if (m_pginfo)
266 
267  m_rbuffer->SetOldFile(fast);
268 }
269 
270 /* vim: set expandtab tabstop=4 shiftwidth=4: */
FileTransfer::Pause
void Pause(void)
Definition: libs/libmythprotoserver/sockethandler/filetransfer.cpp:88
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
MythMediaBuffer::ReOpen
virtual bool ReOpen(const QString &="")
Definition: mythmediabuffer.h:135
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
MythMediaBuffer::WriterSetBlocking
bool WriterSetBlocking(bool Lock=true)
Calls ThreadedFileWriter::SetBlocking(bool)
Definition: mythmediabuffer.cpp:1701
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
MythSocketManager
Definition: mythsocketmanager.h:35
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
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
SocketHandler::GetSocket
MythSocket * GetSocket(void)
Definition: sockethandler.h:29
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
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
SocketHandler
Definition: sockethandler.h:17
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
MythMediaBuffer::IsOpen
virtual bool IsOpen(void) const =0
MythSocket::Read
int Read(char *data, int size, int max_wait_ms)
Definition: mythsocket.cpp:543