00001
00032 #include "linden_common.h"
00033 #include "llmath.h"
00034 #include "llvfsthread.h"
00035 #include "llstl.h"
00036
00037
00038
00039 std::string LLVFSThread::sDataPath = "";
00040
00041 LLVFSThread* LLVFSThread::sLocal = NULL;
00042
00043
00044
00045
00046 void LLVFSThread::initClass(bool local_is_threaded)
00047 {
00048 llassert(sLocal == NULL);
00049 sLocal = new LLVFSThread(local_is_threaded);
00050 }
00051
00052
00053 S32 LLVFSThread::updateClass(U32 ms_elapsed)
00054 {
00055 sLocal->update(ms_elapsed);
00056 return sLocal->getPending();
00057 }
00058
00059
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
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);
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
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
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
00231 {
00232 mVFS->incLock(mFileID, mFileType, VFSLOCK_READ);
00233 }
00234 }
00235
00236
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
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
00283 }
00284 else if (mOperation == FILE_WRITE)
00285 {
00286 mBytesRead = mVFS->storeData(mFileID, mFileType, mBuffer, mOffset, mBytes);
00287 complete = true;
00288
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
00298 }
00299 else
00300 {
00301 llerrs << llformat("LLVFSThread::unknown operation: %d", mOperation) << llendl;
00302 }
00303 return complete;
00304 }
00305
00306