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