llvfsthread.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:8k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llvfsthread.cpp
  3.  * @brief LLVFSThread implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llvfsthread.h"
  34. #include "llstl.h"
  35. //============================================================================
  36. /*static*/ std::string LLVFSThread::sDataPath = "";
  37. /*static*/ LLVFSThread* LLVFSThread::sLocal = NULL;
  38. //============================================================================
  39. // Run on MAIN thread
  40. //static
  41. void LLVFSThread::initClass(bool local_is_threaded)
  42. {
  43. llassert(sLocal == NULL);
  44. sLocal = new LLVFSThread(local_is_threaded);
  45. }
  46. //static
  47. S32 LLVFSThread::updateClass(U32 ms_elapsed)
  48. {
  49. sLocal->update(ms_elapsed);
  50. return sLocal->getPending();
  51. }
  52. //static
  53. void LLVFSThread::cleanupClass()
  54. {
  55. sLocal->setQuitting();
  56. while (sLocal->getPending())
  57. {
  58. sLocal->update(0);
  59. }
  60. delete sLocal;
  61. sLocal = 0;
  62. }
  63. //----------------------------------------------------------------------------
  64. LLVFSThread::LLVFSThread(bool threaded) :
  65. LLQueuedThread("VFS", threaded)
  66. {
  67. }
  68. LLVFSThread::~LLVFSThread()
  69. {
  70. // ~LLQueuedThread() will be called here
  71. }
  72. //----------------------------------------------------------------------------
  73. LLVFSThread::handle_t LLVFSThread::read(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
  74. U8* buffer, S32 offset, S32 numbytes, U32 priority, U32 flags)
  75. {
  76. handle_t handle = generateHandle();
  77. priority = llmax(priority, (U32)PRIORITY_LOW); // All reads are at least PRIORITY_LOW
  78. Request* req = new Request(handle, priority, flags, FILE_READ, vfs, file_id, file_type,
  79.    buffer, offset, numbytes);
  80. bool res = addRequest(req);
  81. if (!res)
  82. {
  83. llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
  84. req->deleteRequest();
  85. handle = nullHandle();
  86. }
  87. return handle;
  88. }
  89. S32 LLVFSThread::readImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
  90.    U8* buffer, S32 offset, S32 numbytes)
  91. {
  92. handle_t handle = generateHandle();
  93. Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0, FILE_READ, vfs, file_id, file_type,
  94.    buffer, offset, numbytes);
  95. S32 res = addRequest(req) ? 1 : 0;
  96. if (res == 0)
  97. {
  98. llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
  99. req->deleteRequest();
  100. }
  101. else
  102. {
  103. llverify(waitForResult(handle, false) == true);
  104. res = req->getBytesRead();
  105. completeRequest(handle);
  106. }
  107. return res;
  108. }
  109. LLVFSThread::handle_t LLVFSThread::write(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
  110.  U8* buffer, S32 offset, S32 numbytes, U32 flags)
  111. {
  112. handle_t handle = generateHandle();
  113. Request* req = new Request(handle, 0, flags, FILE_WRITE, vfs, file_id, file_type,
  114.    buffer, offset, numbytes);
  115. bool res = addRequest(req);
  116. if (!res)
  117. {
  118. llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
  119. req->deleteRequest();
  120. handle = nullHandle();
  121. }
  122. return handle;
  123. }
  124. S32 LLVFSThread::writeImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
  125.  U8* buffer, S32 offset, S32 numbytes)
  126. {
  127. handle_t handle = generateHandle();
  128. Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0, FILE_WRITE, vfs, file_id, file_type,
  129.    buffer, offset, numbytes);
  130. S32 res = addRequest(req) ? 1 : 0;
  131. if (res == 0)
  132. {
  133. llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
  134. req->deleteRequest();
  135. }
  136. else
  137. {
  138. llverify(waitForResult(handle, false) == true);
  139. res = req->getBytesRead();
  140. completeRequest(handle);
  141. }
  142. return res;
  143. }
  144. // LLVFSThread::handle_t LLVFSThread::rename(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
  145. //    const LLUUID &new_id, const LLAssetType::EType new_type, U32 flags)
  146. // {
  147. //  handle_t handle = generateHandle();
  148. //  LLUUID* new_idp = new LLUUID(new_id); // deleted with Request
  149. //  // new_type is passed as "numbytes"
  150. //  Request* req = new Request(handle, 0, flags, FILE_RENAME, vfs, file_id, file_type,
  151. //     (U8*)new_idp, 0, (S32)new_type);
  152. //  bool res = addRequest(req);
  153. //  if (!res)
  154. //  {
  155. //  llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
  156. //  req->deleteRequest();
  157. //  handle = nullHandle();
  158. //  }
  159. //  return handle;
  160. // }
  161. //============================================================================
  162. LLVFSThread::Request::Request(handle_t handle, U32 priority, U32 flags,
  163.   operation_t op, LLVFS* vfs,
  164.   const LLUUID &file_id, const LLAssetType::EType file_type,
  165.   U8* buffer, S32 offset, S32 numbytes) :
  166. QueuedRequest(handle, priority, flags),
  167. mOperation(op),
  168. mVFS(vfs),
  169. mFileID(file_id),
  170. mFileType(file_type),
  171. mBuffer(buffer),
  172. mOffset(offset),
  173. mBytes(numbytes),
  174. mBytesRead(0)
  175. {
  176. llassert(mBuffer);
  177. if (numbytes <= 0 && mOperation != FILE_RENAME)
  178. {
  179. llwarns << "LLVFSThread: Request with numbytes = " << numbytes 
  180. << " operation = " << op
  181. << " offset " << offset 
  182. << " file_type " << file_type << llendl;
  183. }
  184. if (mOperation == FILE_WRITE)
  185. {
  186. S32 blocksize =  mVFS->getMaxSize(mFileID, mFileType);
  187. if (blocksize < 0)
  188. {
  189. llwarns << "VFS write to temporary block (shouldn't happen)" << llendl;
  190. }
  191. mVFS->incLock(mFileID, mFileType, VFSLOCK_APPEND);
  192. }
  193. else if (mOperation == FILE_RENAME)
  194. {
  195. mVFS->incLock(mFileID, mFileType, VFSLOCK_APPEND);
  196. }
  197. else // if (mOperation == FILE_READ)
  198. {
  199. mVFS->incLock(mFileID, mFileType, VFSLOCK_READ);
  200. }
  201. }
  202. // dec locks as soon as a request finishes
  203. void LLVFSThread::Request::finishRequest(bool completed)
  204. {
  205. if (mOperation == FILE_WRITE)
  206. {
  207. mVFS->decLock(mFileID, mFileType, VFSLOCK_APPEND);
  208. }
  209. else if (mOperation == FILE_RENAME)
  210. {
  211. mVFS->decLock(mFileID, mFileType, VFSLOCK_APPEND);
  212. }
  213. else // if (mOperation == FILE_READ)
  214. {
  215. mVFS->decLock(mFileID, mFileType, VFSLOCK_READ);
  216. }
  217. }
  218. void LLVFSThread::Request::deleteRequest()
  219. {
  220. if (getStatus() == STATUS_QUEUED)
  221. {
  222. llerrs << "Attempt to delete a queued LLVFSThread::Request!" << llendl;
  223. }
  224. if (mOperation == FILE_WRITE)
  225. {
  226. if (mFlags & FLAG_AUTO_DELETE)
  227. {
  228. delete [] mBuffer;
  229. }
  230. }
  231. else if (mOperation == FILE_RENAME)
  232. {
  233. LLUUID* new_idp = (LLUUID*)mBuffer;
  234. delete new_idp;
  235. }
  236. LLQueuedThread::QueuedRequest::deleteRequest();
  237. }
  238. bool LLVFSThread::Request::processRequest()
  239. {
  240. bool complete = false;
  241. if (mOperation ==  FILE_READ)
  242. {
  243. llassert(mOffset >= 0);
  244. mBytesRead = mVFS->getData(mFileID, mFileType, mBuffer, mOffset, mBytes);
  245. complete = true;
  246. //llinfos << llformat("LLVFSThread::READ '%s': %d bytes arg:%d",getFilename(),mBytesRead) << llendl;
  247. }
  248. else if (mOperation ==  FILE_WRITE)
  249. {
  250. mBytesRead = mVFS->storeData(mFileID, mFileType, mBuffer, mOffset, mBytes);
  251. complete = true;
  252. //llinfos << llformat("LLVFSThread::WRITE '%s': %d bytes arg:%d",getFilename(),mBytesRead) << llendl;
  253. }
  254. else if (mOperation ==  FILE_RENAME)
  255. {
  256. LLUUID* new_idp = (LLUUID*)mBuffer;
  257. LLAssetType::EType new_type = (LLAssetType::EType)mBytes;
  258. mVFS->renameFile(mFileID, mFileType, *new_idp, new_type);
  259. mFileID = *new_idp;
  260. complete = true;
  261. //llinfos << llformat("LLVFSThread::RENAME '%s': %d bytes arg:%d",getFilename(),mBytesRead) << llendl;
  262. }
  263. else
  264. {
  265. llerrs << llformat("LLVFSThread::unknown operation: %d", mOperation) << llendl;
  266. }
  267. return complete;
  268. }
  269. //============================================================================