lllfsthread.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 #include "llmath.h"
00034 #include "lllfsthread.h"
00035 #include "llstl.h"
00036 #include "llapr.h"
00037 
00038 //============================================================================
00039 
00040 /*static*/ LLLFSThread* LLLFSThread::sLocal = NULL;
00041 
00042 //============================================================================
00043 // Run on MAIN thread
00044 //static
00045 void LLLFSThread::initClass(bool local_is_threaded)
00046 {
00047         llassert(sLocal == NULL);
00048         sLocal = new LLLFSThread(local_is_threaded);
00049 }
00050 
00051 //static
00052 S32 LLLFSThread::updateClass(U32 ms_elapsed)
00053 {
00054         sLocal->update(ms_elapsed);
00055         return sLocal->getPending();
00056 }
00057 
00058 //static
00059 void LLLFSThread::cleanupClass()
00060 {
00061         sLocal->setQuitting();
00062         while (sLocal->getPending())
00063         {
00064                 sLocal->update(0);
00065         }
00066         delete sLocal;
00067         sLocal = 0;
00068 }
00069 
00070 //----------------------------------------------------------------------------
00071 
00072 LLLFSThread::LLLFSThread(bool threaded) :
00073         LLQueuedThread("LFS", threaded),
00074         mPriorityCounter(PRIORITY_LOWBITS)
00075 {
00076 }
00077 
00078 LLLFSThread::~LLLFSThread()
00079 {
00080         // ~LLQueuedThread() will be called here
00081 }
00082 
00083 //----------------------------------------------------------------------------
00084 
00085 LLLFSThread::handle_t LLLFSThread::read(const LLString& filename,       /* Flawfinder: ignore */ 
00086                                                                                 U8* buffer, S32 offset, S32 numbytes,
00087                                                                                 Responder* responder, U32 priority)
00088 {
00089         handle_t handle = generateHandle();
00090 
00091         if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter();
00092         else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW
00093 
00094         Request* req = new Request(this, handle, priority,
00095                                                            FILE_READ, filename,
00096                                                            buffer, offset, numbytes,
00097                                                            responder);
00098 
00099         bool res = addRequest(req);
00100         if (!res)
00101         {
00102                 llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
00103         }
00104 
00105         return handle;
00106 }
00107 
00108 LLLFSThread::handle_t LLLFSThread::write(const LLString& filename,
00109                                                                                  U8* buffer, S32 offset, S32 numbytes,
00110                                                                                  Responder* responder, U32 priority)
00111 {
00112         handle_t handle = generateHandle();
00113 
00114         if (priority == 0) priority = PRIORITY_LOW | priorityCounter();
00115         
00116         Request* req = new Request(this, handle, priority,
00117                                                            FILE_WRITE, filename,
00118                                                            buffer, offset, numbytes,
00119                                                            responder);
00120 
00121         bool res = addRequest(req);
00122         if (!res)
00123         {
00124                 llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
00125         }
00126         
00127         return handle;
00128 }
00129 
00130 //============================================================================
00131 
00132 LLLFSThread::Request::Request(LLLFSThread* thread,
00133                                                           handle_t handle, U32 priority,
00134                                                           operation_t op, const LLString& filename,
00135                                                           U8* buffer, S32 offset, S32 numbytes,
00136                                                           Responder* responder) :
00137         QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
00138         mThread(thread),
00139         mOperation(op),
00140         mFileName(filename),
00141         mBuffer(buffer),
00142         mOffset(offset),
00143         mBytes(numbytes),
00144         mBytesRead(0),
00145         mResponder(responder)
00146 {
00147         if (numbytes <= 0)
00148         {
00149                 llwarns << "LLLFSThread: Request with numbytes = " << numbytes << llendl;
00150         }
00151 }
00152 
00153 LLLFSThread::Request::~Request()
00154 {
00155 }
00156 
00157 // virtual, called from own thread
00158 void LLLFSThread::Request::finishRequest(bool completed)
00159 {
00160         if (mResponder.notNull())
00161         {
00162                 mResponder->completed(completed ? mBytesRead : 0);
00163                 mResponder = NULL;
00164         }
00165 }
00166 
00167 void LLLFSThread::Request::deleteRequest()
00168 {
00169         if (getStatus() == STATUS_QUEUED)
00170         {
00171                 llerrs << "Attempt to delete a queued LLLFSThread::Request!" << llendl;
00172         }       
00173         if (mResponder.notNull())
00174         {
00175                 mResponder->completed(0);
00176                 mResponder = NULL;
00177         }
00178         LLQueuedThread::QueuedRequest::deleteRequest();
00179 }
00180 
00181 bool LLLFSThread::Request::processRequest()
00182 {
00183         bool complete = false;
00184         if (mOperation ==  FILE_READ)
00185         {
00186                 llassert(mOffset >= 0);
00187                 apr_file_t* filep = ll_apr_file_open(mFileName, LL_APR_RB, mThread->mAPRPoolp);
00188                 if (!filep)
00189                 {
00190                         llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
00191                         mBytesRead = 0; // fail
00192                         return true;
00193                 }
00194                 S32 off;
00195                 if (mOffset < 0)
00196                         off = ll_apr_file_seek(filep, APR_END, 0);
00197                 else
00198                         off = ll_apr_file_seek(filep, APR_SET, mOffset);
00199                 llassert_always(off >= 0);
00200                 mBytesRead = ll_apr_file_read(filep, mBuffer, mBytes );
00201                 apr_file_close(filep);
00202                 complete = true;
00203 //              llinfos << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << llendl;
00204         }
00205         else if (mOperation ==  FILE_WRITE)
00206         {
00207                 apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
00208                 if (mOffset < 0)
00209                         flags |= APR_APPEND;
00210                 apr_file_t* filep = ll_apr_file_open(mFileName, flags, mThread->mAPRPoolp);
00211                 if (!filep)
00212                 {
00213                         llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;
00214                         mBytesRead = 0; // fail
00215                         return true;
00216                 }
00217                 if (mOffset >= 0)
00218                 {
00219                         S32 seek = ll_apr_file_seek(filep, APR_SET, mOffset);
00220                         if (seek < 0)
00221                         {
00222                                 apr_file_close(filep);
00223                                 llwarns << "LLLFS: Unable to write file (seek failed): " << mFileName << llendl;
00224                                 mBytesRead = 0; // fail
00225                                 return true;
00226                         }
00227                 }
00228                 mBytesRead = ll_apr_file_write(filep, mBuffer, mBytes );
00229                 complete = true;
00230                 apr_file_close(filep);
00231 //              llinfos << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << llendl;
00232         }
00233         else
00234         {
00235                 llerrs << "LLLFSThread::unknown operation: " << (S32)mOperation << llendl;
00236         }
00237         return complete;
00238 }
00239 
00240 //============================================================================
00241 
00242 LLLFSThread::Responder::~Responder()
00243 {
00244 }
00245 
00246 //============================================================================

Generated on Thu Jul 1 06:08:48 2010 for Second Life Viewer by  doxygen 1.4.7