PageRenderTime 21ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llvfs/lllfsthread.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 243 lines | 174 code | 29 blank | 40 comment | 27 complexity | e24223b915c8513f8cd102b3ad090dad MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lllfsthread.cpp
  3. * @brief LLLFSThread base class
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "lllfsthread.h"
  28. #include "llstl.h"
  29. #include "llapr.h"
  30. //============================================================================
  31. /*static*/ LLLFSThread* LLLFSThread::sLocal = NULL;
  32. //============================================================================
  33. // Run on MAIN thread
  34. //static
  35. void LLLFSThread::initClass(bool local_is_threaded)
  36. {
  37. llassert(sLocal == NULL);
  38. sLocal = new LLLFSThread(local_is_threaded);
  39. }
  40. //static
  41. S32 LLLFSThread::updateClass(U32 ms_elapsed)
  42. {
  43. sLocal->update(ms_elapsed);
  44. return sLocal->getPending();
  45. }
  46. //static
  47. void LLLFSThread::cleanupClass()
  48. {
  49. sLocal->setQuitting();
  50. while (sLocal->getPending())
  51. {
  52. sLocal->update(0);
  53. }
  54. delete sLocal;
  55. sLocal = 0;
  56. }
  57. //----------------------------------------------------------------------------
  58. LLLFSThread::LLLFSThread(bool threaded) :
  59. LLQueuedThread("LFS", threaded),
  60. mPriorityCounter(PRIORITY_LOWBITS)
  61. {
  62. if(!mLocalAPRFilePoolp)
  63. {
  64. mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
  65. }
  66. }
  67. LLLFSThread::~LLLFSThread()
  68. {
  69. // ~LLQueuedThread() will be called here
  70. }
  71. //----------------------------------------------------------------------------
  72. LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfinder: ignore */
  73. U8* buffer, S32 offset, S32 numbytes,
  74. Responder* responder, U32 priority)
  75. {
  76. handle_t handle = generateHandle();
  77. if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter();
  78. else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW
  79. Request* req = new Request(this, handle, priority,
  80. FILE_READ, filename,
  81. buffer, offset, numbytes,
  82. responder);
  83. bool res = addRequest(req);
  84. if (!res)
  85. {
  86. llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
  87. }
  88. return handle;
  89. }
  90. LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,
  91. U8* buffer, S32 offset, S32 numbytes,
  92. Responder* responder, U32 priority)
  93. {
  94. handle_t handle = generateHandle();
  95. if (priority == 0) priority = PRIORITY_LOW | priorityCounter();
  96. Request* req = new Request(this, handle, priority,
  97. FILE_WRITE, filename,
  98. buffer, offset, numbytes,
  99. responder);
  100. bool res = addRequest(req);
  101. if (!res)
  102. {
  103. llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
  104. }
  105. return handle;
  106. }
  107. //============================================================================
  108. LLLFSThread::Request::Request(LLLFSThread* thread,
  109. handle_t handle, U32 priority,
  110. operation_t op, const std::string& filename,
  111. U8* buffer, S32 offset, S32 numbytes,
  112. Responder* responder) :
  113. QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
  114. mThread(thread),
  115. mOperation(op),
  116. mFileName(filename),
  117. mBuffer(buffer),
  118. mOffset(offset),
  119. mBytes(numbytes),
  120. mBytesRead(0),
  121. mResponder(responder)
  122. {
  123. if (numbytes <= 0)
  124. {
  125. llwarns << "LLLFSThread: Request with numbytes = " << numbytes << llendl;
  126. }
  127. }
  128. LLLFSThread::Request::~Request()
  129. {
  130. }
  131. // virtual, called from own thread
  132. void LLLFSThread::Request::finishRequest(bool completed)
  133. {
  134. if (mResponder.notNull())
  135. {
  136. mResponder->completed(completed ? mBytesRead : 0);
  137. mResponder = NULL;
  138. }
  139. }
  140. void LLLFSThread::Request::deleteRequest()
  141. {
  142. if (getStatus() == STATUS_QUEUED)
  143. {
  144. llerrs << "Attempt to delete a queued LLLFSThread::Request!" << llendl;
  145. }
  146. if (mResponder.notNull())
  147. {
  148. mResponder->completed(0);
  149. mResponder = NULL;
  150. }
  151. LLQueuedThread::QueuedRequest::deleteRequest();
  152. }
  153. bool LLLFSThread::Request::processRequest()
  154. {
  155. bool complete = false;
  156. if (mOperation == FILE_READ)
  157. {
  158. llassert(mOffset >= 0);
  159. LLAPRFile infile ; // auto-closes
  160. infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool());
  161. if (!infile.getFileHandle())
  162. {
  163. llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
  164. mBytesRead = 0; // fail
  165. return true;
  166. }
  167. S32 off;
  168. if (mOffset < 0)
  169. off = infile.seek(APR_END, 0);
  170. else
  171. off = infile.seek(APR_SET, mOffset);
  172. llassert_always(off >= 0);
  173. mBytesRead = infile.read(mBuffer, mBytes );
  174. complete = true;
  175. // llinfos << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << llendl;
  176. }
  177. else if (mOperation == FILE_WRITE)
  178. {
  179. apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
  180. if (mOffset < 0)
  181. flags |= APR_APPEND;
  182. LLAPRFile outfile ; // auto-closes
  183. outfile.open(mFileName, flags, mThread->getLocalAPRFilePool());
  184. if (!outfile.getFileHandle())
  185. {
  186. llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;
  187. mBytesRead = 0; // fail
  188. return true;
  189. }
  190. if (mOffset >= 0)
  191. {
  192. S32 seek = outfile.seek(APR_SET, mOffset);
  193. if (seek < 0)
  194. {
  195. llwarns << "LLLFS: Unable to write file (seek failed): " << mFileName << llendl;
  196. mBytesRead = 0; // fail
  197. return true;
  198. }
  199. }
  200. mBytesRead = outfile.write(mBuffer, mBytes );
  201. complete = true;
  202. // llinfos << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << llendl;
  203. }
  204. else
  205. {
  206. llerrs << "LLLFSThread::unknown operation: " << (S32)mOperation << llendl;
  207. }
  208. return complete;
  209. }
  210. //============================================================================
  211. LLLFSThread::Responder::~Responder()
  212. {
  213. }
  214. //============================================================================