MythTV  0.26-pre
filetransfer.cpp
Go to the documentation of this file.
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 /*ms*/);
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; // we hit eof
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 /* vim: set expandtab tabstop=4 shiftwidth=4: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends