00001
00002 using namespace std;
00003
00004 #include <QFileInfo>
00005 #include <QMutexLocker>
00006
00007 #include "filetransfer.h"
00008 #include "ringbuffer.h"
00009 #include "programinfo.h"
00010 #include "mythsocket.h"
00011
00012 FileTransfer::FileTransfer(QString &filename, MythSocket *remote,
00013 MythSocketManager *parent,
00014 bool usereadahead, int timeout_ms) :
00015 SocketHandler(remote, parent, ""),
00016 readthreadlive(true), readsLocked(false),
00017 rbuffer(RingBuffer::Create(filename, false, usereadahead, timeout_ms)),
00018 ateof(false), lock(QMutex::NonRecursive),
00019 writemode(false)
00020 {
00021 pginfo = new ProgramInfo(filename);
00022 pginfo->MarkAsInUse(true, kFileTransferInUseID);
00023 }
00024
00025 FileTransfer::FileTransfer(QString &filename, MythSocket *remote,
00026 MythSocketManager *parent, bool write) :
00027 SocketHandler(remote, parent, ""),
00028 readthreadlive(true), readsLocked(false),
00029 rbuffer(RingBuffer::Create(filename, write)),
00030 ateof(false), lock(QMutex::NonRecursive),
00031 writemode(write)
00032 {
00033 pginfo = new ProgramInfo(filename);
00034 pginfo->MarkAsInUse(true, kFileTransferInUseID);
00035
00036 if (write)
00037 remote->useReadyReadCallback(false);
00038 }
00039
00040 FileTransfer::~FileTransfer()
00041 {
00042 Stop();
00043
00044 if (rbuffer)
00045 {
00046 delete rbuffer;
00047 rbuffer = NULL;
00048 }
00049
00050 if (pginfo)
00051 {
00052 pginfo->MarkAsInUse(false, kFileTransferInUseID);
00053 delete pginfo;
00054 }
00055 }
00056
00057 bool FileTransfer::isOpen(void)
00058 {
00059 if (rbuffer && rbuffer->IsOpen())
00060 return true;
00061 return false;
00062 }
00063
00064 void FileTransfer::Stop(void)
00065 {
00066 if (readthreadlive)
00067 {
00068 readthreadlive = false;
00069 rbuffer->StopReads();
00070 QMutexLocker locker(&lock);
00071 readsLocked = true;
00072 }
00073
00074 if (writemode)
00075 rbuffer->WriterFlush();
00076
00077 if (pginfo)
00078 pginfo->UpdateInUseMark();
00079 }
00080
00081 void FileTransfer::Pause(void)
00082 {
00083 rbuffer->StopReads();
00084 QMutexLocker locker(&lock);
00085 readsLocked = true;
00086
00087 if (pginfo)
00088 pginfo->UpdateInUseMark();
00089 }
00090
00091 void FileTransfer::Unpause(void)
00092 {
00093 rbuffer->StartReads();
00094 {
00095 QMutexLocker locker(&lock);
00096 readsLocked = false;
00097 }
00098 readsUnlockedCond.wakeAll();
00099
00100 if (pginfo)
00101 pginfo->UpdateInUseMark();
00102 }
00103
00104 int FileTransfer::RequestBlock(int size)
00105 {
00106 if (!readthreadlive || !rbuffer)
00107 return -1;
00108
00109 int tot = 0;
00110 int ret = 0;
00111
00112 QMutexLocker locker(&lock);
00113 while (readsLocked)
00114 readsUnlockedCond.wait(&lock, 100 );
00115
00116 requestBuffer.resize(max((size_t)max(size,0) + 128, requestBuffer.size()));
00117 char *buf = &requestBuffer[0];
00118 while (tot < size && !rbuffer->GetStopReads() && readthreadlive)
00119 {
00120 int request = size - tot;
00121
00122 ret = rbuffer->Read(buf, request);
00123
00124 if (rbuffer->GetStopReads() || ret <= 0)
00125 break;
00126
00127 if (!GetSocket()->writeData(buf, (uint)ret))
00128 {
00129 tot = -1;
00130 break;
00131 }
00132
00133 tot += ret;
00134 if (ret < request)
00135 break;
00136 }
00137
00138 if (pginfo)
00139 pginfo->UpdateInUseMark();
00140
00141 return (ret < 0) ? -1 : tot;
00142 }
00143
00144 int FileTransfer::WriteBlock(int size)
00145 {
00146 if (!writemode || !rbuffer)
00147 return -1;
00148
00149 int tot = 0;
00150 int ret = 0;
00151
00152 QMutexLocker locker(&lock);
00153
00154 requestBuffer.resize(max((size_t)max(size,0) + 128, requestBuffer.size()));
00155 char *buf = &requestBuffer[0];
00156 while (tot < size)
00157 {
00158 int request = size - tot;
00159
00160 if (!GetSocket()->readData(buf, (uint)request))
00161 break;
00162
00163 ret = rbuffer->Write(buf, request);
00164
00165 if (ret <= 0)
00166 break;
00167
00168 tot += request;
00169 }
00170
00171 if (pginfo)
00172 pginfo->UpdateInUseMark();
00173
00174 return (ret < 0) ? -1 : tot;
00175 }
00176
00177 long long FileTransfer::Seek(long long curpos, long long pos, int whence)
00178 {
00179 if (pginfo)
00180 pginfo->UpdateInUseMark();
00181
00182 if (!rbuffer)
00183 return -1;
00184 if (!readthreadlive)
00185 return -1;
00186
00187 ateof = false;
00188
00189 Pause();
00190
00191 if (whence == SEEK_CUR)
00192 {
00193 long long desired = curpos + pos;
00194 long long realpos = rbuffer->GetReadPosition();
00195
00196 pos = desired - realpos;
00197 }
00198
00199 long long ret = rbuffer->Seek(pos, whence);
00200
00201 Unpause();
00202
00203 if (pginfo)
00204 pginfo->UpdateInUseMark();
00205
00206 return ret;
00207 }
00208
00209 uint64_t FileTransfer::GetFileSize(void)
00210 {
00211 if (pginfo)
00212 pginfo->UpdateInUseMark();
00213
00214 return QFileInfo(rbuffer->GetFilename()).size();
00215 }
00216
00217 void FileTransfer::SetTimeout(bool fast)
00218 {
00219 if (pginfo)
00220 pginfo->UpdateInUseMark();
00221
00222 rbuffer->SetOldFile(fast);
00223 }
00224
00225