llvfsthread.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 #include "llmath.h"
00034 #include "llvfsthread.h"
00035 #include "llstl.h"
00036 
00037 //============================================================================
00038 
00039 /*static*/ std::string LLVFSThread::sDataPath = "";
00040 
00041 /*static*/ LLVFSThread* LLVFSThread::sLocal = NULL;
00042 
00043 //============================================================================
00044 // Run on MAIN thread
00045 //static
00046 void LLVFSThread::initClass(bool local_is_threaded)
00047 {
00048         llassert(sLocal == NULL);
00049         sLocal = new LLVFSThread(local_is_threaded);
00050 }
00051 
00052 //static
00053 S32 LLVFSThread::updateClass(U32 ms_elapsed)
00054 {
00055         sLocal->update(ms_elapsed);
00056         return sLocal->getPending();
00057 }
00058 
00059 //static
00060 void LLVFSThread::cleanupClass()
00061 {
00062         sLocal->setQuitting();
00063         while (sLocal->getPending())
00064         {
00065                 sLocal->update(0);
00066         }
00067         delete sLocal;
00068         sLocal = 0;
00069 }
00070 
00071 //----------------------------------------------------------------------------
00072 
00073 LLVFSThread::LLVFSThread(bool threaded) :
00074         LLQueuedThread("VFS", threaded)
00075 {
00076 }
00077 
00078 LLVFSThread::~LLVFSThread()
00079 {
00080         // ~LLQueuedThread() will be called here
00081 }
00082 
00083 //----------------------------------------------------------------------------
00084 
00085 LLVFSThread::handle_t LLVFSThread::read(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
00086                                                                                 U8* buffer, S32 offset, S32 numbytes, U32 priority, U32 flags)
00087 {
00088         handle_t handle = generateHandle();
00089 
00090         priority = llmax(priority, (U32)PRIORITY_LOW); // All reads are at least PRIORITY_LOW
00091         Request* req = new Request(handle, priority, flags, FILE_READ, vfs, file_id, file_type,
00092                                                            buffer, offset, numbytes);
00093 
00094         bool res = addRequest(req);
00095         if (!res)
00096         {
00097                 llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
00098                 req->deleteRequest();
00099                 handle = nullHandle();
00100         }
00101 
00102         return handle;
00103 }
00104 
00105 S32 LLVFSThread::readImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
00106                                                            U8* buffer, S32 offset, S32 numbytes)
00107 {
00108         handle_t handle = generateHandle();
00109 
00110         Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0, FILE_READ, vfs, file_id, file_type,
00111                                                            buffer, offset, numbytes);
00112         
00113         S32 res = addRequest(req) ? 1 : 0;
00114         if (res == 0)
00115         {
00116                 llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
00117                 req->deleteRequest();
00118         }
00119         else
00120         {
00121                 llverify(waitForResult(handle, false) == true);
00122                 res = req->getBytesRead();
00123                 completeRequest(handle);
00124         }
00125         return res;
00126 }
00127 
00128 LLVFSThread::handle_t LLVFSThread::write(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
00129                                                                                  U8* buffer, S32 offset, S32 numbytes, U32 flags)
00130 {
00131         handle_t handle = generateHandle();
00132 
00133         Request* req = new Request(handle, 0, flags, FILE_WRITE, vfs, file_id, file_type,
00134                                                            buffer, offset, numbytes);
00135 
00136         bool res = addRequest(req);
00137         if (!res)
00138         {
00139                 llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
00140                 req->deleteRequest();
00141                 handle = nullHandle();
00142         }
00143         
00144         return handle;
00145 }
00146 
00147 S32 LLVFSThread::writeImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
00148                                                                  U8* buffer, S32 offset, S32 numbytes)
00149 {
00150         handle_t handle = generateHandle();
00151 
00152         Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0, FILE_WRITE, vfs, file_id, file_type,
00153                                                            buffer, offset, numbytes);
00154 
00155         S32 res = addRequest(req) ? 1 : 0;
00156         if (res == 0)
00157         {
00158                 llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
00159                 req->deleteRequest();
00160         }
00161         else
00162         {
00163                 llverify(waitForResult(handle, false) == true);
00164                 res = req->getBytesRead();
00165                 completeRequest(handle);
00166         }
00167         return res;
00168 }
00169 
00170 
00171 // LLVFSThread::handle_t LLVFSThread::rename(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
00172 //                                                                                const LLUUID &new_id, const LLAssetType::EType new_type, U32 flags)
00173 // {
00174 //      handle_t handle = generateHandle();
00175 
00176 //      LLUUID* new_idp = new LLUUID(new_id); // deleted with Request
00177 //      // new_type is passed as "numbytes"
00178 //      Request* req = new Request(handle, 0, flags, FILE_RENAME, vfs, file_id, file_type,
00179 //                                                         (U8*)new_idp, 0, (S32)new_type);
00180 
00181 //      bool res = addRequest(req);
00182 //      if (!res)
00183 //      {
00184 //              llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
00185 //              req->deleteRequest();
00186 //              handle = nullHandle();
00187 //      }
00188         
00189 //      return handle;
00190 // }
00191 
00192 //============================================================================
00193 
00194 LLVFSThread::Request::Request(handle_t handle, U32 priority, U32 flags,
00195                                                           operation_t op, LLVFS* vfs,
00196                                                           const LLUUID &file_id, const LLAssetType::EType file_type,
00197                                                           U8* buffer, S32 offset, S32 numbytes) :
00198         QueuedRequest(handle, priority, flags),
00199         mOperation(op),
00200         mVFS(vfs),
00201         mFileID(file_id),
00202         mFileType(file_type),
00203         mBuffer(buffer),
00204         mOffset(offset),
00205         mBytes(numbytes),
00206         mBytesRead(0)
00207 {
00208         llassert(mBuffer);
00209 
00210         if (numbytes <= 0 && mOperation != FILE_RENAME)
00211         {
00212                 llwarns << "LLVFSThread: Request with numbytes = " << numbytes 
00213                         << " operation = " << op
00214                         << " offset " << offset 
00215                         << " file_type " << file_type << llendl;
00216         }
00217         if (mOperation == FILE_WRITE)
00218         {
00219                 S32 blocksize =  mVFS->getMaxSize(mFileID, mFileType);
00220                 if (blocksize < 0)
00221                 {
00222                         llwarns << "VFS write to temporary block (shouldn't happen)" << llendl;
00223                 }
00224                 mVFS->incLock(mFileID, mFileType, VFSLOCK_APPEND);
00225         }
00226         else if (mOperation == FILE_RENAME)
00227         {
00228                 mVFS->incLock(mFileID, mFileType, VFSLOCK_APPEND);
00229         }
00230         else // if (mOperation == FILE_READ)
00231         {
00232                 mVFS->incLock(mFileID, mFileType, VFSLOCK_READ);
00233         }
00234 }
00235 
00236 // dec locks as soon as a request finishes
00237 void LLVFSThread::Request::finishRequest(bool completed)
00238 {
00239         if (mOperation == FILE_WRITE)
00240         {
00241                 mVFS->decLock(mFileID, mFileType, VFSLOCK_APPEND);
00242         }
00243         else if (mOperation == FILE_RENAME)
00244         {
00245                 mVFS->decLock(mFileID, mFileType, VFSLOCK_APPEND);
00246         }
00247         else // if (mOperation == FILE_READ)
00248         {
00249                 mVFS->decLock(mFileID, mFileType, VFSLOCK_READ);
00250         }
00251 }
00252 
00253 void LLVFSThread::Request::deleteRequest()
00254 {
00255         if (getStatus() == STATUS_QUEUED)
00256         {
00257                 llerrs << "Attempt to delete a queued LLVFSThread::Request!" << llendl;
00258         }       
00259         if (mOperation == FILE_WRITE)
00260         {
00261                 if (mFlags & FLAG_AUTO_DELETE)
00262                 {
00263                         delete [] mBuffer;
00264                 }
00265         }
00266         else if (mOperation == FILE_RENAME)
00267         {
00268                 LLUUID* new_idp = (LLUUID*)mBuffer;
00269                 delete new_idp;
00270         }
00271         LLQueuedThread::QueuedRequest::deleteRequest();
00272 }
00273 
00274 bool LLVFSThread::Request::processRequest()
00275 {
00276         bool complete = false;
00277         if (mOperation ==  FILE_READ)
00278         {
00279                 llassert(mOffset >= 0);
00280                 mBytesRead = mVFS->getData(mFileID, mFileType, mBuffer, mOffset, mBytes);
00281                 complete = true;
00282                 //llinfos << llformat("LLVFSThread::READ '%s': %d bytes arg:%d",getFilename(),mBytesRead) << llendl;
00283         }
00284         else if (mOperation ==  FILE_WRITE)
00285         {
00286                 mBytesRead = mVFS->storeData(mFileID, mFileType, mBuffer, mOffset, mBytes);
00287                 complete = true;
00288                 //llinfos << llformat("LLVFSThread::WRITE '%s': %d bytes arg:%d",getFilename(),mBytesRead) << llendl;
00289         }
00290         else if (mOperation ==  FILE_RENAME)
00291         {
00292                 LLUUID* new_idp = (LLUUID*)mBuffer;
00293                 LLAssetType::EType new_type = (LLAssetType::EType)mBytes;
00294                 mVFS->renameFile(mFileID, mFileType, *new_idp, new_type);
00295                 mFileID = *new_idp;
00296                 complete = true;
00297                 //llinfos << llformat("LLVFSThread::RENAME '%s': %d bytes arg:%d",getFilename(),mBytesRead) << llendl;
00298         }
00299         else
00300         {
00301                 llerrs << llformat("LLVFSThread::unknown operation: %d", mOperation) << llendl;
00302         }
00303         return complete;
00304 }
00305 
00306 //============================================================================

Generated on Thu Jul 1 06:09:26 2010 for Second Life Viewer by  doxygen 1.4.7