00001
00032 #include "linden_common.h"
00033 #include "llmath.h"
00034 #include "lllfsthread.h"
00035 #include "llstl.h"
00036 #include "llapr.h"
00037
00038
00039
00040 LLLFSThread* LLLFSThread::sLocal = NULL;
00041
00042
00043
00044
00045 void LLLFSThread::initClass(bool local_is_threaded)
00046 {
00047 llassert(sLocal == NULL);
00048 sLocal = new LLLFSThread(local_is_threaded);
00049 }
00050
00051
00052 S32 LLLFSThread::updateClass(U32 ms_elapsed)
00053 {
00054 sLocal->update(ms_elapsed);
00055 return sLocal->getPending();
00056 }
00057
00058
00059 void LLLFSThread::cleanupClass()
00060 {
00061 sLocal->setQuitting();
00062 while (sLocal->getPending())
00063 {
00064 sLocal->update(0);
00065 }
00066 delete sLocal;
00067 sLocal = 0;
00068 }
00069
00070
00071
00072 LLLFSThread::LLLFSThread(bool threaded) :
00073 LLQueuedThread("LFS", threaded),
00074 mPriorityCounter(PRIORITY_LOWBITS)
00075 {
00076 }
00077
00078 LLLFSThread::~LLLFSThread()
00079 {
00080
00081 }
00082
00083
00084
00085 LLLFSThread::handle_t LLLFSThread::read(const LLString& filename,
00086 U8* buffer, S32 offset, S32 numbytes,
00087 Responder* responder, U32 priority)
00088 {
00089 handle_t handle = generateHandle();
00090
00091 if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter();
00092 else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW;
00093
00094 Request* req = new Request(this, handle, priority,
00095 FILE_READ, filename,
00096 buffer, offset, numbytes,
00097 responder);
00098
00099 bool res = addRequest(req);
00100 if (!res)
00101 {
00102 llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
00103 }
00104
00105 return handle;
00106 }
00107
00108 LLLFSThread::handle_t LLLFSThread::write(const LLString& filename,
00109 U8* buffer, S32 offset, S32 numbytes,
00110 Responder* responder, U32 priority)
00111 {
00112 handle_t handle = generateHandle();
00113
00114 if (priority == 0) priority = PRIORITY_LOW | priorityCounter();
00115
00116 Request* req = new Request(this, handle, priority,
00117 FILE_WRITE, filename,
00118 buffer, offset, numbytes,
00119 responder);
00120
00121 bool res = addRequest(req);
00122 if (!res)
00123 {
00124 llerrs << "LLLFSThread::read called after LLLFSThread::cleanupClass()" << llendl;
00125 }
00126
00127 return handle;
00128 }
00129
00130
00131
00132 LLLFSThread::Request::Request(LLLFSThread* thread,
00133 handle_t handle, U32 priority,
00134 operation_t op, const LLString& filename,
00135 U8* buffer, S32 offset, S32 numbytes,
00136 Responder* responder) :
00137 QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
00138 mThread(thread),
00139 mOperation(op),
00140 mFileName(filename),
00141 mBuffer(buffer),
00142 mOffset(offset),
00143 mBytes(numbytes),
00144 mBytesRead(0),
00145 mResponder(responder)
00146 {
00147 if (numbytes <= 0)
00148 {
00149 llwarns << "LLLFSThread: Request with numbytes = " << numbytes << llendl;
00150 }
00151 }
00152
00153 LLLFSThread::Request::~Request()
00154 {
00155 }
00156
00157
00158 void LLLFSThread::Request::finishRequest(bool completed)
00159 {
00160 if (mResponder.notNull())
00161 {
00162 mResponder->completed(completed ? mBytesRead : 0);
00163 mResponder = NULL;
00164 }
00165 }
00166
00167 void LLLFSThread::Request::deleteRequest()
00168 {
00169 if (getStatus() == STATUS_QUEUED)
00170 {
00171 llerrs << "Attempt to delete a queued LLLFSThread::Request!" << llendl;
00172 }
00173 if (mResponder.notNull())
00174 {
00175 mResponder->completed(0);
00176 mResponder = NULL;
00177 }
00178 LLQueuedThread::QueuedRequest::deleteRequest();
00179 }
00180
00181 bool LLLFSThread::Request::processRequest()
00182 {
00183 bool complete = false;
00184 if (mOperation == FILE_READ)
00185 {
00186 llassert(mOffset >= 0);
00187 apr_file_t* filep = ll_apr_file_open(mFileName, LL_APR_RB, mThread->mAPRPoolp);
00188 if (!filep)
00189 {
00190 llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
00191 mBytesRead = 0;
00192 return true;
00193 }
00194 S32 off;
00195 if (mOffset < 0)
00196 off = ll_apr_file_seek(filep, APR_END, 0);
00197 else
00198 off = ll_apr_file_seek(filep, APR_SET, mOffset);
00199 llassert_always(off >= 0);
00200 mBytesRead = ll_apr_file_read(filep, mBuffer, mBytes );
00201 apr_file_close(filep);
00202 complete = true;
00203
00204 }
00205 else if (mOperation == FILE_WRITE)
00206 {
00207 apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
00208 if (mOffset < 0)
00209 flags |= APR_APPEND;
00210 apr_file_t* filep = ll_apr_file_open(mFileName, flags, mThread->mAPRPoolp);
00211 if (!filep)
00212 {
00213 llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;
00214 mBytesRead = 0;
00215 return true;
00216 }
00217 if (mOffset >= 0)
00218 {
00219 S32 seek = ll_apr_file_seek(filep, APR_SET, mOffset);
00220 if (seek < 0)
00221 {
00222 apr_file_close(filep);
00223 llwarns << "LLLFS: Unable to write file (seek failed): " << mFileName << llendl;
00224 mBytesRead = 0;
00225 return true;
00226 }
00227 }
00228 mBytesRead = ll_apr_file_write(filep, mBuffer, mBytes );
00229 complete = true;
00230 apr_file_close(filep);
00231
00232 }
00233 else
00234 {
00235 llerrs << "LLLFSThread::unknown operation: " << (S32)mOperation << llendl;
00236 }
00237 return complete;
00238 }
00239
00240
00241
00242 LLLFSThread::Responder::~Responder()
00243 {
00244 }
00245
00246