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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lllfsthread.cpp
  3.  * @brief LLLFSThread base class
  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 "lllfsthread.h"
  34. #include "llstl.h"
  35. #include "llapr.h"
  36. //============================================================================
  37. /*static*/ LLLFSThread* LLLFSThread::sLocal = NULL;
  38. //============================================================================
  39. // Run on MAIN thread
  40. //static
  41. void LLLFSThread::initClass(bool local_is_threaded)
  42. {
  43. llassert(sLocal == NULL);
  44. sLocal = new LLLFSThread(local_is_threaded);
  45. }
  46. //static
  47. S32 LLLFSThread::updateClass(U32 ms_elapsed)
  48. {
  49. sLocal->update(ms_elapsed);
  50. return sLocal->getPending();
  51. }
  52. //static
  53. void LLLFSThread::cleanupClass()
  54. {
  55. sLocal->setQuitting();
  56. while (sLocal->getPending())
  57. {
  58. sLocal->update(0);
  59. }
  60. delete sLocal;
  61. sLocal = 0;
  62. }
  63. //----------------------------------------------------------------------------
  64. LLLFSThread::LLLFSThread(bool threaded) :
  65. LLQueuedThread("LFS", threaded),
  66. mPriorityCounter(PRIORITY_LOWBITS)
  67. {
  68. if(!mLocalAPRFilePoolp)
  69. {
  70. mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
  71. }
  72. }
  73. LLLFSThread::~LLLFSThread()
  74. {
  75. // ~LLQueuedThread() will be called here
  76. }
  77. //----------------------------------------------------------------------------
  78. LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfinder: ignore */ 
  79. U8* buffer, S32 offset, S32 numbytes,
  80. Responder* responder, U32 priority)
  81. {
  82. handle_t handle = generateHandle();
  83. if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter();
  84. else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW
  85. Request* req = new Request(this, handle, priority,
  86.    FILE_READ, filename,
  87.    buffer, offset, numbytes,
  88.    responder);
  89. bool res = addRequest(req);
  90. if (!res)
  91. {
  92. llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
  93. }
  94. return handle;
  95. }
  96. LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,
  97.  U8* buffer, S32 offset, S32 numbytes,
  98.  Responder* responder, U32 priority)
  99. {
  100. handle_t handle = generateHandle();
  101. if (priority == 0) priority = PRIORITY_LOW | priorityCounter();
  102. Request* req = new Request(this, handle, priority,
  103.    FILE_WRITE, filename,
  104.    buffer, offset, numbytes,
  105.    responder);
  106. bool res = addRequest(req);
  107. if (!res)
  108. {
  109. llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
  110. }
  111. return handle;
  112. }
  113. //============================================================================
  114. LLLFSThread::Request::Request(LLLFSThread* thread,
  115.   handle_t handle, U32 priority,
  116.   operation_t op, const std::string& filename,
  117.   U8* buffer, S32 offset, S32 numbytes,
  118.   Responder* responder) :
  119. QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
  120. mThread(thread),
  121. mOperation(op),
  122. mFileName(filename),
  123. mBuffer(buffer),
  124. mOffset(offset),
  125. mBytes(numbytes),
  126. mBytesRead(0),
  127. mResponder(responder)
  128. {
  129. if (numbytes <= 0)
  130. {
  131. llwarns << "LLLFSThread: Request with numbytes = " << numbytes << llendl;
  132. }
  133. }
  134. LLLFSThread::Request::~Request()
  135. {
  136. }
  137. // virtual, called from own thread
  138. void LLLFSThread::Request::finishRequest(bool completed)
  139. {
  140. if (mResponder.notNull())
  141. {
  142. mResponder->completed(completed ? mBytesRead : 0);
  143. mResponder = NULL;
  144. }
  145. }
  146. void LLLFSThread::Request::deleteRequest()
  147. {
  148. if (getStatus() == STATUS_QUEUED)
  149. {
  150. llerrs << "Attempt to delete a queued LLLFSThread::Request!" << llendl;
  151. }
  152. if (mResponder.notNull())
  153. {
  154. mResponder->completed(0);
  155. mResponder = NULL;
  156. }
  157. LLQueuedThread::QueuedRequest::deleteRequest();
  158. }
  159. bool LLLFSThread::Request::processRequest()
  160. {
  161. bool complete = false;
  162. if (mOperation ==  FILE_READ)
  163. {
  164. llassert(mOffset >= 0);
  165. LLAPRFile infile ;
  166. infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool());
  167. if (!infile.getFileHandle())
  168. {
  169. llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
  170. mBytesRead = 0; // fail
  171. return true;
  172. }
  173. S32 off;
  174. if (mOffset < 0)
  175. off = infile.seek(APR_END, 0);
  176. else
  177. off = infile.seek(APR_SET, mOffset);
  178. llassert_always(off >= 0);
  179. mBytesRead = infile.read(mBuffer, mBytes );
  180. complete = true;
  181. infile.close() ;
  182. //  llinfos << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << llendl;
  183. }
  184. else if (mOperation ==  FILE_WRITE)
  185. {
  186. apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
  187. if (mOffset < 0)
  188. flags |= APR_APPEND;
  189. LLAPRFile outfile ;
  190. outfile.open(mFileName, flags, mThread->getLocalAPRFilePool());
  191. if (!outfile.getFileHandle())
  192. {
  193. llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;
  194. mBytesRead = 0; // fail
  195. return true;
  196. }
  197. if (mOffset >= 0)
  198. {
  199. S32 seek = outfile.seek(APR_SET, mOffset);
  200. if (seek < 0)
  201. {
  202. llwarns << "LLLFS: Unable to write file (seek failed): " << mFileName << llendl;
  203. mBytesRead = 0; // fail
  204. return true;
  205. }
  206. }
  207. mBytesRead = outfile.write(mBuffer, mBytes );
  208. complete = true;
  209. //  llinfos << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << llendl;
  210. }
  211. else
  212. {
  213. llerrs << "LLLFSThread::unknown operation: " << (S32)mOperation << llendl;
  214. }
  215. return complete;
  216. }
  217. //============================================================================
  218. LLLFSThread::Responder::~Responder()
  219. {
  220. }
  221. //============================================================================