diff options
Diffstat (limited to '')
65 files changed, 4089 insertions, 1823 deletions
diff --git a/linden/indra/llcommon/files.lst b/linden/indra/llcommon/files.lst index 2482eec..5fcb8c7 100644 --- a/linden/indra/llcommon/files.lst +++ b/linden/indra/llcommon/files.lst | |||
@@ -2,18 +2,20 @@ llcommon/bitpack.cpp | |||
2 | llcommon/llapp.cpp | 2 | llcommon/llapp.cpp |
3 | llcommon/llapr.cpp | 3 | llcommon/llapr.cpp |
4 | llcommon/llassettype.cpp | 4 | llcommon/llassettype.cpp |
5 | llcommon/llbase32.cpp | ||
6 | llcommon/llbase64.cpp | ||
5 | llcommon/llcommon.cpp | 7 | llcommon/llcommon.cpp |
6 | llcommon/llcriticaldamp.cpp | 8 | llcommon/llcriticaldamp.cpp |
7 | llcommon/lldate.cpp | 9 | llcommon/lldate.cpp |
8 | llcommon/llerrorbuffer.cpp | ||
9 | llcommon/llerror.cpp | 10 | llcommon/llerror.cpp |
10 | llcommon/llerrorstream.cpp | ||
11 | llcommon/llerrorthread.cpp | 11 | llcommon/llerrorthread.cpp |
12 | llcommon/llevent.cpp | 12 | llcommon/llevent.cpp |
13 | llcommon/llfasttimer.cpp | 13 | llcommon/llfasttimer.cpp |
14 | llcommon/llfile.cpp | 14 | llcommon/llfile.cpp |
15 | llcommon/llfixedbuffer.cpp | 15 | llcommon/llfixedbuffer.cpp |
16 | llcommon/llformat.cpp | ||
16 | llcommon/llframetimer.cpp | 17 | llcommon/llframetimer.cpp |
18 | llcommon/llliveappconfig.cpp | ||
17 | llcommon/lllivefile.cpp | 19 | llcommon/lllivefile.cpp |
18 | llcommon/llmemory.cpp | 20 | llcommon/llmemory.cpp |
19 | llcommon/llmemorystream.cpp | 21 | llcommon/llmemorystream.cpp |
diff --git a/linden/indra/llcommon/imageids.h b/linden/indra/llcommon/imageids.h index 150322e..d65b374 100644 --- a/linden/indra/llcommon/imageids.h +++ b/linden/indra/llcommon/imageids.h | |||
@@ -50,7 +50,7 @@ | |||
50 | const LLUUID IMG_CLEAR ("11ee27f5-43c0-414e-afd5-d7f5688c351f"); // VIEWER | 50 | const LLUUID IMG_CLEAR ("11ee27f5-43c0-414e-afd5-d7f5688c351f"); // VIEWER |
51 | const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER | 51 | const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER |
52 | 52 | ||
53 | const LLUUID IMG_DEFAULT ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER | 53 | const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER |
54 | 54 | ||
55 | //const LLUUID IMG_SAND ("0ff70ead-4562-45f9-9e8a-52b1a3286868"); // VIEWER 1.5k | 55 | //const LLUUID IMG_SAND ("0ff70ead-4562-45f9-9e8a-52b1a3286868"); // VIEWER 1.5k |
56 | //const LLUUID IMG_GRASS ("5ab48dd5-05d0-4f1a-ace6-efd4e2fb3508"); // VIEWER 1.2k | 56 | //const LLUUID IMG_GRASS ("5ab48dd5-05d0-4f1a-ace6-efd4e2fb3508"); // VIEWER 1.2k |
diff --git a/linden/indra/llcommon/indra_constants.h b/linden/indra/llcommon/indra_constants.h index 31c2559..deb9c9d 100644 --- a/linden/indra/llcommon/indra_constants.h +++ b/linden/indra/llcommon/indra_constants.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #ifndef LL_INDRA_CONSTANTS_H | 28 | #ifndef LL_INDRA_CONSTANTS_H |
29 | #define LL_INDRA_CONSTANTS_H | 29 | #define LL_INDRA_CONSTANTS_H |
30 | 30 | ||
31 | #include "stdtypes.h" | ||
31 | #include "lluuid.h" | 32 | #include "lluuid.h" |
32 | 33 | ||
33 | // Viewer object cache version, change if object update | 34 | // Viewer object cache version, change if object update |
@@ -105,8 +106,8 @@ const char* const DEFAULT_LOCAL_ASSET_SERVER = "http://localhost:12041/asset/tmp | |||
105 | const char* const LOCAL_ASSET_URL_FORMAT = "http://%s:12041/asset"; | 106 | const char* const LOCAL_ASSET_URL_FORMAT = "http://%s:12041/asset"; |
106 | 107 | ||
107 | const U32 DEFAULT_LAUNCHER_PORT = 12029; | 108 | const U32 DEFAULT_LAUNCHER_PORT = 12029; |
108 | const U32 DEFAULT_BIGBOARD_PORT = 12030; | 109 | //const U32 DEFAULT_BIGBOARD_PORT = 12030; // Deprecated |
109 | const U32 DEFAULT_QUERYSIM_PORT = 12031; | 110 | //const U32 DEFAULT_QUERYSIM_PORT = 12031; // Deprecated |
110 | const U32 DEFAULT_DATA_SERVER_PORT = 12032; | 111 | const U32 DEFAULT_DATA_SERVER_PORT = 12032; |
111 | const U32 DEFAULT_SPACE_SERVER_PORT = 12033; | 112 | const U32 DEFAULT_SPACE_SERVER_PORT = 12033; |
112 | const U32 DEFAULT_VIEWER_PORT = 12034; | 113 | const U32 DEFAULT_VIEWER_PORT = 12034; |
@@ -115,8 +116,11 @@ const U32 DEFAULT_USER_SERVER_PORT = 12036; | |||
115 | const U32 DEFAULT_RPC_SERVER_PORT = 12037; | 116 | const U32 DEFAULT_RPC_SERVER_PORT = 12037; |
116 | const U32 DEFAULT_LOG_DATA_SERVER_PORT = 12039; | 117 | const U32 DEFAULT_LOG_DATA_SERVER_PORT = 12039; |
117 | const U32 DEFAULT_BACKBONE_PORT = 12040; | 118 | const U32 DEFAULT_BACKBONE_PORT = 12040; |
119 | const U32 DEFAULT_CGI_SERVICES_PORT = 12045; | ||
118 | const U32 DEFAULT_LOCAL_ASSET_PORT = 12041; | 120 | const U32 DEFAULT_LOCAL_ASSET_PORT = 12041; |
119 | const U32 DEFAULT_BACKBONE_CAP_PORT = 12042; | 121 | //const U32 DEFAULT_BACKBONE_CAP_PORT = 12042; // Deprecated |
122 | const U32 DEFAULT_CAP_PROXY_PORT = 12043; | ||
123 | const U32 DEFAULT_INV_DATA_SERVER_PORT = 12044; | ||
120 | 124 | ||
121 | // For automatic port discovery when running multiple viewers on one host | 125 | // For automatic port discovery when running multiple viewers on one host |
122 | const U32 PORT_DISCOVERY_RANGE_MIN = 13000; | 126 | const U32 PORT_DISCOVERY_RANGE_MIN = 13000; |
@@ -322,7 +326,7 @@ const U32 MAP_ITEM_TELEHUB = 0x01; | |||
322 | const U32 MAP_ITEM_PG_EVENT = 0x02; | 326 | const U32 MAP_ITEM_PG_EVENT = 0x02; |
323 | const U32 MAP_ITEM_MATURE_EVENT = 0x03; | 327 | const U32 MAP_ITEM_MATURE_EVENT = 0x03; |
324 | const U32 MAP_ITEM_POPULAR = 0x04; | 328 | const U32 MAP_ITEM_POPULAR = 0x04; |
325 | const U32 MAP_ITEM_AGENT_COUNT = 0x05; | 329 | //const U32 MAP_ITEM_AGENT_COUNT = 0x05; |
326 | const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06; | 330 | const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06; |
327 | const U32 MAP_ITEM_LAND_FOR_SALE = 0x07; | 331 | const U32 MAP_ITEM_LAND_FOR_SALE = 0x07; |
328 | const U32 MAP_ITEM_CLASSIFIED = 0x08; | 332 | const U32 MAP_ITEM_CLASSIFIED = 0x08; |
diff --git a/linden/indra/llcommon/linden_common.h b/linden/indra/llcommon/linden_common.h index ff77b3d..b1c5f3b 100644 --- a/linden/indra/llcommon/linden_common.h +++ b/linden/indra/llcommon/linden_common.h | |||
@@ -49,6 +49,7 @@ | |||
49 | #include "stdtypes.h" | 49 | #include "stdtypes.h" |
50 | #include "lldefs.h" | 50 | #include "lldefs.h" |
51 | #include "llerror.h" | 51 | #include "llerror.h" |
52 | #include "llformat.h" | ||
52 | #include "llstring.h" | 53 | #include "llstring.h" |
53 | #include "lltimer.h" | 54 | #include "lltimer.h" |
54 | #include "llfasttimer.h" | 55 | #include "llfasttimer.h" |
diff --git a/linden/indra/llcommon/llapp.cpp b/linden/indra/llcommon/llapp.cpp index 42d9050..f48ff8f 100644 --- a/linden/indra/llcommon/llapp.cpp +++ b/linden/indra/llcommon/llapp.cpp | |||
@@ -30,9 +30,11 @@ | |||
30 | 30 | ||
31 | #include "llcommon.h" | 31 | #include "llcommon.h" |
32 | #include "llapr.h" | 32 | #include "llapr.h" |
33 | #include "llerrorcontrol.h" | ||
33 | #include "llerrorthread.h" | 34 | #include "llerrorthread.h" |
34 | #include "llframetimer.h" | 35 | #include "llframetimer.h" |
35 | #include "llmemory.h" | 36 | #include "llmemory.h" |
37 | #include "lltimer.h" | ||
36 | 38 | ||
37 | // | 39 | // |
38 | // Signal handling | 40 | // Signal handling |
@@ -193,10 +195,8 @@ LLSD LLApp::getOptionData(OptionPriority level) | |||
193 | 195 | ||
194 | void LLApp::stepFrame() | 196 | void LLApp::stepFrame() |
195 | { | 197 | { |
196 | // Update the static frame timer. | ||
197 | LLFrameTimer::updateFrameTime(); | 198 | LLFrameTimer::updateFrameTime(); |
198 | 199 | LLEventTimer::updateClass(); | |
199 | // Run ready runnables | ||
200 | mRunner.run(); | 200 | mRunner.run(); |
201 | } | 201 | } |
202 | 202 | ||
@@ -563,7 +563,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) | |||
563 | else | 563 | else |
564 | { | 564 | { |
565 | // Don't log anything, even errors - this is because this signal could happen anywhere. | 565 | // Don't log anything, even errors - this is because this signal could happen anywhere. |
566 | gErrorStream.setLevel(LLErrorStream::NONE); | 566 | LLError::setDefaultLevel(LLError::LEVEL_NONE); |
567 | } | 567 | } |
568 | 568 | ||
569 | // Change the signal that we reraise to SIGABRT, so we generate a core dump. | 569 | // Change the signal that we reraise to SIGABRT, so we generate a core dump. |
diff --git a/linden/indra/llcommon/llapr.cpp b/linden/indra/llcommon/llapr.cpp index 665ee75..550a8d8 100644 --- a/linden/indra/llcommon/llapr.cpp +++ b/linden/indra/llcommon/llapr.cpp | |||
@@ -122,11 +122,13 @@ void ll_apr_assert_status(apr_status_t status) | |||
122 | llassert(ll_apr_warn_status(status) == false); | 122 | llassert(ll_apr_warn_status(status) == false); |
123 | } | 123 | } |
124 | 124 | ||
125 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep) | 125 | // File I/O |
126 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep, apr_pool_t* pool) | ||
126 | { | 127 | { |
127 | apr_file_t* apr_file; | 128 | apr_file_t* apr_file; |
128 | apr_status_t s; | 129 | apr_status_t s; |
129 | s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp); | 130 | if (pool == NULL) pool = gAPRPoolp; |
131 | s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool); | ||
130 | if (s != APR_SUCCESS) | 132 | if (s != APR_SUCCESS) |
131 | { | 133 | { |
132 | if (sizep) | 134 | if (sizep) |
@@ -142,6 +144,7 @@ apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* s | |||
142 | apr_off_t offset = 0; | 144 | apr_off_t offset = 0; |
143 | if (apr_file_seek(apr_file, APR_END, &offset) == APR_SUCCESS) | 145 | if (apr_file_seek(apr_file, APR_END, &offset) == APR_SUCCESS) |
144 | { | 146 | { |
147 | llassert_always(offset <= 0x7fffffff); | ||
145 | file_size = (S32)offset; | 148 | file_size = (S32)offset; |
146 | offset = 0; | 149 | offset = 0; |
147 | apr_file_seek(apr_file, APR_SET, &offset); | 150 | apr_file_seek(apr_file, APR_SET, &offset); |
@@ -151,6 +154,18 @@ apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* s | |||
151 | 154 | ||
152 | return apr_file; | 155 | return apr_file; |
153 | } | 156 | } |
157 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep) | ||
158 | { | ||
159 | return ll_apr_file_open(filename, flags, sizep, NULL); | ||
160 | } | ||
161 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, apr_pool_t* pool) | ||
162 | { | ||
163 | return ll_apr_file_open(filename, flags, NULL, pool); | ||
164 | } | ||
165 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags) | ||
166 | { | ||
167 | return ll_apr_file_open(filename, flags, NULL, NULL); | ||
168 | } | ||
154 | 169 | ||
155 | S32 ll_apr_file_read(apr_file_t* apr_file, void *buf, S32 nbytes) | 170 | S32 ll_apr_file_read(apr_file_t* apr_file, void *buf, S32 nbytes) |
156 | { | 171 | { |
@@ -162,10 +177,37 @@ S32 ll_apr_file_read(apr_file_t* apr_file, void *buf, S32 nbytes) | |||
162 | } | 177 | } |
163 | else | 178 | else |
164 | { | 179 | { |
180 | llassert_always(sz <= 0x7fffffff); | ||
165 | return (S32)sz; | 181 | return (S32)sz; |
166 | } | 182 | } |
167 | } | 183 | } |
168 | 184 | ||
185 | S32 ll_apr_file_read_ex(const LLString& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes) | ||
186 | { | ||
187 | if (pool == NULL) pool = gAPRPoolp; | ||
188 | apr_file_t* filep = ll_apr_file_open(filename, APR_READ|APR_BINARY, pool); | ||
189 | if (!filep) | ||
190 | { | ||
191 | return 0; | ||
192 | } | ||
193 | S32 off; | ||
194 | if (offset < 0) | ||
195 | off = ll_apr_file_seek(filep, APR_END, 0); | ||
196 | else | ||
197 | off = ll_apr_file_seek(filep, APR_SET, offset); | ||
198 | S32 bytes_read; | ||
199 | if (off < 0) | ||
200 | { | ||
201 | bytes_read = 0; | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | bytes_read = ll_apr_file_read(filep, buf, nbytes ); | ||
206 | } | ||
207 | apr_file_close(filep); | ||
208 | |||
209 | return bytes_read; | ||
210 | } | ||
169 | 211 | ||
170 | S32 ll_apr_file_write(apr_file_t* apr_file, const void *buf, S32 nbytes) | 212 | S32 ll_apr_file_write(apr_file_t* apr_file, const void *buf, S32 nbytes) |
171 | { | 213 | { |
@@ -177,28 +219,73 @@ S32 ll_apr_file_write(apr_file_t* apr_file, const void *buf, S32 nbytes) | |||
177 | } | 219 | } |
178 | else | 220 | else |
179 | { | 221 | { |
222 | llassert_always(sz <= 0x7fffffff); | ||
180 | return (S32)sz; | 223 | return (S32)sz; |
181 | } | 224 | } |
182 | } | 225 | } |
183 | 226 | ||
227 | S32 ll_apr_file_write_ex(const LLString& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes) | ||
228 | { | ||
229 | if (pool == NULL) pool = gAPRPoolp; | ||
230 | apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; | ||
231 | if (offset < 0) | ||
232 | { | ||
233 | flags |= APR_APPEND; | ||
234 | offset = 0; | ||
235 | } | ||
236 | apr_file_t* filep = ll_apr_file_open(filename, flags, pool); | ||
237 | if (!filep) | ||
238 | { | ||
239 | return 0; | ||
240 | } | ||
241 | if (offset > 0) | ||
242 | { | ||
243 | offset = ll_apr_file_seek(filep, APR_SET, offset); | ||
244 | } | ||
245 | S32 bytes_written; | ||
246 | if (offset < 0) | ||
247 | { | ||
248 | bytes_written = 0; | ||
249 | } | ||
250 | else | ||
251 | { | ||
252 | bytes_written = ll_apr_file_write(filep, buf, nbytes ); | ||
253 | } | ||
254 | apr_file_close(filep); | ||
255 | |||
256 | return bytes_written; | ||
257 | } | ||
258 | |||
184 | S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset) | 259 | S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset) |
185 | { | 260 | { |
186 | apr_off_t apr_offset = offset; | 261 | apr_status_t s; |
187 | apr_status_t s = apr_file_seek(apr_file, where, &apr_offset); | 262 | apr_off_t apr_offset; |
263 | if (offset >= 0) | ||
264 | { | ||
265 | apr_offset = (apr_off_t)offset; | ||
266 | s = apr_file_seek(apr_file, where, &apr_offset); | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | apr_offset = 0; | ||
271 | s = apr_file_seek(apr_file, APR_END, &apr_offset); | ||
272 | } | ||
188 | if (s != APR_SUCCESS) | 273 | if (s != APR_SUCCESS) |
189 | { | 274 | { |
190 | return -1; | 275 | return -1; |
191 | } | 276 | } |
192 | else | 277 | else |
193 | { | 278 | { |
279 | llassert_always(apr_offset <= 0x7fffffff); | ||
194 | return (S32)apr_offset; | 280 | return (S32)apr_offset; |
195 | } | 281 | } |
196 | } | 282 | } |
197 | 283 | ||
198 | bool ll_apr_file_remove(const LLString& filename) | 284 | bool ll_apr_file_remove(const LLString& filename, apr_pool_t* pool) |
199 | { | 285 | { |
200 | apr_status_t s; | 286 | apr_status_t s; |
201 | s = apr_file_remove(filename.c_str(), gAPRPoolp); | 287 | if (pool == NULL) pool = gAPRPoolp; |
288 | s = apr_file_remove(filename.c_str(), pool); | ||
202 | if (s != APR_SUCCESS) | 289 | if (s != APR_SUCCESS) |
203 | { | 290 | { |
204 | llwarns << "ll_apr_file_remove failed on file: " << filename << llendl; | 291 | llwarns << "ll_apr_file_remove failed on file: " << filename << llendl; |
@@ -207,10 +294,11 @@ bool ll_apr_file_remove(const LLString& filename) | |||
207 | return true; | 294 | return true; |
208 | } | 295 | } |
209 | 296 | ||
210 | bool ll_apr_file_rename(const LLString& filename, const LLString& newname) | 297 | bool ll_apr_file_rename(const LLString& filename, const LLString& newname, apr_pool_t* pool) |
211 | { | 298 | { |
212 | apr_status_t s; | 299 | apr_status_t s; |
213 | s = apr_file_rename(filename.c_str(), newname.c_str(), gAPRPoolp); | 300 | if (pool == NULL) pool = gAPRPoolp; |
301 | s = apr_file_rename(filename.c_str(), newname.c_str(), pool); | ||
214 | if (s != APR_SUCCESS) | 302 | if (s != APR_SUCCESS) |
215 | { | 303 | { |
216 | llwarns << "ll_apr_file_rename failed on file: " << filename << llendl; | 304 | llwarns << "ll_apr_file_rename failed on file: " << filename << llendl; |
@@ -218,3 +306,73 @@ bool ll_apr_file_rename(const LLString& filename, const LLString& newname) | |||
218 | } | 306 | } |
219 | return true; | 307 | return true; |
220 | } | 308 | } |
309 | |||
310 | bool ll_apr_file_exists(const LLString& filename, apr_pool_t* pool) | ||
311 | { | ||
312 | apr_file_t* apr_file; | ||
313 | apr_status_t s; | ||
314 | if (pool == NULL) pool = gAPRPoolp; | ||
315 | s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool); | ||
316 | if (s != APR_SUCCESS || !apr_file) | ||
317 | { | ||
318 | return false; | ||
319 | } | ||
320 | else | ||
321 | { | ||
322 | apr_file_close(apr_file); | ||
323 | return true; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | S32 ll_apr_file_size(const LLString& filename, apr_pool_t* pool) | ||
328 | { | ||
329 | apr_file_t* apr_file; | ||
330 | apr_finfo_t info; | ||
331 | apr_status_t s; | ||
332 | if (pool == NULL) pool = gAPRPoolp; | ||
333 | s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool); | ||
334 | if (s != APR_SUCCESS || !apr_file) | ||
335 | { | ||
336 | return 0; | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file); | ||
341 | apr_file_close(apr_file); | ||
342 | if (s == APR_SUCCESS) | ||
343 | { | ||
344 | return (S32)info.size; | ||
345 | } | ||
346 | else | ||
347 | { | ||
348 | return 0; | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | |||
353 | bool ll_apr_dir_make(const LLString& dirname, apr_pool_t* pool) | ||
354 | { | ||
355 | apr_status_t s; | ||
356 | if (pool == NULL) pool = gAPRPoolp; | ||
357 | s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); | ||
358 | if (s != APR_SUCCESS) | ||
359 | { | ||
360 | llwarns << "ll_apr_file_remove failed on file: " << dirname << llendl; | ||
361 | return false; | ||
362 | } | ||
363 | return true; | ||
364 | } | ||
365 | |||
366 | bool ll_apr_dir_remove(const LLString& dirname, apr_pool_t* pool) | ||
367 | { | ||
368 | apr_status_t s; | ||
369 | if (pool == NULL) pool = gAPRPoolp; | ||
370 | s = apr_file_remove(dirname.c_str(), pool); | ||
371 | if (s != APR_SUCCESS) | ||
372 | { | ||
373 | llwarns << "ll_apr_file_remove failed on file: " << dirname << llendl; | ||
374 | return false; | ||
375 | } | ||
376 | return true; | ||
377 | } | ||
378 | |||
diff --git a/linden/indra/llcommon/llapr.h b/linden/indra/llcommon/llapr.h index a5c217c..be6fc6c 100644 --- a/linden/indra/llcommon/llapr.h +++ b/linden/indra/llcommon/llapr.h | |||
@@ -125,14 +125,24 @@ typedef LLAtomic32<S32> LLAtomicS32; | |||
125 | #define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb" | 125 | #define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb" |
126 | #define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b" | 126 | #define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b" |
127 | #define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b" | 127 | #define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b" |
128 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep = NULL); | 128 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep, apr_pool_t* pool); |
129 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, S32* sizep); | ||
130 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags, apr_pool_t* pool); | ||
131 | apr_file_t* ll_apr_file_open(const LLString& filename, apr_int32_t flags); | ||
129 | // Returns actual offset, -1 if seek fails | 132 | // Returns actual offset, -1 if seek fails |
130 | S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset); | 133 | S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset); |
131 | // Returns bytes read/written, 0 if read/write fails | 134 | // Returns bytes read/written, 0 if read/write fails: |
132 | S32 ll_apr_file_read(apr_file_t* apr_file, void* buf, S32 nbytes); | 135 | S32 ll_apr_file_read(apr_file_t* apr_file, void* buf, S32 nbytes); |
136 | S32 ll_apr_file_read_ex(const LLString& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes); | ||
133 | S32 ll_apr_file_write(apr_file_t* apr_file, const void* buf, S32 nbytes); | 137 | S32 ll_apr_file_write(apr_file_t* apr_file, const void* buf, S32 nbytes); |
134 | bool ll_apr_file_remove(const LLString& filename); | 138 | S32 ll_apr_file_write_ex(const LLString& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes); |
135 | bool ll_apr_file_rename(const LLString& filename, const LLString& newname); | 139 | // returns false if failure: |
140 | bool ll_apr_file_remove(const LLString& filename, apr_pool_t* pool = NULL); | ||
141 | bool ll_apr_file_rename(const LLString& filename, const LLString& newname, apr_pool_t* pool = NULL); | ||
142 | bool ll_apr_file_exists(const LLString& filename, apr_pool_t* pool = NULL); | ||
143 | S32 ll_apr_file_size(const LLString& filename, apr_pool_t* pool = NULL); | ||
144 | bool ll_apr_dir_make(const LLString& dirname, apr_pool_t* pool = NULL); | ||
145 | bool ll_apr_dir_remove(const LLString& dirname, apr_pool_t* pool = NULL); | ||
136 | 146 | ||
137 | /** | 147 | /** |
138 | * @brief Function which approprately logs error or remains quiet on | 148 | * @brief Function which approprately logs error or remains quiet on |
diff --git a/linden/indra/llcommon/llassettype.cpp b/linden/indra/llcommon/llassettype.cpp index 051092e..df00af8 100644 --- a/linden/indra/llcommon/llassettype.cpp +++ b/linden/indra/llcommon/llassettype.cpp | |||
@@ -203,6 +203,20 @@ const char* LLAssetType::lookupHumanReadable(LLAssetType::EType type) | |||
203 | } | 203 | } |
204 | } | 204 | } |
205 | 205 | ||
206 | // static | ||
207 | LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name ) | ||
208 | { | ||
209 | for( S32 i = 0; i < AT_COUNT; i++ ) | ||
210 | { | ||
211 | if( 0 == strcmp(name, mAssetTypeHumanNames[i]) ) | ||
212 | { | ||
213 | // match | ||
214 | return (EType)i; | ||
215 | } | ||
216 | } | ||
217 | return AT_NONE; | ||
218 | } | ||
219 | |||
206 | EDragAndDropType LLAssetType::lookupDragAndDropType( EType asset ) | 220 | EDragAndDropType LLAssetType::lookupDragAndDropType( EType asset ) |
207 | { | 221 | { |
208 | switch( asset ) | 222 | switch( asset ) |
diff --git a/linden/indra/llcommon/llassettype.h b/linden/indra/llcommon/llassettype.h index 67dc3ef..da4cf0b 100644 --- a/linden/indra/llcommon/llassettype.h +++ b/linden/indra/llcommon/llassettype.h | |||
@@ -145,6 +145,7 @@ public: | |||
145 | static const char* lookup(EType type); | 145 | static const char* lookup(EType type); |
146 | 146 | ||
147 | // translation from a type to a human readable form. | 147 | // translation from a type to a human readable form. |
148 | static EType lookupHumanReadable( const char* name ); | ||
148 | static const char* lookupHumanReadable(EType type); | 149 | static const char* lookupHumanReadable(EType type); |
149 | 150 | ||
150 | static EDragAndDropType lookupDragAndDropType( EType ); | 151 | static EDragAndDropType lookupDragAndDropType( EType ); |
diff --git a/linden/indra/llcommon/llavatarconstants.h b/linden/indra/llcommon/llavatarconstants.h index 3335949..1eb5b05 100644 --- a/linden/indra/llcommon/llavatarconstants.h +++ b/linden/indra/llcommon/llavatarconstants.h | |||
@@ -39,16 +39,16 @@ const char* const BLACKLIST_PROFILE_WEB_URL = "http://secondlife.com/app/webdisa | |||
39 | // Maximum number of avatar picks | 39 | // Maximum number of avatar picks |
40 | const S32 MAX_AVATAR_PICKS = 10; | 40 | const S32 MAX_AVATAR_PICKS = 10; |
41 | 41 | ||
42 | // For Flags in AvatarPropertiesReply | 42 | // For Flags in AvatarPropertiesReply |
43 | const U32 AVATAR_ALLOW_PUBLISH = 0x1 << 0; // whether profile is externally visible or not | 43 | const U32 AVATAR_ALLOW_PUBLISH = 0x1 << 0; // whether profile is externally visible or not |
44 | const U32 AVATAR_MATURE_PUBLISH = 0x1 << 1; // profile is "mature" | 44 | const U32 AVATAR_MATURE_PUBLISH = 0x1 << 1; // profile is "mature" |
45 | const U32 AVATAR_IDENTIFIED = 0x1 << 2; // whether avatar has provided payment info | 45 | const U32 AVATAR_IDENTIFIED = 0x1 << 2; // whether avatar has provided payment info |
46 | const U32 AVATAR_TRANSACTED = 0x1 << 3; // whether avatar has actively used payment info | 46 | const U32 AVATAR_TRANSACTED = 0x1 << 3; // whether avatar has actively used payment info |
47 | const U32 AVATAR_ONLINE = 0x1 << 4; // the online status of this avatar, if known. | 47 | const U32 AVATAR_ONLINE = 0x1 << 4; // the online status of this avatar, if known. |
48 | 48 | ||
49 | static const std::string VISIBILITY_DEFAULT("default"); | 49 | static const std::string VISIBILITY_DEFAULT("default"); |
50 | static const std::string VISIBILITY_HIDDEN("hidden"); | 50 | static const std::string VISIBILITY_HIDDEN("hidden"); |
51 | static const std::string VISIBILITY_VISIBLE("visible"); | 51 | static const std::string VISIBILITY_VISIBLE("visible"); |
52 | static const std::string VISIBILITY_INVISIBLE("invisible"); | 52 | static const std::string VISIBILITY_INVISIBLE("invisible"); |
53 | 53 | ||
54 | #endif | 54 | #endif |
diff --git a/linden/indra/llcommon/llbase32.cpp b/linden/indra/llcommon/llbase32.cpp new file mode 100644 index 0000000..711ba63 --- /dev/null +++ b/linden/indra/llcommon/llbase32.cpp | |||
@@ -0,0 +1,214 @@ | |||
1 | /** | ||
2 | * @file llbase32.cpp | ||
3 | * @brief base32 encoding that returns a std::string | ||
4 | * @author James Cook | ||
5 | * | ||
6 | * Based on code from bitter | ||
7 | * http://ghostwhitecrab.com/bitter/ | ||
8 | * | ||
9 | * Copyright (c) 2006 Christian Biere <christianbiere@gmx.de> | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * | ||
16 | * 1. Redistributions of source code must retain the above copyright | ||
17 | * notice, this list of conditions and the following disclaimer. | ||
18 | * 2. Redistributions in binary form must reproduce the above copyright | ||
19 | * notice, this list of conditions and the following disclaimer in the | ||
20 | * documentation and/or other materials provided with the distribution. | ||
21 | * 3. Neither the name of the authors nor the names of its contributors | ||
22 | * may be used to endorse or promote products derived from this software | ||
23 | * without specific prior written permission. | ||
24 | * | ||
25 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | ||
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
35 | * SUCH DAMAGE. | ||
36 | */ | ||
37 | |||
38 | #include "linden_common.h" | ||
39 | |||
40 | #include "llbase32.h" | ||
41 | |||
42 | #include <string> | ||
43 | |||
44 | // bitter - base32.c starts here | ||
45 | |||
46 | /* | ||
47 | * See RFC 3548 for details about Base 32 encoding: | ||
48 | * http://www.faqs.org/rfcs/rfc3548.html | ||
49 | */ | ||
50 | |||
51 | static const char base32_alphabet[32] = { | ||
52 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | ||
53 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | ||
54 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | ||
55 | 'Y', 'Z', '2', '3', '4', '5', '6', '7' | ||
56 | }; | ||
57 | |||
58 | size_t | ||
59 | base32_encode(char *dst, size_t size, const void *data, size_t len) | ||
60 | { | ||
61 | size_t i = 0; | ||
62 | const U8 *p = (const U8*)data; | ||
63 | const char *end = &dst[size]; | ||
64 | char *q = dst; | ||
65 | |||
66 | do { | ||
67 | size_t j, k; | ||
68 | U8 x[5]; | ||
69 | char s[8]; | ||
70 | |||
71 | switch (len - i) { | ||
72 | case 4: k = 7; break; | ||
73 | case 3: k = 5; break; | ||
74 | case 2: k = 3; break; | ||
75 | case 1: k = 2; break; | ||
76 | default: | ||
77 | k = 8; | ||
78 | } | ||
79 | |||
80 | for (j = 0; j < 5; j++) | ||
81 | x[j] = i < len ? p[i++] : 0; | ||
82 | |||
83 | /* | ||
84 | +-------+-----------+--------+ | ||
85 | | target| source | source | | ||
86 | | byte | bits | byte | | ||
87 | +-------+-----------+--------+ | ||
88 | | 0 | 7 6 5 4 3 | 0 | | ||
89 | | 1 | 2 1 0 7 6 | 0-1 | | ||
90 | | 2 | 5 4 3 2 1 | 1 | | ||
91 | | 3 | 0 7 6 5 4 | 1-2 | | ||
92 | | 4 | 3 2 1 0 7 | 2-3 | | ||
93 | | 5 | 6 5 4 3 2 | 3 | | ||
94 | | 6 | 1 0 7 6 5 | 3-4 | | ||
95 | | 7 | 4 3 2 1 0 | 4 | | ||
96 | +-------+-----------+--------+ | ||
97 | |||
98 | */ | ||
99 | |||
100 | s[0] = (x[0] >> 3); | ||
101 | s[1] = ((x[0] & 0x07) << 2) | (x[1] >> 6); | ||
102 | s[2] = (x[1] >> 1) & 0x1f; | ||
103 | s[3] = ((x[1] & 0x01) << 4) | (x[2] >> 4); | ||
104 | s[4] = ((x[2] & 0x0f) << 1) | (x[3] >> 7); | ||
105 | s[5] = (x[3] >> 2) & 0x1f; | ||
106 | s[6] = ((x[3] & 0x03) << 3) | (x[4] >> 5); | ||
107 | s[7] = x[4] & 0x1f; | ||
108 | |||
109 | for (j = 0; j < k && q != end; j++) | ||
110 | *q++ = base32_alphabet[(U8) s[j]]; | ||
111 | |||
112 | } while (i < len); | ||
113 | |||
114 | return q - dst; | ||
115 | } | ||
116 | |||
117 | /* *TODO: Implement base32 encode. | ||
118 | |||
119 | #define ARRAY_LEN(a) (sizeof (a) / sizeof((a)[0])) | ||
120 | |||
121 | static inline int | ||
122 | ascii_toupper(int c) | ||
123 | { | ||
124 | return c >= 97 && c <= 122 ? c - 32 : c; | ||
125 | } | ||
126 | |||
127 | static inline int | ||
128 | ascii_tolower(int c) | ||
129 | { | ||
130 | return c >= 65 && c <= 90 ? c + 32 : c; | ||
131 | } | ||
132 | |||
133 | |||
134 | static char base32_map[(unsigned char) -1]; | ||
135 | |||
136 | size_t | ||
137 | base32_decode(char *dst, size_t size, const void *data, size_t len) | ||
138 | { | ||
139 | const char *end = &dst[size]; | ||
140 | const unsigned char *p = data; | ||
141 | char *q = dst; | ||
142 | size_t i; | ||
143 | unsigned max_pad = 3; | ||
144 | |||
145 | if (0 == base32_map[0]) { | ||
146 | for (i = 0; i < ARRAY_LEN(base32_map); i++) { | ||
147 | const char *x; | ||
148 | |||
149 | x = memchr(base32_alphabet, ascii_toupper(i), sizeof base32_alphabet); | ||
150 | base32_map[i] = x ? (x - base32_alphabet) : (unsigned char) -1; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | for (i = 0; i < len && max_pad > 0; i++) { | ||
155 | unsigned char c; | ||
156 | char s[8]; | ||
157 | size_t j; | ||
158 | |||
159 | c = p[i]; | ||
160 | if ('=' == c) { | ||
161 | max_pad--; | ||
162 | c = 0; | ||
163 | } else { | ||
164 | c = base32_map[c]; | ||
165 | if ((unsigned char) -1 == c) { | ||
166 | return -1; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | j = i % ARRAY_LEN(s); | ||
171 | s[j] = c; | ||
172 | |||
173 | if (7 == j) { | ||
174 | char b[5]; | ||
175 | |||
176 | b[0] = ((s[0] << 3) & 0xf8) | ((s[1] >> 2) & 0x07); | ||
177 | b[1] = ((s[1] & 0x03) << 6) | ((s[2] & 0x1f) << 1) | ((s[3] >> 4) & 1); | ||
178 | b[2] = ((s[3] & 0x0f) << 4) | ((s[4] >> 1) & 0x0f); | ||
179 | b[3] = ((s[4] & 1) << 7) | ((s[5] & 0x1f) << 2) | ((s[6] >> 3) & 0x03); | ||
180 | b[4] = ((s[6] & 0x07) << 5) | (s[7] & 0x1f); | ||
181 | |||
182 | for (j = 0; j < ARRAY_LEN(b); j++) { | ||
183 | if (q != end) | ||
184 | *q = b[j]; | ||
185 | q++; | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | |||
190 | return q - dst; | ||
191 | } | ||
192 | */ | ||
193 | |||
194 | |||
195 | // static | ||
196 | std::string LLBase32::encode(const U8* input, size_t input_size) | ||
197 | { | ||
198 | std::string output; | ||
199 | if (input) | ||
200 | { | ||
201 | // Each 5 byte chunk of input is represented by an | ||
202 | // 8 byte chunk of output. | ||
203 | size_t input_chunks = (input_size + 4) / 5; | ||
204 | size_t output_size = input_chunks * 8; | ||
205 | |||
206 | output.resize(output_size); | ||
207 | |||
208 | size_t encoded = base32_encode(&output[0], output_size, input, input_size); | ||
209 | |||
210 | llinfos << "encoded " << encoded << " into buffer of size " << output_size | ||
211 | << llendl; | ||
212 | } | ||
213 | return output; | ||
214 | } | ||
diff --git a/linden/indra/llcommon/llbase32.h b/linden/indra/llcommon/llbase32.h new file mode 100644 index 0000000..eaf3efc --- /dev/null +++ b/linden/indra/llcommon/llbase32.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /** | ||
2 | * @file llbase32.h | ||
3 | * @brief base32 encoding that returns a std::string | ||
4 | * @author James Cook | ||
5 | * | ||
6 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #ifndef LLBASE32_H | ||
30 | #define LLBASE32_h | ||
31 | |||
32 | class LLBase32 | ||
33 | { | ||
34 | public: | ||
35 | static std::string encode(const U8* input, size_t input_size); | ||
36 | }; | ||
37 | |||
38 | #endif | ||
diff --git a/linden/indra/llcommon/llbase64.cpp b/linden/indra/llcommon/llbase64.cpp new file mode 100644 index 0000000..0869d3f --- /dev/null +++ b/linden/indra/llcommon/llbase64.cpp | |||
@@ -0,0 +1,62 @@ | |||
1 | /** | ||
2 | * @file llbase64.cpp | ||
3 | * @brief Wrapper for apr base64 encoding that returns a std::string | ||
4 | * @author James Cook | ||
5 | * | ||
6 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #include "llbase64.h" | ||
32 | |||
33 | #include <string> | ||
34 | |||
35 | #include "apr-1/apr_base64.h" | ||
36 | |||
37 | |||
38 | // static | ||
39 | std::string LLBase64::encode(const U8* input, size_t input_size) | ||
40 | { | ||
41 | std::string output; | ||
42 | if (input | ||
43 | && input_size > 0) | ||
44 | { | ||
45 | // Yes, it returns int. | ||
46 | int b64_buffer_length = apr_base64_encode_len(input_size); | ||
47 | char* b64_buffer = new char[b64_buffer_length]; | ||
48 | |||
49 | // This is faster than apr_base64_encode() if you know | ||
50 | // you're not on an EBCDIC machine. Also, the output is | ||
51 | // null terminated, even though the documentation doesn't | ||
52 | // specify. See apr_base64.c for details. JC | ||
53 | b64_buffer_length = apr_base64_encode_binary( | ||
54 | b64_buffer, | ||
55 | input, | ||
56 | input_size); | ||
57 | output.assign(b64_buffer); | ||
58 | delete[] b64_buffer; | ||
59 | } | ||
60 | return output; | ||
61 | } | ||
62 | |||
diff --git a/linden/indra/llcommon/llbase64.h b/linden/indra/llcommon/llbase64.h new file mode 100644 index 0000000..d8b4acc --- /dev/null +++ b/linden/indra/llcommon/llbase64.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /** | ||
2 | * @file llbase64.h | ||
3 | * @brief Wrapper for apr base64 encoding that returns a std::string | ||
4 | * @author James Cook | ||
5 | * | ||
6 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #ifndef LLBASE64_H | ||
30 | #define LLBASE64_h | ||
31 | |||
32 | class LLBase64 | ||
33 | { | ||
34 | public: | ||
35 | static std::string encode(const U8* input, size_t input_size); | ||
36 | }; | ||
37 | |||
38 | #endif | ||
diff --git a/linden/indra/llcommon/llcommon.cpp b/linden/indra/llcommon/llcommon.cpp index 50b9849..49675e1 100644 --- a/linden/indra/llcommon/llcommon.cpp +++ b/linden/indra/llcommon/llcommon.cpp | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "linden_common.h" | 27 | #include "linden_common.h" |
28 | 28 | ||
29 | #include "llcommon.h" | 29 | #include "llcommon.h" |
30 | #include "llthread.h" | ||
30 | 31 | ||
31 | //static | 32 | //static |
32 | BOOL LLCommon::sAprInitialized = FALSE; | 33 | BOOL LLCommon::sAprInitialized = FALSE; |
diff --git a/linden/indra/llcommon/llcommon.h b/linden/indra/llcommon/llcommon.h index 5d5264c..8b57579 100644 --- a/linden/indra/llcommon/llcommon.h +++ b/linden/indra/llcommon/llcommon.h | |||
@@ -31,7 +31,6 @@ | |||
31 | #include "llapr.h" | 31 | #include "llapr.h" |
32 | // #include "llframecallbackmanager.h" | 32 | // #include "llframecallbackmanager.h" |
33 | #include "lltimer.h" | 33 | #include "lltimer.h" |
34 | #include "llworkerthread.h" | ||
35 | #include "llfile.h" | 34 | #include "llfile.h" |
36 | 35 | ||
37 | class LLCommon | 36 | class LLCommon |
diff --git a/linden/indra/llcommon/llcommon.vcproj b/linden/indra/llcommon/llcommon.vcproj index 5cfbc64..403b8c5 100644 --- a/linden/indra/llcommon/llcommon.vcproj +++ b/linden/indra/llcommon/llcommon.vcproj | |||
@@ -167,22 +167,22 @@ | |||
167 | RelativePath=".\llassettype.cpp"> | 167 | RelativePath=".\llassettype.cpp"> |
168 | </File> | 168 | </File> |
169 | <File | 169 | <File |
170 | RelativePath=".\llcommon.cpp"> | 170 | RelativePath=".\llbase32.cpp"> |
171 | </File> | 171 | </File> |
172 | <File | 172 | <File |
173 | RelativePath=".\llcriticaldamp.cpp"> | 173 | RelativePath=".\llbase64.cpp"> |
174 | </File> | 174 | </File> |
175 | <File | 175 | <File |
176 | RelativePath=".\lldate.cpp"> | 176 | RelativePath=".\llcommon.cpp"> |
177 | </File> | 177 | </File> |
178 | <File | 178 | <File |
179 | RelativePath=".\llerror.cpp"> | 179 | RelativePath=".\llcriticaldamp.cpp"> |
180 | </File> | 180 | </File> |
181 | <File | 181 | <File |
182 | RelativePath=".\llerrorbuffer.cpp"> | 182 | RelativePath=".\lldate.cpp"> |
183 | </File> | 183 | </File> |
184 | <File | 184 | <File |
185 | RelativePath=".\llerrorstream.cpp"> | 185 | RelativePath=".\llerror.cpp"> |
186 | </File> | 186 | </File> |
187 | <File | 187 | <File |
188 | RelativePath=".\llerrorthread.cpp"> | 188 | RelativePath=".\llerrorthread.cpp"> |
@@ -200,9 +200,15 @@ | |||
200 | RelativePath=".\llfixedbuffer.cpp"> | 200 | RelativePath=".\llfixedbuffer.cpp"> |
201 | </File> | 201 | </File> |
202 | <File | 202 | <File |
203 | RelativePath=".\llformat.cpp"> | ||
204 | </File> | ||
205 | <File | ||
203 | RelativePath=".\llframetimer.cpp"> | 206 | RelativePath=".\llframetimer.cpp"> |
204 | </File> | 207 | </File> |
205 | <File | 208 | <File |
209 | RelativePath=".\llliveappconfig.cpp"> | ||
210 | </File> | ||
211 | <File | ||
206 | RelativePath=".\lllivefile.cpp"> | 212 | RelativePath=".\lllivefile.cpp"> |
207 | </File> | 213 | </File> |
208 | <File | 214 | <File |
@@ -322,6 +328,12 @@ | |||
322 | RelativePath=".\llavatarconstants.h"> | 328 | RelativePath=".\llavatarconstants.h"> |
323 | </File> | 329 | </File> |
324 | <File | 330 | <File |
331 | RelativePath=".\llbase32.h"> | ||
332 | </File> | ||
333 | <File | ||
334 | RelativePath=".\llbase64.h"> | ||
335 | </File> | ||
336 | <File | ||
325 | RelativePath=".\llboost.h"> | 337 | RelativePath=".\llboost.h"> |
326 | </File> | 338 | </File> |
327 | <File | 339 | <File |
@@ -364,10 +376,7 @@ | |||
364 | RelativePath=".\llerror.h"> | 376 | RelativePath=".\llerror.h"> |
365 | </File> | 377 | </File> |
366 | <File | 378 | <File |
367 | RelativePath=".\llerrorbuffer.h"> | 379 | RelativePath=".\llerrorcontrol.h"> |
368 | </File> | ||
369 | <File | ||
370 | RelativePath=".\llerrorstream.h"> | ||
371 | </File> | 380 | </File> |
372 | <File | 381 | <File |
373 | RelativePath=".\llerrorthread.h"> | 382 | RelativePath=".\llerrorthread.h"> |
@@ -385,6 +394,9 @@ | |||
385 | RelativePath=".\llfixedbuffer.h"> | 394 | RelativePath=".\llfixedbuffer.h"> |
386 | </File> | 395 | </File> |
387 | <File | 396 | <File |
397 | RelativePath=".\llformat.h"> | ||
398 | </File> | ||
399 | <File | ||
388 | RelativePath=".\llframecallbackmanager.h"> | 400 | RelativePath=".\llframecallbackmanager.h"> |
389 | </File> | 401 | </File> |
390 | <File | 402 | <File |
@@ -400,6 +412,9 @@ | |||
400 | RelativePath=".\lllinkedqueue.h"> | 412 | RelativePath=".\lllinkedqueue.h"> |
401 | </File> | 413 | </File> |
402 | <File | 414 | <File |
415 | RelativePath=".\llliveappconfig.h"> | ||
416 | </File> | ||
417 | <File | ||
403 | RelativePath=".\lllivefile.h"> | 418 | RelativePath=".\lllivefile.h"> |
404 | </File> | 419 | </File> |
405 | <File | 420 | <File |
@@ -418,6 +433,9 @@ | |||
418 | RelativePath=".\llmemorystream.h"> | 433 | RelativePath=".\llmemorystream.h"> |
419 | </File> | 434 | </File> |
420 | <File | 435 | <File |
436 | RelativePath=".\llmemtype.h"> | ||
437 | </File> | ||
438 | <File | ||
421 | RelativePath=".\llmortician.h"> | 439 | RelativePath=".\llmortician.h"> |
422 | </File> | 440 | </File> |
423 | <File | 441 | <File |
diff --git a/linden/indra/llcommon/llcommon_vc8.vcproj b/linden/indra/llcommon/llcommon_vc8.vcproj new file mode 100644 index 0000000..4fee443 --- /dev/null +++ b/linden/indra/llcommon/llcommon_vc8.vcproj | |||
@@ -0,0 +1,759 @@ | |||
1 | <?xml version="1.0" encoding="Windows-1252"?> | ||
2 | <VisualStudioProject | ||
3 | ProjectType="Visual C++" | ||
4 | Version="8.00" | ||
5 | Name="llcommon" | ||
6 | ProjectGUID="{7BCB4B2C-8378-4186-88EA-5742B5ABE17F}" | ||
7 | RootNamespace="llcommon" | ||
8 | Keyword="Win32Proj" | ||
9 | > | ||
10 | <Platforms> | ||
11 | <Platform | ||
12 | Name="Win32" | ||
13 | /> | ||
14 | </Platforms> | ||
15 | <ToolFiles> | ||
16 | </ToolFiles> | ||
17 | <Configurations> | ||
18 | <Configuration | ||
19 | Name="Debug|Win32" | ||
20 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | ||
21 | IntermediateDirectory="$(ConfigurationName)" | ||
22 | ConfigurationType="4" | ||
23 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | ||
24 | CharacterSet="1" | ||
25 | > | ||
26 | <Tool | ||
27 | Name="VCPreBuildEventTool" | ||
28 | /> | ||
29 | <Tool | ||
30 | Name="VCCustomBuildTool" | ||
31 | /> | ||
32 | <Tool | ||
33 | Name="VCXMLDataGeneratorTool" | ||
34 | /> | ||
35 | <Tool | ||
36 | Name="VCWebServiceProxyGeneratorTool" | ||
37 | /> | ||
38 | <Tool | ||
39 | Name="VCMIDLTool" | ||
40 | /> | ||
41 | <Tool | ||
42 | Name="VCCLCompilerTool" | ||
43 | Optimization="0" | ||
44 | AdditionalIncludeDirectories="..\..\libraries\i686-win32\include;..\..\libraries\include\" | ||
45 | PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_DEBUG;XML_STATIC;APR_DECLARE_STATIC" | ||
46 | MinimalRebuild="true" | ||
47 | BasicRuntimeChecks="3" | ||
48 | RuntimeLibrary="1" | ||
49 | StructMemberAlignment="4" | ||
50 | TreatWChar_tAsBuiltInType="false" | ||
51 | ForceConformanceInForLoopScope="true" | ||
52 | UsePrecompiledHeader="0" | ||
53 | WarningLevel="3" | ||
54 | WarnAsError="true" | ||
55 | Detect64BitPortabilityProblems="false" | ||
56 | DebugInformationFormat="4" | ||
57 | /> | ||
58 | <Tool | ||
59 | Name="VCManagedResourceCompilerTool" | ||
60 | /> | ||
61 | <Tool | ||
62 | Name="VCResourceCompilerTool" | ||
63 | /> | ||
64 | <Tool | ||
65 | Name="VCPreLinkEventTool" | ||
66 | /> | ||
67 | <Tool | ||
68 | Name="VCLibrarianTool" | ||
69 | OutputFile="$(OutDir)/llcommon.lib" | ||
70 | /> | ||
71 | <Tool | ||
72 | Name="VCALinkTool" | ||
73 | /> | ||
74 | <Tool | ||
75 | Name="VCXDCMakeTool" | ||
76 | /> | ||
77 | <Tool | ||
78 | Name="VCBscMakeTool" | ||
79 | /> | ||
80 | <Tool | ||
81 | Name="VCFxCopTool" | ||
82 | /> | ||
83 | <Tool | ||
84 | Name="VCPostBuildEventTool" | ||
85 | /> | ||
86 | </Configuration> | ||
87 | <Configuration | ||
88 | Name="Release|Win32" | ||
89 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | ||
90 | IntermediateDirectory="$(ConfigurationName)" | ||
91 | ConfigurationType="4" | ||
92 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | ||
93 | CharacterSet="1" | ||
94 | > | ||
95 | <Tool | ||
96 | Name="VCPreBuildEventTool" | ||
97 | /> | ||
98 | <Tool | ||
99 | Name="VCCustomBuildTool" | ||
100 | /> | ||
101 | <Tool | ||
102 | Name="VCXMLDataGeneratorTool" | ||
103 | /> | ||
104 | <Tool | ||
105 | Name="VCWebServiceProxyGeneratorTool" | ||
106 | /> | ||
107 | <Tool | ||
108 | Name="VCMIDLTool" | ||
109 | /> | ||
110 | <Tool | ||
111 | Name="VCCLCompilerTool" | ||
112 | InlineFunctionExpansion="2" | ||
113 | EnableIntrinsicFunctions="true" | ||
114 | AdditionalIncludeDirectories="..\..\libraries\i686-win32\include;..\..\libraries\include\" | ||
115 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE;XML_STATIC;APR_DECLARE_STATIC" | ||
116 | RuntimeLibrary="0" | ||
117 | StructMemberAlignment="0" | ||
118 | TreatWChar_tAsBuiltInType="false" | ||
119 | ForceConformanceInForLoopScope="true" | ||
120 | UsePrecompiledHeader="0" | ||
121 | WarningLevel="3" | ||
122 | WarnAsError="true" | ||
123 | Detect64BitPortabilityProblems="false" | ||
124 | DebugInformationFormat="3" | ||
125 | /> | ||
126 | <Tool | ||
127 | Name="VCManagedResourceCompilerTool" | ||
128 | /> | ||
129 | <Tool | ||
130 | Name="VCResourceCompilerTool" | ||
131 | /> | ||
132 | <Tool | ||
133 | Name="VCPreLinkEventTool" | ||
134 | /> | ||
135 | <Tool | ||
136 | Name="VCLibrarianTool" | ||
137 | OutputFile="$(OutDir)/llcommon.lib" | ||
138 | /> | ||
139 | <Tool | ||
140 | Name="VCALinkTool" | ||
141 | /> | ||
142 | <Tool | ||
143 | Name="VCXDCMakeTool" | ||
144 | /> | ||
145 | <Tool | ||
146 | Name="VCBscMakeTool" | ||
147 | /> | ||
148 | <Tool | ||
149 | Name="VCFxCopTool" | ||
150 | /> | ||
151 | <Tool | ||
152 | Name="VCPostBuildEventTool" | ||
153 | /> | ||
154 | </Configuration> | ||
155 | <Configuration | ||
156 | Name="ReleaseNoOpt|Win32" | ||
157 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | ||
158 | IntermediateDirectory="$(ConfigurationName)" | ||
159 | ConfigurationType="4" | ||
160 | InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | ||
161 | CharacterSet="1" | ||
162 | > | ||
163 | <Tool | ||
164 | Name="VCPreBuildEventTool" | ||
165 | /> | ||
166 | <Tool | ||
167 | Name="VCCustomBuildTool" | ||
168 | /> | ||
169 | <Tool | ||
170 | Name="VCXMLDataGeneratorTool" | ||
171 | /> | ||
172 | <Tool | ||
173 | Name="VCWebServiceProxyGeneratorTool" | ||
174 | /> | ||
175 | <Tool | ||
176 | Name="VCMIDLTool" | ||
177 | /> | ||
178 | <Tool | ||
179 | Name="VCCLCompilerTool" | ||
180 | Optimization="0" | ||
181 | AdditionalIncludeDirectories="..\..\libraries\i686-win32\include;..\..\libraries\include\" | ||
182 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE;XML_STATIC;APR_DECLARE_STATIC" | ||
183 | RuntimeLibrary="0" | ||
184 | StructMemberAlignment="0" | ||
185 | TreatWChar_tAsBuiltInType="false" | ||
186 | ForceConformanceInForLoopScope="true" | ||
187 | UsePrecompiledHeader="0" | ||
188 | WarningLevel="3" | ||
189 | WarnAsError="true" | ||
190 | Detect64BitPortabilityProblems="false" | ||
191 | DebugInformationFormat="3" | ||
192 | /> | ||
193 | <Tool | ||
194 | Name="VCManagedResourceCompilerTool" | ||
195 | /> | ||
196 | <Tool | ||
197 | Name="VCResourceCompilerTool" | ||
198 | /> | ||
199 | <Tool | ||
200 | Name="VCPreLinkEventTool" | ||
201 | /> | ||
202 | <Tool | ||
203 | Name="VCLibrarianTool" | ||
204 | OutputFile="$(OutDir)/llcommon.lib" | ||
205 | /> | ||
206 | <Tool | ||
207 | Name="VCALinkTool" | ||
208 | /> | ||
209 | <Tool | ||
210 | Name="VCXDCMakeTool" | ||
211 | /> | ||
212 | <Tool | ||
213 | Name="VCBscMakeTool" | ||
214 | /> | ||
215 | <Tool | ||
216 | Name="VCFxCopTool" | ||
217 | /> | ||
218 | <Tool | ||
219 | Name="VCPostBuildEventTool" | ||
220 | /> | ||
221 | </Configuration> | ||
222 | </Configurations> | ||
223 | <References> | ||
224 | </References> | ||
225 | <Files> | ||
226 | <Filter | ||
227 | Name="Source Files" | ||
228 | Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" | ||
229 | UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" | ||
230 | > | ||
231 | <File | ||
232 | RelativePath=".\bitpack.cpp" | ||
233 | > | ||
234 | </File> | ||
235 | <File | ||
236 | RelativePath=".\llapp.cpp" | ||
237 | > | ||
238 | </File> | ||
239 | <File | ||
240 | RelativePath=".\llapr.cpp" | ||
241 | > | ||
242 | </File> | ||
243 | <File | ||
244 | RelativePath=".\llassettype.cpp" | ||
245 | > | ||
246 | </File> | ||
247 | <File | ||
248 | RelativePath=".\llbase64.cpp" | ||
249 | > | ||
250 | </File> | ||
251 | <File | ||
252 | RelativePath=".\llcommon.cpp" | ||
253 | > | ||
254 | </File> | ||
255 | <File | ||
256 | RelativePath=".\llcriticaldamp.cpp" | ||
257 | > | ||
258 | </File> | ||
259 | <File | ||
260 | RelativePath=".\lldate.cpp" | ||
261 | > | ||
262 | </File> | ||
263 | <File | ||
264 | RelativePath=".\llerror.cpp" | ||
265 | > | ||
266 | </File> | ||
267 | <File | ||
268 | RelativePath=".\llerrorthread.cpp" | ||
269 | > | ||
270 | </File> | ||
271 | <File | ||
272 | RelativePath=".\llevent.cpp" | ||
273 | > | ||
274 | </File> | ||
275 | <File | ||
276 | RelativePath=".\llfasttimer.cpp" | ||
277 | > | ||
278 | </File> | ||
279 | <File | ||
280 | RelativePath=".\llfile.cpp" | ||
281 | > | ||
282 | </File> | ||
283 | <File | ||
284 | RelativePath=".\llfixedbuffer.cpp" | ||
285 | > | ||
286 | </File> | ||
287 | <File | ||
288 | RelativePath=".\llformat.cpp" | ||
289 | > | ||
290 | </File> | ||
291 | <File | ||
292 | RelativePath=".\llframetimer.cpp" | ||
293 | > | ||
294 | </File> | ||
295 | <File | ||
296 | RelativePath=".\lllivefile.cpp" | ||
297 | > | ||
298 | </File> | ||
299 | <File | ||
300 | RelativePath=".\llmemory.cpp" | ||
301 | > | ||
302 | </File> | ||
303 | <File | ||
304 | RelativePath=".\llmemorystream.cpp" | ||
305 | > | ||
306 | </File> | ||
307 | <File | ||
308 | RelativePath=".\llmortician.cpp" | ||
309 | > | ||
310 | </File> | ||
311 | <File | ||
312 | RelativePath=".\llprocessor.cpp" | ||
313 | > | ||
314 | </File> | ||
315 | <File | ||
316 | RelativePath=".\llqueuedthread.cpp" | ||
317 | > | ||
318 | </File> | ||
319 | <File | ||
320 | RelativePath=".\llrun.cpp" | ||
321 | > | ||
322 | </File> | ||
323 | <File | ||
324 | RelativePath=".\llsd.cpp" | ||
325 | > | ||
326 | </File> | ||
327 | <File | ||
328 | RelativePath=".\llsdserialize.cpp" | ||
329 | > | ||
330 | </File> | ||
331 | <File | ||
332 | RelativePath=".\llsdserialize_xml.cpp" | ||
333 | > | ||
334 | </File> | ||
335 | <File | ||
336 | RelativePath=".\llsdutil.cpp" | ||
337 | > | ||
338 | </File> | ||
339 | <File | ||
340 | RelativePath=".\llsecondlifeurls.cpp" | ||
341 | > | ||
342 | </File> | ||
343 | <File | ||
344 | RelativePath=".\llstat.cpp" | ||
345 | > | ||
346 | </File> | ||
347 | <File | ||
348 | RelativePath=".\llstreamtools.cpp" | ||
349 | > | ||
350 | </File> | ||
351 | <File | ||
352 | RelativePath=".\llstring.cpp" | ||
353 | > | ||
354 | </File> | ||
355 | <File | ||
356 | RelativePath=".\llstringtable.cpp" | ||
357 | > | ||
358 | </File> | ||
359 | <File | ||
360 | RelativePath=".\llsys.cpp" | ||
361 | > | ||
362 | </File> | ||
363 | <File | ||
364 | RelativePath=".\llthread.cpp" | ||
365 | > | ||
366 | </File> | ||
367 | <File | ||
368 | RelativePath=".\lltimer.cpp" | ||
369 | > | ||
370 | </File> | ||
371 | <File | ||
372 | RelativePath=".\lluri.cpp" | ||
373 | > | ||
374 | </File> | ||
375 | <File | ||
376 | RelativePath=".\llworkerthread.cpp" | ||
377 | > | ||
378 | </File> | ||
379 | <File | ||
380 | RelativePath=".\metaclass.cpp" | ||
381 | > | ||
382 | </File> | ||
383 | <File | ||
384 | RelativePath=".\metaproperty.cpp" | ||
385 | > | ||
386 | </File> | ||
387 | <File | ||
388 | RelativePath=".\reflective.cpp" | ||
389 | > | ||
390 | </File> | ||
391 | <File | ||
392 | RelativePath=".\timing.cpp" | ||
393 | > | ||
394 | </File> | ||
395 | <File | ||
396 | RelativePath=".\u64.cpp" | ||
397 | > | ||
398 | </File> | ||
399 | </Filter> | ||
400 | <Filter | ||
401 | Name="Header Files" | ||
402 | Filter="h;hpp;hxx;hm;inl;inc;xsd" | ||
403 | UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" | ||
404 | > | ||
405 | <File | ||
406 | RelativePath=".\bitpack.h" | ||
407 | > | ||
408 | </File> | ||
409 | <File | ||
410 | RelativePath=".\doublelinkedlist.h" | ||
411 | > | ||
412 | </File> | ||
413 | <File | ||
414 | RelativePath=".\imageids.h" | ||
415 | > | ||
416 | </File> | ||
417 | <File | ||
418 | RelativePath=".\indra_constants.h" | ||
419 | > | ||
420 | </File> | ||
421 | <File | ||
422 | RelativePath=".\linden_common.h" | ||
423 | > | ||
424 | </File> | ||
425 | <File | ||
426 | RelativePath=".\linked_lists.h" | ||
427 | > | ||
428 | </File> | ||
429 | <File | ||
430 | RelativePath=".\llagentconstants.h" | ||
431 | > | ||
432 | </File> | ||
433 | <File | ||
434 | RelativePath=".\llapp.h" | ||
435 | > | ||
436 | </File> | ||
437 | <File | ||
438 | RelativePath=".\llapr.h" | ||
439 | > | ||
440 | </File> | ||
441 | <File | ||
442 | RelativePath=".\llassettype.h" | ||
443 | > | ||
444 | </File> | ||
445 | <File | ||
446 | RelativePath=".\llassoclist.h" | ||
447 | > | ||
448 | </File> | ||
449 | <File | ||
450 | RelativePath=".\llavatarconstants.h" | ||
451 | > | ||
452 | </File> | ||
453 | <File | ||
454 | RelativePath=".\llbase64.h" | ||
455 | > | ||
456 | </File> | ||
457 | <File | ||
458 | RelativePath=".\llboost.h" | ||
459 | > | ||
460 | </File> | ||
461 | <File | ||
462 | RelativePath=".\llchat.h" | ||
463 | > | ||
464 | </File> | ||
465 | <File | ||
466 | RelativePath=".\llclickaction.h" | ||
467 | > | ||
468 | </File> | ||
469 | <File | ||
470 | RelativePath=".\llcommon.h" | ||
471 | > | ||
472 | </File> | ||
473 | <File | ||
474 | RelativePath=".\llcriticaldamp.h" | ||
475 | > | ||
476 | </File> | ||
477 | <File | ||
478 | RelativePath=".\lldarray.h" | ||
479 | > | ||
480 | </File> | ||
481 | <File | ||
482 | RelativePath=".\lldarrayptr.h" | ||
483 | > | ||
484 | </File> | ||
485 | <File | ||
486 | RelativePath=".\lldate.h" | ||
487 | > | ||
488 | </File> | ||
489 | <File | ||
490 | RelativePath=".\lldefs.h" | ||
491 | > | ||
492 | </File> | ||
493 | <File | ||
494 | RelativePath=".\lldlinked.h" | ||
495 | > | ||
496 | </File> | ||
497 | <File | ||
498 | RelativePath=".\lldqueueptr.h" | ||
499 | > | ||
500 | </File> | ||
501 | <File | ||
502 | RelativePath=".\llendianswizzle.h" | ||
503 | > | ||
504 | </File> | ||
505 | <File | ||
506 | RelativePath=".\llenum.h" | ||
507 | > | ||
508 | </File> | ||
509 | <File | ||
510 | RelativePath=".\llerror.h" | ||
511 | > | ||
512 | </File> | ||
513 | <File | ||
514 | RelativePath=".\llerrorcontrol.h" | ||
515 | > | ||
516 | </File> | ||
517 | <File | ||
518 | RelativePath=".\llerrorthread.h" | ||
519 | > | ||
520 | </File> | ||
521 | <File | ||
522 | RelativePath=".\llevent.h" | ||
523 | > | ||
524 | </File> | ||
525 | <File | ||
526 | RelativePath=".\llfasttimer.h" | ||
527 | > | ||
528 | </File> | ||
529 | <File | ||
530 | RelativePath=".\llfile.h" | ||
531 | > | ||
532 | </File> | ||
533 | <File | ||
534 | RelativePath=".\llfixedbuffer.h" | ||
535 | > | ||
536 | </File> | ||
537 | <File | ||
538 | RelativePath=".\llformat.h" | ||
539 | > | ||
540 | </File> | ||
541 | <File | ||
542 | RelativePath=".\llframecallbackmanager.h" | ||
543 | > | ||
544 | </File> | ||
545 | <File | ||
546 | RelativePath=".\llframetimer.h" | ||
547 | > | ||
548 | </File> | ||
549 | <File | ||
550 | RelativePath=".\llhash.h" | ||
551 | > | ||
552 | </File> | ||
553 | <File | ||
554 | RelativePath=".\llindexedqueue.h" | ||
555 | > | ||
556 | </File> | ||
557 | <File | ||
558 | RelativePath=".\lllinkedqueue.h" | ||
559 | > | ||
560 | </File> | ||
561 | <File | ||
562 | RelativePath=".\lllivefile.h" | ||
563 | > | ||
564 | </File> | ||
565 | <File | ||
566 | RelativePath=".\lllocalidhashmap.h" | ||
567 | > | ||
568 | </File> | ||
569 | <File | ||
570 | RelativePath=".\lllslconstants.h" | ||
571 | > | ||
572 | </File> | ||
573 | <File | ||
574 | RelativePath=".\llmap.h" | ||
575 | > | ||
576 | </File> | ||
577 | <File | ||
578 | RelativePath=".\llmemory.h" | ||
579 | > | ||
580 | </File> | ||
581 | <File | ||
582 | RelativePath=".\llmemorystream.h" | ||
583 | > | ||
584 | </File> | ||
585 | <File | ||
586 | RelativePath=".\llmortician.h" | ||
587 | > | ||
588 | </File> | ||
589 | <File | ||
590 | RelativePath=".\llnametable.h" | ||
591 | > | ||
592 | </File> | ||
593 | <File | ||
594 | RelativePath=".\llpagemem.h" | ||
595 | > | ||
596 | </File> | ||
597 | <File | ||
598 | RelativePath=".\llpreprocessor.h" | ||
599 | > | ||
600 | </File> | ||
601 | <File | ||
602 | RelativePath=".\llpriqueuemap.h" | ||
603 | > | ||
604 | </File> | ||
605 | <File | ||
606 | RelativePath=".\llprocessor.h" | ||
607 | > | ||
608 | </File> | ||
609 | <File | ||
610 | RelativePath=".\llptrskiplist.h" | ||
611 | > | ||
612 | </File> | ||
613 | <File | ||
614 | RelativePath=".\llptrskipmap.h" | ||
615 | > | ||
616 | </File> | ||
617 | <File | ||
618 | RelativePath=".\llqueuedthread.h" | ||
619 | > | ||
620 | </File> | ||
621 | <File | ||
622 | RelativePath=".\llrun.h" | ||
623 | > | ||
624 | </File> | ||
625 | <File | ||
626 | RelativePath=".\llsd.h" | ||
627 | > | ||
628 | </File> | ||
629 | <File | ||
630 | RelativePath=".\llsdserialize.h" | ||
631 | > | ||
632 | </File> | ||
633 | <File | ||
634 | RelativePath=".\llsdserialize_xml.h" | ||
635 | > | ||
636 | </File> | ||
637 | <File | ||
638 | RelativePath=".\llsdutil.h" | ||
639 | > | ||
640 | </File> | ||
641 | <File | ||
642 | RelativePath=".\llsecondlifeurls.h" | ||
643 | > | ||
644 | </File> | ||
645 | <File | ||
646 | RelativePath=".\llskiplist.h" | ||
647 | > | ||
648 | </File> | ||
649 | <File | ||
650 | RelativePath=".\llskipmap.h" | ||
651 | > | ||
652 | </File> | ||
653 | <File | ||
654 | RelativePath=".\llstat.h" | ||
655 | > | ||
656 | </File> | ||
657 | <File | ||
658 | RelativePath=".\llstatenums.h" | ||
659 | > | ||
660 | </File> | ||
661 | <File | ||
662 | RelativePath=".\llstl.h" | ||
663 | > | ||
664 | </File> | ||
665 | <File | ||
666 | RelativePath=".\llstreamtools.h" | ||
667 | > | ||
668 | </File> | ||
669 | <File | ||
670 | RelativePath=".\llstrider.h" | ||
671 | > | ||
672 | </File> | ||
673 | <File | ||
674 | RelativePath=".\llstring.h" | ||
675 | > | ||
676 | </File> | ||
677 | <File | ||
678 | RelativePath=".\llstringtable.h" | ||
679 | > | ||
680 | </File> | ||
681 | <File | ||
682 | RelativePath=".\llsys.h" | ||
683 | > | ||
684 | </File> | ||
685 | <File | ||
686 | RelativePath=".\llthread.h" | ||
687 | > | ||
688 | </File> | ||
689 | <File | ||
690 | RelativePath=".\lltimer.h" | ||
691 | > | ||
692 | </File> | ||
693 | <File | ||
694 | RelativePath=".\lluri.h" | ||
695 | > | ||
696 | </File> | ||
697 | <File | ||
698 | RelativePath=".\lluuidhashmap.h" | ||
699 | > | ||
700 | </File> | ||
701 | <File | ||
702 | RelativePath=".\llversion.h" | ||
703 | > | ||
704 | </File> | ||
705 | <File | ||
706 | RelativePath=".\llworkerthread.h" | ||
707 | > | ||
708 | </File> | ||
709 | <File | ||
710 | RelativePath=".\new_mem_ops.h" | ||
711 | > | ||
712 | </File> | ||
713 | <File | ||
714 | RelativePath=".\priqueue.h" | ||
715 | > | ||
716 | </File> | ||
717 | <File | ||
718 | RelativePath=".\processor.h" | ||
719 | > | ||
720 | </File> | ||
721 | <File | ||
722 | RelativePath=".\roles_constants.h" | ||
723 | > | ||
724 | </File> | ||
725 | <File | ||
726 | RelativePath=".\stdenums.h" | ||
727 | > | ||
728 | </File> | ||
729 | <File | ||
730 | RelativePath=".\stdtypes.h" | ||
731 | > | ||
732 | </File> | ||
733 | <File | ||
734 | RelativePath=".\string_table.h" | ||
735 | > | ||
736 | </File> | ||
737 | <File | ||
738 | RelativePath=".\timer.h" | ||
739 | > | ||
740 | </File> | ||
741 | <File | ||
742 | RelativePath=".\timing.h" | ||
743 | > | ||
744 | </File> | ||
745 | <File | ||
746 | RelativePath=".\u64.h" | ||
747 | > | ||
748 | </File> | ||
749 | </Filter> | ||
750 | <Filter | ||
751 | Name="Resource Files" | ||
752 | Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" | ||
753 | UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" | ||
754 | > | ||
755 | </Filter> | ||
756 | </Files> | ||
757 | <Globals> | ||
758 | </Globals> | ||
759 | </VisualStudioProject> | ||
diff --git a/linden/indra/llcommon/llerror.cpp b/linden/indra/llcommon/llerror.cpp index 29f4500..57e098e 100644 --- a/linden/indra/llcommon/llerror.cpp +++ b/linden/indra/llcommon/llerror.cpp | |||
@@ -1,8 +1,9 @@ | |||
1 | /** | 1 | /** |
2 | * @file llerror.cpp | 2 | * @file llerror.cpp |
3 | * @brief Function to crash. | 3 | * @date December 2006 |
4 | * @brief error message system | ||
4 | * | 5 | * |
5 | * Copyright (c) 2001-2007, Linden Research, Inc. | 6 | * Copyright (c) 2006-2007, Linden Research, Inc. |
6 | * | 7 | * |
7 | * The source code in this file ("Source Code") is provided by Linden Lab | 8 | * 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 | * to you under the terms of the GNU General Public License, version 2.0 |
@@ -24,36 +25,1048 @@ | |||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | 25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, |
25 | * COMPLETENESS OR PERFORMANCE. | 26 | * COMPLETENESS OR PERFORMANCE. |
26 | */ | 27 | */ |
28 | |||
27 | #include "linden_common.h" | 29 | #include "linden_common.h" |
28 | 30 | ||
29 | #include "llerror.h" | 31 | #include "llerror.h" |
32 | #include "llerrorcontrol.h" | ||
33 | |||
34 | #include "llapp.h" | ||
35 | #include "llapr.h" | ||
36 | extern apr_thread_mutex_t *gLogMutexp; | ||
37 | #include "llfile.h" | ||
38 | #include "llfixedbuffer.h" | ||
39 | #include "lllivefile.h" | ||
40 | #include "llsd.h" | ||
41 | #include "llsdserialize.h" | ||
42 | |||
43 | #include <algorithm> | ||
44 | #include <cctype> | ||
45 | #include <map> | ||
46 | #include <sstream> | ||
47 | #if !LL_WINDOWS | ||
48 | #include <stdio.h> | ||
49 | #include <syslog.h> | ||
50 | #endif | ||
51 | #include <time.h> | ||
52 | #if LL_WINDOWS | ||
53 | #include <windows.h> | ||
54 | #endif | ||
55 | #include <vector> | ||
56 | |||
57 | |||
58 | #ifdef __GNUC__ | ||
59 | #include <cxxabi.h> | ||
60 | #endif | ||
61 | |||
62 | namespace { | ||
63 | #if !LL_WINDOWS | ||
64 | class RecordToSyslog : public LLError::Recorder | ||
65 | { | ||
66 | public: | ||
67 | RecordToSyslog(const std::string& identity) | ||
68 | : mIdentity(identity) | ||
69 | { | ||
70 | openlog(mIdentity.c_str(), LOG_CONS|LOG_PID, LOG_LOCAL0); | ||
71 | // we need to set the string from a local copy of the string | ||
72 | // since apparanetly openlog expects the const char* to remain | ||
73 | // valid even after it returns (presumably until closelog) | ||
74 | } | ||
75 | |||
76 | ~RecordToSyslog() | ||
77 | { | ||
78 | closelog(); | ||
79 | } | ||
80 | |||
81 | virtual void recordMessage(LLError::ELevel level, | ||
82 | const std::string& message) | ||
83 | { | ||
84 | int syslogPriority = LOG_CRIT; | ||
85 | switch (level) { | ||
86 | case LLError::LEVEL_DEBUG: syslogPriority = LOG_DEBUG; break; | ||
87 | case LLError::LEVEL_INFO: syslogPriority = LOG_INFO; break; | ||
88 | case LLError::LEVEL_WARN: syslogPriority = LOG_WARNING; break; | ||
89 | case LLError::LEVEL_ERROR: syslogPriority = LOG_CRIT; break; | ||
90 | default: syslogPriority = LOG_CRIT; | ||
91 | } | ||
92 | |||
93 | syslog(syslogPriority, "%s", message.c_str()); | ||
94 | } | ||
95 | private: | ||
96 | std::string mIdentity; | ||
97 | }; | ||
98 | #endif | ||
99 | |||
100 | class RecordToFile : public LLError::Recorder | ||
101 | { | ||
102 | public: | ||
103 | RecordToFile(const std::string& filename) | ||
104 | { | ||
105 | mFile.open(filename.c_str(), llofstream::out | llofstream::app); | ||
106 | if (!mFile) | ||
107 | { | ||
108 | llinfos << "Error setting log file to " << filename << llendl; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | ~RecordToFile() | ||
113 | { | ||
114 | mFile.close(); | ||
115 | } | ||
116 | |||
117 | bool okay() { return mFile; } | ||
118 | |||
119 | virtual bool wantsTime() { return true; } | ||
120 | |||
121 | virtual void recordMessage(LLError::ELevel level, | ||
122 | const std::string& message) | ||
123 | { | ||
124 | mFile << message << std::endl; | ||
125 | // mFile.flush(); | ||
126 | // *FIX: should we do this? | ||
127 | } | ||
128 | |||
129 | private: | ||
130 | llofstream mFile; | ||
131 | }; | ||
132 | |||
133 | |||
134 | class RecordToStderr : public LLError::Recorder | ||
135 | { | ||
136 | public: | ||
137 | RecordToStderr(bool timestamp) : mTimestamp(timestamp) { } | ||
30 | 138 | ||
31 | LLErrorBuffer gErrorBuffer; | 139 | virtual bool wantsTime() { return mTimestamp; } |
32 | LLErrorStream gErrorStream(&gErrorBuffer); | 140 | |
141 | virtual void recordMessage(LLError::ELevel level, | ||
142 | const std::string& message) | ||
143 | { | ||
144 | fprintf(stderr, "%s\n", message.c_str()); | ||
145 | } | ||
146 | |||
147 | private: | ||
148 | bool mTimestamp; | ||
149 | }; | ||
33 | 150 | ||
151 | class RecordToFixedBuffer : public LLError::Recorder | ||
152 | { | ||
153 | public: | ||
154 | RecordToFixedBuffer(LLFixedBuffer& buffer) : mBuffer(buffer) { } | ||
155 | |||
156 | virtual void recordMessage(LLError::ELevel level, | ||
157 | const std::string& message) | ||
158 | { | ||
159 | mBuffer.addLine(message.c_str()); | ||
160 | } | ||
161 | |||
162 | private: | ||
163 | LLFixedBuffer& mBuffer; | ||
164 | }; | ||
34 | 165 | ||
35 | void _llcrash_and_loop() | 166 | #if LL_WINDOWS |
167 | class RecordToWinDebug: public LLError::Recorder | ||
168 | { | ||
169 | public: | ||
170 | virtual void recordMessage(LLError::ELevel level, | ||
171 | const std::string& message) | ||
172 | { | ||
173 | llutf16string utf16str = | ||
174 | wstring_to_utf16str(utf8str_to_wstring(message)); | ||
175 | utf16str += '\n'; | ||
176 | OutputDebugString(utf16str.c_str()); | ||
177 | } | ||
178 | }; | ||
179 | #endif | ||
180 | } | ||
181 | |||
182 | |||
183 | namespace | ||
36 | { | 184 | { |
37 | // Now, we go kaboom! | 185 | std::string className(const std::type_info& type) |
38 | U32* crash = NULL; | 186 | { |
187 | #ifdef __GNUC__ | ||
188 | // GCC: type_info::name() returns a mangled class name, must demangle | ||
189 | |||
190 | static size_t abi_name_len = 100; | ||
191 | static char* abi_name_buf = (char*)malloc(abi_name_len); | ||
192 | // warning: above is voodoo inferred from the GCC manual, | ||
193 | // do NOT change | ||
194 | |||
195 | int status; | ||
196 | // We don't use status, and shouldn't have to pass apointer to it | ||
197 | // but gcc 3.3 libstc++'s implementation of demangling is broken | ||
198 | // and fails without. | ||
199 | |||
200 | char* name = abi::__cxa_demangle(type.name(), | ||
201 | abi_name_buf, &abi_name_len, &status); | ||
202 | // this call can realloc the abi_name_buf pointer (!) | ||
203 | |||
204 | return name ? name : type.name(); | ||
39 | 205 | ||
40 | *crash = 0; | 206 | #elif LL_WINDOWS |
207 | // DevStudio: type_info::name() includes the text "class " at the start | ||
41 | 208 | ||
42 | while(TRUE) | 209 | static const std::string class_prefix = "class "; |
210 | |||
211 | std::string name = type.name(); | ||
212 | std::string::size_type p = name.find(class_prefix); | ||
213 | if (p == std::string::npos) | ||
214 | { | ||
215 | return name; | ||
216 | } | ||
217 | |||
218 | return name.substr(p + class_prefix.size()); | ||
219 | |||
220 | #else | ||
221 | return type.name(); | ||
222 | #endif | ||
223 | } | ||
224 | |||
225 | std::string functionName(const std::string& preprocessor_name) | ||
43 | { | 226 | { |
227 | #if LL_WINDOWS | ||
228 | // DevStudio: the __FUNCTION__ macro string includes | ||
229 | // the type and/or namespace prefixes | ||
230 | |||
231 | std::string::size_type p = preprocessor_name.rfind(':'); | ||
232 | if (p == std::string::npos) | ||
233 | { | ||
234 | return preprocessor_name; | ||
235 | } | ||
236 | return preprocessor_name.substr(p + 1); | ||
237 | |||
238 | #else | ||
239 | return preprocessor_name; | ||
240 | #endif | ||
241 | } | ||
242 | |||
243 | |||
244 | class LogControlFile : public LLLiveFile | ||
245 | { | ||
246 | LOG_CLASS(LogControlFile); | ||
247 | |||
248 | public: | ||
249 | static LogControlFile& fromDirectory(const std::string& dir); | ||
250 | |||
251 | virtual void loadFile(); | ||
252 | |||
253 | private: | ||
254 | LogControlFile(const std::string &filename) | ||
255 | : LLLiveFile(filename) | ||
256 | { } | ||
257 | }; | ||
258 | |||
259 | LogControlFile& LogControlFile::fromDirectory(const std::string& dir) | ||
260 | { | ||
261 | std::string dirBase = dir + "/"; | ||
262 | // NB: We have no abstraction in llcommon for the "proper" | ||
263 | // delimiter but it turns out that "/" works on all three platforms | ||
264 | |||
265 | std::string file = dirBase + "logcontrol-dev.xml"; | ||
266 | |||
267 | llstat stat_info; | ||
268 | if (LLFile::stat(file.c_str(), &stat_info)) { | ||
269 | // NB: stat returns non-zero if it can't read the file, for example | ||
270 | // if it doesn't exist. LLFile has no better abstraction for | ||
271 | // testing for file existence. | ||
272 | |||
273 | file = dirBase + "logcontrol.xml"; | ||
274 | } | ||
275 | return * new LogControlFile(file); | ||
276 | // NB: This instance is never freed | ||
277 | } | ||
278 | |||
279 | void LogControlFile::loadFile() | ||
280 | { | ||
281 | LLSD configuration; | ||
282 | |||
283 | { | ||
284 | llifstream file(filename().c_str()); | ||
285 | if (file.is_open()) | ||
286 | { | ||
287 | LLSDSerialize::fromXML(configuration, file); | ||
288 | } | ||
289 | |||
290 | if (configuration.isUndefined()) | ||
291 | { | ||
292 | llwarns << filename() << " missing, ill-formed," | ||
293 | " or simply undefined; not changing configuration" | ||
294 | << llendl; | ||
295 | return; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | LLError::configure(configuration); | ||
300 | llinfos << "logging reconfigured from " << filename() << llendl; | ||
301 | } | ||
302 | |||
303 | |||
304 | typedef std::map<std::string, LLError::ELevel> LevelMap; | ||
305 | typedef std::vector<LLError::Recorder*> Recorders; | ||
306 | typedef std::vector<LLError::CallSite*> CallSiteVector; | ||
307 | |||
308 | class Globals | ||
309 | { | ||
310 | public: | ||
311 | std::ostringstream messageStream; | ||
312 | bool messageStreamInUse; | ||
313 | |||
314 | void addCallSite(LLError::CallSite&); | ||
315 | void invalidateCallSites(); | ||
316 | |||
317 | static Globals& get(); | ||
318 | // return the one instance of the globals | ||
319 | |||
320 | private: | ||
321 | CallSiteVector callSites; | ||
322 | |||
323 | Globals() | ||
324 | : messageStreamInUse(false) | ||
325 | { } | ||
326 | |||
327 | }; | ||
328 | |||
329 | void Globals::addCallSite(LLError::CallSite& site) | ||
330 | { | ||
331 | callSites.push_back(&site); | ||
332 | } | ||
44 | 333 | ||
45 | // Loop forever, in case the crash didn't work? | 334 | void Globals::invalidateCallSites() |
335 | { | ||
336 | for (CallSiteVector::const_iterator i = callSites.begin(); | ||
337 | i != callSites.end(); | ||
338 | ++i) | ||
339 | { | ||
340 | (*i)->invalidate(); | ||
341 | } | ||
342 | |||
343 | callSites.clear(); | ||
344 | } | ||
345 | |||
346 | Globals& Globals::get() | ||
347 | { | ||
348 | /* This pattern, of returning a reference to a static function | ||
349 | variable, is to ensure that this global is constructed before | ||
350 | it is used, no matter what the global initializeation sequence | ||
351 | is. | ||
352 | See C++ FAQ Lite, sections 10.12 through 10.14 | ||
353 | */ | ||
354 | static Globals* globals = new Globals; | ||
355 | return *globals; | ||
46 | } | 356 | } |
47 | } | 357 | } |
48 | 358 | ||
49 | LLScopedErrorLevel::LLScopedErrorLevel(LLErrorBuffer::ELevel error_level) | 359 | namespace LLError |
50 | { | 360 | { |
51 | mOrigErrorLevel = gErrorStream.getErrorLevel(); | 361 | class Settings |
52 | gErrorStream.setErrorLevel(error_level); | 362 | { |
363 | public: | ||
364 | bool printLocation; | ||
365 | |||
366 | LLError::ELevel defaultLevel; | ||
367 | |||
368 | LevelMap functionLevelMap; | ||
369 | LevelMap classLevelMap; | ||
370 | LevelMap fileLevelMap; | ||
371 | |||
372 | LLError::FatalFunction crashFunction; | ||
373 | LLError::TimeFunction timeFunction; | ||
374 | |||
375 | Recorders recorders; | ||
376 | Recorder* fileRecorder; | ||
377 | Recorder* fixedBufferRecorder; | ||
378 | std::string fileRecorderFileName; | ||
379 | |||
380 | int shouldLogCallCounter; | ||
381 | |||
382 | static Settings& get(); | ||
383 | |||
384 | static void reset(); | ||
385 | static Settings* saveAndReset(); | ||
386 | static void restore(Settings*); | ||
387 | |||
388 | private: | ||
389 | Settings() | ||
390 | : printLocation(false), | ||
391 | defaultLevel(LLError::LEVEL_DEBUG), | ||
392 | crashFunction(NULL), | ||
393 | timeFunction(NULL), | ||
394 | fileRecorder(NULL), | ||
395 | fixedBufferRecorder(NULL), | ||
396 | shouldLogCallCounter(0) | ||
397 | { } | ||
398 | |||
399 | static Settings*& getPtr(); | ||
400 | }; | ||
401 | |||
402 | Settings& Settings::get() | ||
403 | { | ||
404 | Settings* p = getPtr(); | ||
405 | if (!p) | ||
406 | { | ||
407 | reset(); | ||
408 | p = getPtr(); | ||
409 | } | ||
410 | return *p; | ||
411 | } | ||
412 | |||
413 | void Settings::reset() | ||
414 | { | ||
415 | Globals::get().invalidateCallSites(); | ||
416 | |||
417 | Settings*& p = getPtr(); | ||
418 | delete p; | ||
419 | p = new Settings(); | ||
420 | } | ||
421 | |||
422 | Settings* Settings::saveAndReset() | ||
423 | { | ||
424 | Globals::get().invalidateCallSites(); | ||
425 | |||
426 | Settings*& p = getPtr(); | ||
427 | Settings* originalSettings = p; | ||
428 | p = new Settings(); | ||
429 | return originalSettings; | ||
430 | } | ||
431 | |||
432 | void Settings::restore(Settings* originalSettings) | ||
433 | { | ||
434 | Globals::get().invalidateCallSites(); | ||
435 | |||
436 | Settings*& p = getPtr(); | ||
437 | delete p; | ||
438 | p = originalSettings; | ||
439 | } | ||
440 | |||
441 | Settings*& Settings::getPtr() | ||
442 | { | ||
443 | static Settings* currentSettings = NULL; | ||
444 | return currentSettings; | ||
445 | } | ||
53 | } | 446 | } |
54 | 447 | ||
448 | namespace LLError | ||
449 | { | ||
450 | CallSite::CallSite(ELevel level, | ||
451 | const char* file, int line, | ||
452 | const std::type_info& class_info, const char* function) | ||
453 | : mLevel(level), mFile(file), mLine(line), | ||
454 | mClassInfo(class_info), mFunction(function), | ||
455 | mCached(false), mShouldLog(false) | ||
456 | { } | ||
457 | |||
458 | |||
459 | void CallSite::invalidate() | ||
460 | { mCached = false; } | ||
461 | } | ||
462 | |||
463 | namespace | ||
464 | { | ||
465 | bool shouldLogToStderr() | ||
466 | { | ||
467 | #if LL_DARWIN | ||
468 | // On Mac OS X, stderr from apps launched from the Finder goes to the | ||
469 | // console log. It's generally considered bad form to spam too much | ||
470 | // there. | ||
471 | |||
472 | // If stdin is a tty, assume the user launched from the command line and | ||
473 | // therefore wants to see stderr. Otherwise, assume we've been launched | ||
474 | // from the finder and shouldn't spam stderr. | ||
475 | return isatty(0); | ||
476 | #else | ||
477 | return true; | ||
478 | #endif | ||
479 | } | ||
480 | |||
481 | bool stderrLogWantsTime() | ||
482 | { | ||
483 | #if LL_WINDOWS | ||
484 | return false; | ||
485 | #else | ||
486 | return true; | ||
487 | #endif | ||
488 | } | ||
489 | |||
490 | |||
491 | void commonInit(const std::string& dir) | ||
492 | { | ||
493 | LLError::Settings::reset(); | ||
494 | |||
495 | LLError::setDefaultLevel(LLError::LEVEL_INFO); | ||
496 | LLError::setFatalFunction(LLError::crashAndLoop); | ||
497 | LLError::setTimeFunction(LLError::utcTime); | ||
498 | |||
499 | if (shouldLogToStderr()) | ||
500 | { | ||
501 | LLError::addRecorder(new RecordToStderr(stderrLogWantsTime())); | ||
502 | } | ||
503 | |||
504 | #if LL_WINDOWS | ||
505 | LLError::addRecorder(new RecordToWinDebug); | ||
506 | #endif | ||
55 | 507 | ||
56 | LLScopedErrorLevel::~LLScopedErrorLevel() | 508 | LogControlFile& e = LogControlFile::fromDirectory(dir); |
509 | e.addToEventTimer(); | ||
510 | } | ||
511 | } | ||
512 | |||
513 | namespace LLError | ||
57 | { | 514 | { |
58 | gErrorStream.setErrorLevel(mOrigErrorLevel); | 515 | void initForServer(const std::string& identity) |
516 | { | ||
517 | std::string dir = LLApp::instance()->getOption("configdir"); | ||
518 | commonInit(dir); | ||
519 | #if !LL_WINDOWS | ||
520 | addRecorder(new RecordToSyslog(identity)); | ||
521 | #endif | ||
522 | } | ||
523 | |||
524 | void initForApplication(const std::string& dir) | ||
525 | { | ||
526 | commonInit(dir); | ||
527 | } | ||
528 | |||
529 | void setPrintLocation(bool print) | ||
530 | { | ||
531 | Settings& s = Settings::get(); | ||
532 | s.printLocation = print; | ||
533 | } | ||
534 | |||
535 | void setFatalFunction(FatalFunction f) | ||
536 | { | ||
537 | Settings& s = Settings::get(); | ||
538 | s.crashFunction = f; | ||
539 | } | ||
540 | |||
541 | void setTimeFunction(TimeFunction f) | ||
542 | { | ||
543 | Settings& s = Settings::get(); | ||
544 | s.timeFunction = f; | ||
545 | } | ||
546 | |||
547 | void setDefaultLevel(ELevel level) | ||
548 | { | ||
549 | Globals& g = Globals::get(); | ||
550 | Settings& s = Settings::get(); | ||
551 | g.invalidateCallSites(); | ||
552 | s.defaultLevel = level; | ||
553 | } | ||
554 | |||
555 | void setFunctionLevel(const std::string& function_name, ELevel level) | ||
556 | { | ||
557 | Globals& g = Globals::get(); | ||
558 | Settings& s = Settings::get(); | ||
559 | g.invalidateCallSites(); | ||
560 | s.functionLevelMap[function_name] = level; | ||
561 | } | ||
562 | |||
563 | void setClassLevel(const std::string& class_name, ELevel level) | ||
564 | { | ||
565 | Globals& g = Globals::get(); | ||
566 | Settings& s = Settings::get(); | ||
567 | g.invalidateCallSites(); | ||
568 | s.classLevelMap[class_name] = level; | ||
569 | } | ||
570 | |||
571 | void setFileLevel(const std::string& file_name, ELevel level) | ||
572 | { | ||
573 | Globals& g = Globals::get(); | ||
574 | Settings& s = Settings::get(); | ||
575 | g.invalidateCallSites(); | ||
576 | s.fileLevelMap[file_name] = level; | ||
577 | } | ||
59 | } | 578 | } |
579 | |||
580 | namespace { | ||
581 | LLError::ELevel decodeLevel(std::string name) | ||
582 | { | ||
583 | static LevelMap level_names; | ||
584 | if (level_names.empty()) | ||
585 | { | ||
586 | level_names["ALL"] = LLError::LEVEL_ALL; | ||
587 | level_names["DEBUG"] = LLError::LEVEL_DEBUG; | ||
588 | level_names["INFO"] = LLError::LEVEL_INFO; | ||
589 | level_names["WARN"] = LLError::LEVEL_WARN; | ||
590 | level_names["ERROR"] = LLError::LEVEL_ERROR; | ||
591 | level_names["NONE"] = LLError::LEVEL_NONE; | ||
592 | } | ||
593 | |||
594 | std::transform(name.begin(), name.end(), name.begin(), toupper); | ||
595 | |||
596 | LevelMap::const_iterator i = level_names.find(name); | ||
597 | if (i == level_names.end()) | ||
598 | { | ||
599 | llwarns << "unrecognized logging level: '" << name << "'" << llendl; | ||
600 | return LLError::LEVEL_INFO; | ||
601 | } | ||
602 | |||
603 | return i->second; | ||
604 | } | ||
605 | |||
606 | void setLevels(LevelMap& map, const LLSD& list, LLError::ELevel level) | ||
607 | { | ||
608 | LLSD::array_const_iterator i, end; | ||
609 | for (i = list.beginArray(), end = list.endArray(); i != end; ++i) | ||
610 | { | ||
611 | map[*i] = level; | ||
612 | } | ||
613 | } | ||
614 | } | ||
615 | |||
616 | namespace LLError | ||
617 | { | ||
618 | void configure(const LLSD& config) | ||
619 | { | ||
620 | Globals& g = Globals::get(); | ||
621 | Settings& s = Settings::get(); | ||
622 | |||
623 | g.invalidateCallSites(); | ||
624 | s.functionLevelMap.clear(); | ||
625 | s.classLevelMap.clear(); | ||
626 | s.fileLevelMap.clear(); | ||
627 | |||
628 | setPrintLocation(config["print-location"]); | ||
629 | setDefaultLevel(decodeLevel(config["default-level"])); | ||
630 | |||
631 | LLSD sets = config["settings"]; | ||
632 | LLSD::array_const_iterator a, end; | ||
633 | for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a) | ||
634 | { | ||
635 | const LLSD& entry = *a; | ||
636 | |||
637 | ELevel level = decodeLevel(entry["level"]); | ||
638 | |||
639 | setLevels(s.functionLevelMap, entry["functions"], level); | ||
640 | setLevels(s.classLevelMap, entry["classes"], level); | ||
641 | setLevels(s.fileLevelMap, entry["files"], level); | ||
642 | } | ||
643 | } | ||
644 | } | ||
645 | |||
646 | |||
647 | namespace LLError | ||
648 | { | ||
649 | Recorder::~Recorder() | ||
650 | { } | ||
651 | |||
652 | // virtual | ||
653 | bool Recorder::wantsTime() | ||
654 | { return false; } | ||
655 | |||
656 | |||
657 | |||
658 | void addRecorder(Recorder* recorder) | ||
659 | { | ||
660 | if (recorder == NULL) | ||
661 | { | ||
662 | return; | ||
663 | } | ||
664 | Settings& s = Settings::get(); | ||
665 | s.recorders.push_back(recorder); | ||
666 | } | ||
667 | |||
668 | void removeRecorder(Recorder* recorder) | ||
669 | { | ||
670 | if (recorder == NULL) | ||
671 | { | ||
672 | return; | ||
673 | } | ||
674 | Settings& s = Settings::get(); | ||
675 | s.recorders.erase( | ||
676 | std::remove(s.recorders.begin(), s.recorders.end(), recorder), | ||
677 | s.recorders.end()); | ||
678 | } | ||
679 | } | ||
680 | |||
681 | namespace LLError | ||
682 | { | ||
683 | void logToFile(const std::string& file_name) | ||
684 | { | ||
685 | LLError::Settings& s = LLError::Settings::get(); | ||
686 | |||
687 | removeRecorder(s.fileRecorder); | ||
688 | delete s.fileRecorder; | ||
689 | s.fileRecorder = NULL; | ||
690 | s.fileRecorderFileName.clear(); | ||
691 | |||
692 | if (file_name.empty()) | ||
693 | { | ||
694 | return; | ||
695 | } | ||
696 | |||
697 | RecordToFile* f = new RecordToFile(file_name); | ||
698 | if (!f->okay()) | ||
699 | { | ||
700 | delete f; | ||
701 | return; | ||
702 | } | ||
703 | |||
704 | s.fileRecorderFileName = file_name; | ||
705 | s.fileRecorder = f; | ||
706 | addRecorder(f); | ||
707 | } | ||
708 | |||
709 | void logToFixedBuffer(LLFixedBuffer* fixedBuffer) | ||
710 | { | ||
711 | LLError::Settings& s = LLError::Settings::get(); | ||
712 | |||
713 | removeRecorder(s.fixedBufferRecorder); | ||
714 | delete s.fixedBufferRecorder; | ||
715 | s.fixedBufferRecorder = NULL; | ||
716 | |||
717 | if (!fixedBuffer) | ||
718 | { | ||
719 | return; | ||
720 | } | ||
721 | |||
722 | s.fixedBufferRecorder = new RecordToFixedBuffer(*fixedBuffer); | ||
723 | addRecorder(s.fixedBufferRecorder); | ||
724 | } | ||
725 | |||
726 | std::string logFileName() | ||
727 | { | ||
728 | LLError::Settings& s = LLError::Settings::get(); | ||
729 | return s.fileRecorderFileName; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | namespace | ||
734 | { | ||
735 | void writeToRecorders(LLError::ELevel level, const std::string& message) | ||
736 | { | ||
737 | LLError::Settings& s = LLError::Settings::get(); | ||
738 | |||
739 | std::string messageWithTime; | ||
740 | |||
741 | for (Recorders::const_iterator i = s.recorders.begin(); | ||
742 | i != s.recorders.end(); | ||
743 | ++i) | ||
744 | { | ||
745 | LLError::Recorder* r = *i; | ||
746 | |||
747 | if (r->wantsTime() && s.timeFunction != NULL) | ||
748 | { | ||
749 | if (messageWithTime.empty()) | ||
750 | { | ||
751 | messageWithTime = s.timeFunction() + " " + message; | ||
752 | } | ||
753 | |||
754 | r->recordMessage(level, messageWithTime); | ||
755 | } | ||
756 | else | ||
757 | { | ||
758 | r->recordMessage(level, message); | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | } | ||
763 | |||
764 | |||
765 | /* | ||
766 | Recorder formats: | ||
767 | |||
768 | $type = "ERROR" | "WARNING" | "ALERT" | "INFO" | "DEBUG" | ||
769 | $loc = "$file($line)" | ||
770 | $msg = "$loc : " if FATAL or printing loc | ||
771 | "" otherwise | ||
772 | $msg += "$type: " | ||
773 | $msg += contents of stringstream | ||
774 | |||
775 | $time = "%Y-%m-%dT%H:%M:%SZ" if UTC | ||
776 | or "%Y-%m-%dT%H:%M:%S %Z" if local | ||
777 | |||
778 | syslog: "$msg" | ||
779 | file: "$time $msg\n" | ||
780 | stderr: "$time $msg\n" except on windows, "$msg\n" | ||
781 | fixedbuf: "$msg" | ||
782 | winddebug: "$msg\n" | ||
783 | |||
784 | Note: if FATAL, an additional line gets logged first, with $msg set to | ||
785 | "$loc : error" | ||
786 | |||
787 | You get: | ||
788 | llfoo.cpp(42) : error | ||
789 | llfoo.cpp(42) : ERROR: something | ||
790 | |||
791 | */ | ||
792 | |||
793 | namespace { | ||
794 | bool checkLevelMap(const LevelMap& map, const std::string& key, | ||
795 | LLError::ELevel& level) | ||
796 | { | ||
797 | LevelMap::const_iterator i = map.find(key); | ||
798 | if (i == map.end()) | ||
799 | { | ||
800 | return false; | ||
801 | } | ||
802 | |||
803 | level = i->second; | ||
804 | return true; | ||
805 | } | ||
806 | |||
807 | class LogLock | ||
808 | { | ||
809 | public: | ||
810 | LogLock(); | ||
811 | ~LogLock(); | ||
812 | bool ok() const { return mOK; } | ||
813 | private: | ||
814 | bool mLocked; | ||
815 | bool mOK; | ||
816 | }; | ||
817 | |||
818 | LogLock::LogLock() | ||
819 | : mLocked(false), mOK(false) | ||
820 | { | ||
821 | if (!gLogMutexp) | ||
822 | { | ||
823 | mOK = true; | ||
824 | return; | ||
825 | } | ||
826 | |||
827 | const int MAX_RETRIES = 5; | ||
828 | for (int attempts = 0; attempts < MAX_RETRIES; ++attempts) | ||
829 | { | ||
830 | apr_status_t s = apr_thread_mutex_trylock(gLogMutexp); | ||
831 | if (!APR_STATUS_IS_EBUSY(s)) | ||
832 | { | ||
833 | mLocked = true; | ||
834 | mOK = true; | ||
835 | return; | ||
836 | } | ||
837 | |||
838 | ms_sleep(1); | ||
839 | //apr_thread_yield(); | ||
840 | // Just yielding won't necessarily work, I had problems with | ||
841 | // this on Linux - doug 12/02/04 | ||
842 | } | ||
843 | |||
844 | // We're hosed, we can't get the mutex. Blah. | ||
845 | std::cerr << "LogLock::LogLock: failed to get mutex for log" | ||
846 | << std::endl; | ||
847 | } | ||
848 | |||
849 | LogLock::~LogLock() | ||
850 | { | ||
851 | if (mLocked) | ||
852 | { | ||
853 | apr_thread_mutex_unlock(gLogMutexp); | ||
854 | } | ||
855 | } | ||
856 | } | ||
857 | |||
858 | namespace LLError | ||
859 | { | ||
860 | bool Log::shouldLog(CallSite& site) | ||
861 | { | ||
862 | LogLock lock; | ||
863 | if (!lock.ok()) | ||
864 | { | ||
865 | return false; | ||
866 | } | ||
867 | |||
868 | Globals& g = Globals::get(); | ||
869 | Settings& s = Settings::get(); | ||
870 | |||
871 | s.shouldLogCallCounter += 1; | ||
872 | |||
873 | std::string class_name = className(site.mClassInfo); | ||
874 | std::string function_name = functionName(site.mFunction); | ||
875 | if (site.mClassInfo != typeid(NoClassInfo)) | ||
876 | { | ||
877 | function_name = class_name + "::" + function_name; | ||
878 | } | ||
879 | |||
880 | ELevel compareLevel = s.defaultLevel; | ||
881 | |||
882 | checkLevelMap(s.functionLevelMap, function_name, compareLevel) | ||
883 | || checkLevelMap(s.classLevelMap, class_name, compareLevel) | ||
884 | || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel); | ||
885 | |||
886 | site.mCached = true; | ||
887 | g.addCallSite(site); | ||
888 | return site.mShouldLog = site.mLevel >= compareLevel; | ||
889 | } | ||
890 | |||
891 | |||
892 | std::ostringstream* Log::out() | ||
893 | { | ||
894 | LogLock lock; | ||
895 | if (lock.ok()) | ||
896 | { | ||
897 | Globals& g = Globals::get(); | ||
898 | |||
899 | if (!g.messageStreamInUse) | ||
900 | { | ||
901 | g.messageStreamInUse = true; | ||
902 | return &g.messageStream; | ||
903 | } | ||
904 | } | ||
905 | |||
906 | return new std::ostringstream; | ||
907 | } | ||
908 | |||
909 | void Log::flush(std::ostringstream* out, const CallSite& site) | ||
910 | { | ||
911 | LogLock lock; | ||
912 | if (!lock.ok()) | ||
913 | { | ||
914 | return; | ||
915 | } | ||
916 | |||
917 | Globals& g = Globals::get(); | ||
918 | Settings& s = Settings::get(); | ||
919 | |||
920 | std::string message = out->str(); | ||
921 | if (out == &g.messageStream) | ||
922 | { | ||
923 | g.messageStream.clear(); | ||
924 | g.messageStream.str(""); | ||
925 | g.messageStreamInUse = false; | ||
926 | } | ||
927 | else | ||
928 | { | ||
929 | delete out; | ||
930 | } | ||
931 | |||
932 | if (site.mLevel == LEVEL_ERROR) | ||
933 | { | ||
934 | std::ostringstream fatalMessage; | ||
935 | fatalMessage << abbreviateFile(site.mFile) | ||
936 | << "(" << site.mLine << ") : error"; | ||
937 | |||
938 | writeToRecorders(site.mLevel, fatalMessage.str()); | ||
939 | } | ||
940 | |||
941 | |||
942 | std::ostringstream prefix; | ||
943 | |||
944 | switch (site.mLevel) | ||
945 | { | ||
946 | case LEVEL_DEBUG: prefix << "DEBUG: "; break; | ||
947 | case LEVEL_INFO: prefix << "INFO: "; break; | ||
948 | case LEVEL_WARN: prefix << "WARNING: "; break; | ||
949 | case LEVEL_ERROR: prefix << "ERROR: "; break; | ||
950 | default: prefix << "XXX: "; break; | ||
951 | }; | ||
952 | |||
953 | if (s.printLocation) | ||
954 | { | ||
955 | prefix << abbreviateFile(site.mFile) | ||
956 | << "(" << site.mLine << ") : "; | ||
957 | } | ||
958 | |||
959 | if (message.find(functionName(site.mFunction)) == std::string::npos) | ||
960 | { | ||
961 | #if LL_WINDOWS | ||
962 | // DevStudio: __FUNCTION__ already includes the full class name | ||
963 | #else | ||
964 | if (site.mClassInfo != typeid(NoClassInfo)) | ||
965 | { | ||
966 | prefix << className(site.mClassInfo) << "::"; | ||
967 | } | ||
968 | #endif | ||
969 | prefix << site.mFunction << ": "; | ||
970 | } | ||
971 | |||
972 | prefix << message; | ||
973 | message = prefix.str(); | ||
974 | |||
975 | writeToRecorders(site.mLevel, message); | ||
976 | |||
977 | if (site.mLevel == LEVEL_ERROR && s.crashFunction) | ||
978 | { | ||
979 | s.crashFunction(message); | ||
980 | } | ||
981 | } | ||
982 | } | ||
983 | |||
984 | |||
985 | |||
986 | |||
987 | namespace LLError | ||
988 | { | ||
989 | Settings* saveAndResetSettings() | ||
990 | { | ||
991 | return Settings::saveAndReset(); | ||
992 | } | ||
993 | |||
994 | void restoreSettings(Settings* s) | ||
995 | { | ||
996 | return Settings::restore(s); | ||
997 | } | ||
998 | |||
999 | std::string removePrefix(std::string& s, const std::string& p) | ||
1000 | { | ||
1001 | std::string::size_type where = s.find(p); | ||
1002 | if (where == std::string::npos) | ||
1003 | { | ||
1004 | return s; | ||
1005 | } | ||
1006 | |||
1007 | return std::string(s, where + p.size()); | ||
1008 | } | ||
1009 | |||
1010 | void replaceChar(std::string& s, char old, char replacement) | ||
1011 | { | ||
1012 | std::string::size_type i = 0; | ||
1013 | std::string::size_type len = s.length(); | ||
1014 | for ( ; i < len; i++ ) | ||
1015 | { | ||
1016 | if (s[i] == old) | ||
1017 | { | ||
1018 | s[i] = replacement; | ||
1019 | } | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | std::string abbreviateFile(const std::string& filePath) | ||
1024 | { | ||
1025 | std::string f = filePath; | ||
1026 | #if LL_WINDOWS | ||
1027 | replaceChar(f, '\\', '/'); | ||
1028 | #endif | ||
1029 | static std::string indra_prefix = "indra/"; | ||
1030 | f = removePrefix(f, indra_prefix); | ||
1031 | |||
1032 | #if LL_DARWIN | ||
1033 | static std::string newview_prefix = "newview/../"; | ||
1034 | f = removePrefix(f, newview_prefix); | ||
1035 | #endif | ||
1036 | |||
1037 | return f; | ||
1038 | } | ||
1039 | |||
1040 | int shouldLogCallCount() | ||
1041 | { | ||
1042 | Settings& s = Settings::get(); | ||
1043 | return s.shouldLogCallCounter; | ||
1044 | } | ||
1045 | |||
1046 | void crashAndLoop(const std::string& message) | ||
1047 | { | ||
1048 | // Now, we go kaboom! | ||
1049 | int* crash = NULL; | ||
1050 | |||
1051 | *crash = 0; | ||
1052 | |||
1053 | while(true) | ||
1054 | { | ||
1055 | // Loop forever, in case the crash didn't work? | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | std::string utcTime() | ||
1060 | { | ||
1061 | time_t now = time(NULL); | ||
1062 | const size_t BUF_SIZE = 64; | ||
1063 | char time_str[BUF_SIZE]; /* Flawfinder: ignore */ | ||
1064 | |||
1065 | int chars = strftime(time_str, BUF_SIZE, | ||
1066 | "%Y-%m-%dT%H:%M:%SZ", | ||
1067 | gmtime(&now)); | ||
1068 | |||
1069 | return chars ? time_str : "time error"; | ||
1070 | } | ||
1071 | } | ||
1072 | |||
diff --git a/linden/indra/llcommon/llerror.h b/linden/indra/llcommon/llerror.h index 04e8eee..1285491 100644 --- a/linden/indra/llcommon/llerror.h +++ b/linden/indra/llcommon/llerror.h | |||
@@ -1,8 +1,9 @@ | |||
1 | /** | 1 | /** |
2 | * @file llerror.h | 2 | * @file llerror.h |
3 | * @brief Constants, functions, and macros for logging and runtime errors. | 3 | * @date December 2006 |
4 | * @brief error message system | ||
4 | * | 5 | * |
5 | * Copyright (c) 2001-2007, Linden Research, Inc. | 6 | * Copyright (c) 2006-2007, Linden Research, Inc. |
6 | * | 7 | * |
7 | * The source code in this file ("Source Code") is provided by Linden Lab | 8 | * 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 | * to you under the terms of the GNU General Public License, version 2.0 |
@@ -29,209 +30,208 @@ | |||
29 | #define LL_LLERROR_H | 30 | #define LL_LLERROR_H |
30 | 31 | ||
31 | #include <sstream> | 32 | #include <sstream> |
32 | #include <stdio.h> | 33 | #include <typeinfo> |
33 | #include <stdarg.h> | 34 | |
34 | 35 | #include "llerrorlegacy.h" | |
35 | #include "llerrorstream.h" | 36 | |
36 | #include "llerrorbuffer.h" | 37 | |
37 | 38 | /* Error Logging Facility | |
38 | // Specific error codes | 39 | |
39 | const S32 LL_ERR_NOERR = 0; | 40 | Information for most users: |
40 | const S32 LL_ERR_ASSET_REQUEST_FAILED = -1; | 41 | |
41 | //const S32 LL_ERR_ASSET_REQUEST_INVALID = -2; | 42 | Code can log messages with constuctions like this: |
42 | const S32 LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3; | 43 | |
43 | const S32 LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4; | 44 | llinfos << "request to fizzbip agent " << agent_id |
44 | const S32 LL_ERR_INSUFFICIENT_PERMISSIONS = -5; | 45 | << " denied due to timeout" << llendl; |
45 | const S32 LL_ERR_EOF = -39; | 46 | |
46 | const S32 LL_ERR_CANNOT_OPEN_FILE = -42; | 47 | Messages can be logged to one of four increasing levels of concern, |
47 | const S32 LL_ERR_FILE_NOT_FOUND = -43; | 48 | using one of four "streams": |
48 | const S32 LL_ERR_FILE_EMPTY = -44; | 49 | |
49 | const S32 LL_ERR_TCP_TIMEOUT = -23016; | 50 | lldebugs - debug messages that are normally supressed |
50 | const S32 LL_ERR_CIRCUIT_GONE = -23017; | 51 | llinfos - informational messages that are normall shown |
51 | 52 | llwarns - warning messages that singal a problem | |
52 | // Error types | 53 | llerrs - error messages that are major, unrecoverable failures |
53 | 54 | ||
54 | #define LLERR_IMAGE (1 << 1) // Image requests | 55 | The later (llerrs) automatically crashes the process after the message |
55 | #define LLERR_MESSAGE (1 << 2) // Messaging | 56 | is logged. |
56 | #define LLERR_PERF (1 << 3) // Performance | 57 | |
57 | #define LLERR_SQL (1 << 4) // SQL statements | 58 | Note that these "streams" are actually #define magic. Rules for use: |
58 | #define LLERR_DOUG (1 << 5) // Doug's debugging | 59 | * they cannot be used as normal streams, only to start a message |
59 | #define LLERR_USER_INPUT (1 << 6) // Keyboard and mouse | 60 | * messages written to them MUST be terminated with llendl |
60 | #define LLERR_TIMING (1 << 7) // Verbose time info | 61 | * between the opening and closing, the << operator is indeed |
61 | #define LLERR_TASK (1 << 8) // Tracking tasks | 62 | writing onto a std::ostream, so all conversions and stream |
62 | #define LLERR_MSG_HANDLER (1 << 9) // | 63 | formating are available |
63 | #define LLERR_CIRCUIT_INFO (1 << 10) // Message system circuit info | 64 | |
64 | #define LLERR_PHYSICS (1 << 11) // physics | 65 | These messages are automatically logged with function name, and (if enabled) |
65 | #define LLERR_VFS (1 << 12) // VFS | 66 | file and line of the message. (Note: Existing messages that already include |
66 | const U32 LLERR_ALL = 0xffff; | 67 | the function name don't get name printed twice.) |
67 | const U32 LLERR_NONE = 0x0; | 68 | |
68 | 69 | If you have a class, adding LOG_CLASS line to the declaration will cause | |
69 | // Define one of these for different error levels in release... | 70 | all messages emitted from member functions (normal and static) to be tagged |
70 | // #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output. | 71 | with the proper class name as well as the function name: |
71 | #define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output | 72 | |
72 | #define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output. | 73 | class LLFoo |
73 | 74 | { | |
74 | 75 | LOG_CLASS(LLFoo); | |
75 | ////////////////////////////////////////// | 76 | public: |
76 | // | 77 | ... |
77 | // Implementation - ignore | 78 | }; |
78 | // | 79 | |
79 | // | 80 | void LLFoo::doSomething(int i) |
80 | #ifdef _DEBUG | 81 | { |
81 | #define SHOW_DEBUG | 82 | if (i > 100) |
82 | #define SHOW_WARN | 83 | { |
83 | #define SHOW_INFO | 84 | llwanrs << "called with a big value for i: " << i << llendl; |
84 | #define SHOW_ASSERT | 85 | } |
85 | #else // _DEBUG | 86 | ... |
86 | 87 | } | |
87 | #ifdef RELEASE_SHOW_DEBUG | 88 | |
88 | #define SHOW_DEBUG | 89 | will result in messages like: |
89 | #endif | 90 | |
90 | 91 | WARN: LLFoo::doSomething: called with a big value for i: 283 | |
91 | #ifdef RELEASE_SHOW_WARN | 92 | |
92 | #define SHOW_WARN | 93 | Which messages are logged and which are supressed can be controled at run |
93 | #endif | 94 | time from the live file logcontrol.xml based on function, class and/or |
94 | 95 | source file. See etc/logcontrol-dev.xml for details. | |
95 | #ifdef RELEASE_SHOW_INFO | 96 | |
96 | #define SHOW_INFO | 97 | Lastly, logging is now very efficient in both compiled code and execution |
97 | #endif | 98 | when skipped. There is no need to wrap messages, even debugging ones, in |
98 | 99 | #ifdef _DEBUG constructs. lldebugs messages are compiled into all builds, | |
99 | #ifdef RELEASE_SHOW_ASSERT | 100 | even release. Which means you can use them to help debug even when deployed |
100 | #define SHOW_ASSERT | 101 | to a real grid. |
101 | #endif | 102 | */ |
102 | 103 | ||
103 | #endif // _DEBUG | 104 | namespace LLError |
104 | |||
105 | |||
106 | extern LLErrorStream gErrorStream; | ||
107 | |||
108 | |||
109 | // LL Error macros | ||
110 | // | ||
111 | // Usage: | ||
112 | // | ||
113 | // llerrs << "An error, oh my!" << variable << endl; | ||
114 | // llwarns << "Another error, fuck me!" << variable << endl; | ||
115 | // llwarnst(LLERR_IMAGE) << "Debug, mother fucker" << endl; | ||
116 | // | ||
117 | // NOTE: The output format of filename(lineno): is so that MS DevStudio | ||
118 | // can parse the output and automatically jump to that location | ||
119 | |||
120 | inline std::string llerrno_string(int errnum) | ||
121 | { | 105 | { |
122 | std::stringstream res; | 106 | enum ELevel |
123 | res << "error(" << errnum << "):" << strerror(errnum) << " "; | 107 | { |
124 | return res.str(); | 108 | LEVEL_ALL = 0, |
109 | // used to indicate that all messagess should be logged | ||
110 | |||
111 | LEVEL_DEBUG = 0, | ||
112 | LEVEL_INFO = 1, | ||
113 | LEVEL_WARN = 2, | ||
114 | LEVEL_ERROR = 3, // used to be called FATAL | ||
115 | |||
116 | LEVEL_NONE = 4 | ||
117 | // not really a level | ||
118 | // used to indicate that no messages should be logged | ||
119 | }; | ||
120 | |||
121 | /* Macro support | ||
122 | The classes CallSite and Log are used by the logging macros below. | ||
123 | They are not intended for general use. | ||
124 | */ | ||
125 | |||
126 | class CallSite; | ||
127 | |||
128 | class Log | ||
129 | { | ||
130 | public: | ||
131 | static bool shouldLog(CallSite&); | ||
132 | static std::ostringstream* out(); | ||
133 | static void flush(std::ostringstream*, const CallSite&); | ||
134 | }; | ||
135 | |||
136 | class CallSite | ||
137 | { | ||
138 | // Represents a specific place in the code where a message is logged | ||
139 | // This is public because it is used by the macros below. It is not | ||
140 | // intended for public use. | ||
141 | public: | ||
142 | CallSite(ELevel, const char* file, int line, | ||
143 | const std::type_info& class_info, const char* function); | ||
144 | |||
145 | bool shouldLog() | ||
146 | { return mCached ? mShouldLog : Log::shouldLog(*this); } | ||
147 | // this member function needs to be in-line for efficiency | ||
148 | |||
149 | void invalidate(); | ||
150 | |||
151 | private: | ||
152 | // these describe the call site and never change | ||
153 | const ELevel mLevel; | ||
154 | const char* const mFile; | ||
155 | const int mLine; | ||
156 | const std::type_info& mClassInfo; | ||
157 | const char* const mFunction; | ||
158 | |||
159 | // these implement a cache of the call to shouldLog() | ||
160 | bool mCached; | ||
161 | bool mShouldLog; | ||
162 | |||
163 | friend class Log; | ||
164 | }; | ||
165 | |||
166 | |||
167 | class End { }; | ||
168 | inline std::ostream& operator<<(std::ostream& s, const End&) | ||
169 | { return s; } | ||
170 | // used to indicate the end of a message | ||
171 | |||
172 | class NoClassInfo { }; | ||
173 | // used to indicate no class info known for logging | ||
125 | } | 174 | } |
126 | 175 | ||
127 | inline std::string llerror_file_line(const char* file, S32 line) | ||
128 | { | ||
129 | std::stringstream res; | ||
130 | res << file << "(" <<line << ")"; | ||
131 | return res.str(); | ||
132 | } | ||
133 | 176 | ||
134 | // Used to throw an error which is always causes a system halt. | ||
135 | #define llerrs if (gErrorStream.isEnabledFor(LLErrorBuffer::FATAL)) \ | ||
136 | { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::FATAL; \ | ||
137 | llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : error\n"; \ | ||
138 | llerror_oss << "ERROR: " << llerror_file_line(__FILE__, __LINE__) << " " | ||
139 | |||
140 | // Used to show warnings | ||
141 | #define llwarns if (gErrorStream.isEnabledFor(LLErrorBuffer::WARN)) \ | ||
142 | { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::WARN; \ | ||
143 | if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : WARNING: "; \ | ||
144 | else llerror_oss << "WARNING: "; \ | ||
145 | llerror_oss | ||
146 | |||
147 | // Alerts are for serious non-fatal situations that are not supposed to happen and need to alert someone | ||
148 | #define llalerts if (gErrorStream.isEnabledFor(LLErrorBuffer::WARN)) \ | ||
149 | { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::WARN; \ | ||
150 | if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : ALERT: "; \ | ||
151 | else llerror_oss << "ALERT: "; \ | ||
152 | llerror_oss | ||
153 | |||
154 | // Used to show informational messages that don't get disabled | ||
155 | #define llinfos if (gErrorStream.isEnabledFor(LLErrorBuffer::INFO)) \ | ||
156 | { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::INFO; \ | ||
157 | if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : INFO: "; \ | ||
158 | else llerror_oss << "INFO: "; \ | ||
159 | llerror_oss | ||
160 | |||
161 | #define llinfost(type) if (gErrorStream.isEnabledFor(LLErrorBuffer::INFO, type)) \ | ||
162 | { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::INFO; \ | ||
163 | if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : INFO: "; \ | ||
164 | else llerror_oss << "INFO: [" << #type << "] "; \ | ||
165 | llerror_oss | ||
166 | |||
167 | // Used for general debugging output | ||
168 | #define lldebugs if (gErrorStream.isEnabledFor(LLErrorBuffer::DEBUG)) \ | ||
169 | { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::DEBUG; \ | ||
170 | if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : DEBUG: "; \ | ||
171 | else llerror_oss << "DEBUG: "; \ | ||
172 | llerror_oss | ||
173 | |||
174 | #define lldebugst(type) if (gErrorStream.isEnabledFor(LLErrorBuffer::DEBUG, type)) \ | ||
175 | { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::DEBUG; \ | ||
176 | if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : DEBUG: "; \ | ||
177 | else llerror_oss << "DEBUG: [" << #type << "] "; \ | ||
178 | llerror_oss | ||
179 | |||
180 | #define llendl std::endl; gErrorStream.crashOnError(llerror_oss, llerror_level); } | ||
181 | #define llendflush std::endl << std::flush; gErrorStream.crashOnError(llerror_oss, llerror_level); } | ||
182 | #define llcont llerror_oss | ||
183 | |||
184 | #define llerror(msg, num) llerrs << "Error # " << num << ": " << msg << llendl; | ||
185 | |||
186 | #define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl; | ||
187 | |||
188 | #ifdef SHOW_ASSERT | ||
189 | #define llassert(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; | ||
190 | #else | ||
191 | #define llassert(func) | ||
192 | #endif | ||
193 | #define llassert_always(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; | ||
194 | |||
195 | #ifdef SHOW_ASSERT | ||
196 | #define llverify(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; | ||
197 | #else | ||
198 | #define llverify(func) (func); // get rid of warning C4189 | ||
199 | #endif | ||
200 | |||
201 | // handy compile-time assert - enforce those template parameters! | ||
202 | #define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] | ||
203 | |||
204 | // Makes the app go down in flames, but on purpose! | ||
205 | void _llcrash_and_loop(); | ||
206 | |||
207 | // Use as follows: | ||
208 | // llinfos << llformat("Test:%d (%.2f %.2f)", idx, x, y) << llendl; | ||
209 | // | ||
210 | // *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun) | ||
211 | // should perhaps be replaced with boost::format. | ||
212 | inline std::string llformat(const char *fmt, ...) | ||
213 | { | ||
214 | char tstr[1024]; /* Flawfinder: ignore */ | ||
215 | va_list va; | ||
216 | va_start(va, fmt); | ||
217 | #if LL_WINDOWS | ||
218 | _vsnprintf(tstr, 1024, fmt, va); | ||
219 | #else | ||
220 | vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */ | ||
221 | #endif | ||
222 | va_end(va); | ||
223 | return std::string(tstr); | ||
224 | } | ||
225 | 177 | ||
226 | // Helper class to temporarily change error level for the current scope. | 178 | /* |
227 | class LLScopedErrorLevel | 179 | Class type information for logging |
228 | { | 180 | */ |
229 | public: | 181 | |
230 | LLScopedErrorLevel(LLErrorBuffer::ELevel error_level); | 182 | #define LOG_CLASS(s) typedef s _LL_CLASS_TO_LOG |
231 | ~LLScopedErrorLevel(); | 183 | // Declares class to tag logged messages with. |
232 | 184 | // See top of file for example of how to use this | |
233 | private: | 185 | |
234 | LLErrorBuffer::ELevel mOrigErrorLevel; | 186 | typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; |
235 | }; | 187 | // Outside a class declartion, or in class without LOG_CLASS(), this |
236 | 188 | // typedef causes the messages to not be associated with any class. | |
189 | |||
190 | |||
191 | |||
192 | |||
193 | |||
194 | /* | ||
195 | Error Logging Macros | ||
196 | See top of file for common usage. | ||
197 | */ | ||
198 | |||
199 | #define lllog(level) \ | ||
200 | { \ | ||
201 | static LLError::CallSite _site( \ | ||
202 | level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__);\ | ||
203 | if (_site.shouldLog()) \ | ||
204 | { \ | ||
205 | std::ostringstream* _out = LLError::Log::out(); \ | ||
206 | (*_out) | ||
207 | |||
208 | #define llendl \ | ||
209 | LLError::End(); \ | ||
210 | LLError::Log::flush(_out, _site); \ | ||
211 | } \ | ||
212 | } | ||
213 | |||
214 | #define llinfos lllog(LLError::LEVEL_INFO) | ||
215 | #define lldebugs lllog(LLError::LEVEL_DEBUG) | ||
216 | #define llwarns lllog(LLError::LEVEL_WARN) | ||
217 | #define llerrs lllog(LLError::LEVEL_ERROR) | ||
218 | |||
219 | #define llcont (*_out) | ||
220 | /* | ||
221 | Use this construct if you need to do computation in the middle of a | ||
222 | message: | ||
223 | |||
224 | llinfos << "the agent " << agend_id; | ||
225 | switch (f) | ||
226 | { | ||
227 | case FOP_SHRUGS: llcont << "shrugs"; break; | ||
228 | case FOP_TAPS: llcont << "points at " << who; break; | ||
229 | case FOP_SAYS: llcont << "says " << message; break; | ||
230 | } | ||
231 | llcont << " for " << t << " seconds" << llendl; | ||
232 | |||
233 | Such computation is done iff the message will be logged. | ||
234 | */ | ||
235 | |||
236 | |||
237 | #endif // LL_LLERROR_H | 237 | #endif // LL_LLERROR_H |
diff --git a/linden/indra/llcommon/llerrorbuffer.cpp b/linden/indra/llcommon/llerrorbuffer.cpp deleted file mode 100644 index 9de4616..0000000 --- a/linden/indra/llcommon/llerrorbuffer.cpp +++ /dev/null | |||
@@ -1,279 +0,0 @@ | |||
1 | /** | ||
2 | * @file llerrorbuffer.cpp | ||
3 | * | ||
4 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #include "linden_common.h" | ||
28 | |||
29 | #include "llerrorbuffer.h" | ||
30 | #include "llfixedbuffer.h" | ||
31 | |||
32 | #include <fstream> | ||
33 | #include <string.h> | ||
34 | |||
35 | #if LL_WINDOWS | ||
36 | # define WIN32_LEAN_AND_MEAN | ||
37 | # include <winsock2.h> | ||
38 | # include <windows.h> // for OutputDebugString | ||
39 | #else | ||
40 | # include <syslog.h> | ||
41 | # include <stdio.h> | ||
42 | #endif | ||
43 | |||
44 | #include <time.h> | ||
45 | |||
46 | // In order to compile in Visual C++ 6.0, you must use std:: in the header, and then | ||
47 | // use the std namespace in the cpp. Otherwise, you'll break the (very) fragile C++ parser. | ||
48 | using namespace std; | ||
49 | |||
50 | LLErrorBuffer::LLErrorBuffer() | ||
51 | : streambuf(), | ||
52 | mFile(NULL), | ||
53 | mBuf(), | ||
54 | mFixedBuf(NULL), | ||
55 | mErrorActive(TRUE), | ||
56 | mErrorTimestamp(TRUE), | ||
57 | mFileActive(FALSE), | ||
58 | mSyslogActive(TRUE), | ||
59 | mWinDebugActive(TRUE), | ||
60 | mElevatedRemote(FALSE), | ||
61 | mIsUTC(TRUE), | ||
62 | mLevel(DEBUG), | ||
63 | mPriority(DEBUG) | ||
64 | { | ||
65 | mFilename[0] = '\0'; | ||
66 | #if LL_WINDOWS | ||
67 | // by default, turn off timestamps in the debug log on windows | ||
68 | mErrorTimestamp = FALSE; | ||
69 | #endif | ||
70 | } | ||
71 | |||
72 | LLErrorBuffer::~LLErrorBuffer() | ||
73 | { | ||
74 | delete mFile; | ||
75 | mFile = NULL; | ||
76 | } | ||
77 | |||
78 | #if !LL_WINDOWS | ||
79 | int LLErrorBuffer::ELevelToSyslogPriority(const ELevel l) | ||
80 | { | ||
81 | switch(l) | ||
82 | { | ||
83 | case DEBUG: | ||
84 | return LOG_DEBUG; | ||
85 | case INFO: | ||
86 | switch(mElevatedRemote) | ||
87 | { | ||
88 | case TRUE: return LOG_NOTICE; | ||
89 | default: return LOG_INFO; | ||
90 | } | ||
91 | case WARN: | ||
92 | return LOG_WARNING; | ||
93 | case FATAL: | ||
94 | return LOG_CRIT; | ||
95 | default: | ||
96 | return LOG_CRIT; | ||
97 | } | ||
98 | return LOG_CRIT; | ||
99 | } | ||
100 | #endif // LL_WINDOWS | ||
101 | |||
102 | BOOL LLErrorBuffer::setFile(const char *filename) | ||
103 | { | ||
104 | if (mFile == NULL) | ||
105 | { | ||
106 | mFile = new llofstream(); | ||
107 | } | ||
108 | if (mFile->is_open()) | ||
109 | { | ||
110 | mFile->close(); | ||
111 | } | ||
112 | if (filename == NULL) | ||
113 | { | ||
114 | llwarns << "Input filename is NULL!!" << llendl; | ||
115 | return FALSE; | ||
116 | } | ||
117 | mFile->open(filename, llofstream::out | llofstream::app); /* Flawfinder: ignore */ | ||
118 | if (mFile->is_open()) | ||
119 | { | ||
120 | mFileActive = TRUE; | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | mFileActive = FALSE; | ||
125 | delete mFile; | ||
126 | mFile = NULL; | ||
127 | } | ||
128 | snprintf(mFilename, sizeof(mFilename), filename); /* Flawfinder: ignore */ | ||
129 | return mFileActive; | ||
130 | } | ||
131 | |||
132 | void LLErrorBuffer::closeFile() | ||
133 | { | ||
134 | if (mFile && mFile->is_open()) | ||
135 | { | ||
136 | mFile->close(); | ||
137 | mFileActive = FALSE; | ||
138 | delete mFile; | ||
139 | mFile = NULL; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | const char * LLErrorBuffer::getFilename() const | ||
144 | { | ||
145 | return mFilename; | ||
146 | } | ||
147 | |||
148 | void LLErrorBuffer::setUTCTimestamp(BOOL utc) | ||
149 | { | ||
150 | mIsUTC = utc; | ||
151 | } | ||
152 | |||
153 | void LLErrorBuffer::enableError(BOOL active) | ||
154 | { | ||
155 | mErrorActive = active; | ||
156 | } | ||
157 | |||
158 | void LLErrorBuffer::enableErrorTimestamp(BOOL active) | ||
159 | { | ||
160 | mErrorTimestamp = active; | ||
161 | } | ||
162 | |||
163 | void LLErrorBuffer::enableFile(BOOL active) | ||
164 | { | ||
165 | if (mFile != NULL) | ||
166 | { | ||
167 | if (mFile->is_open()) | ||
168 | mFileActive = active; | ||
169 | } | ||
170 | else | ||
171 | mFileActive = FALSE; | ||
172 | } | ||
173 | |||
174 | #if !LL_WINDOWS | ||
175 | void LLErrorBuffer::enableSyslog(BOOL active) | ||
176 | { | ||
177 | mSyslogActive = active; | ||
178 | } | ||
179 | #endif // LL_WINDOWS | ||
180 | |||
181 | #if LL_WINDOWS | ||
182 | void LLErrorBuffer::enableWinDebug(BOOL active) | ||
183 | { | ||
184 | mWinDebugActive = active; | ||
185 | } | ||
186 | #endif // LL_WINDOWS | ||
187 | |||
188 | int LLErrorBuffer::overflow(int c) | ||
189 | { | ||
190 | if (EOF != c) | ||
191 | { | ||
192 | if ('\n' == c) | ||
193 | { | ||
194 | // If we're not supposed to print anything, don't, but | ||
195 | // pretend that we did so taht the iostream doesn't think | ||
196 | // there's been a failure | ||
197 | if (mPriority < mLevel) | ||
198 | { | ||
199 | // Flush our message buffer | ||
200 | mBuf = ""; | ||
201 | return 0; | ||
202 | } | ||
203 | #if !LL_WINDOWS | ||
204 | if (mSyslogActive) | ||
205 | { | ||
206 | int pri = ELevelToSyslogPriority(mPriority); | ||
207 | syslog(pri, "%s", mBuf.c_str()); | ||
208 | } | ||
209 | #endif // LL_WINDOWS | ||
210 | const S32 BUF_SIZE = 64; | ||
211 | char time_str[BUF_SIZE]; /* Flawfinder: ignore */ | ||
212 | if (mFileActive || mErrorActive) | ||
213 | { | ||
214 | time_t now; | ||
215 | time(&now); | ||
216 | S32 chars; | ||
217 | if(mIsUTC) | ||
218 | { | ||
219 | chars = (S32)strftime(time_str, BUF_SIZE, | ||
220 | "%Y-%m-%dT%H:%M:%SZ", | ||
221 | gmtime(&now)); | ||
222 | } | ||
223 | else | ||
224 | { | ||
225 | chars = (S32)strftime(time_str, BUF_SIZE, | ||
226 | "%Y-%m-%dT%H:%M:%S %Z", | ||
227 | localtime(&now)); | ||
228 | } | ||
229 | if (0 == chars) | ||
230 | { | ||
231 | strcpy(time_str, "time error"); /* Flawfinder: ignore */ | ||
232 | } | ||
233 | } | ||
234 | if (mFileActive) | ||
235 | { | ||
236 | *mFile << time_str << " " << mBuf << std::endl; | ||
237 | } | ||
238 | if (mErrorActive) | ||
239 | { | ||
240 | if (mErrorTimestamp) | ||
241 | { | ||
242 | fprintf(stderr, "%s %s\n", time_str, mBuf.c_str()); | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | fprintf(stderr, "%s\n", mBuf.c_str()); | ||
247 | } | ||
248 | |||
249 | // std::cerr goes into the void on the viewer | ||
250 | //std::cerr << time_str << ' ' << mBuf << std::endl; | ||
251 | } | ||
252 | if (mFixedBuf) | ||
253 | { | ||
254 | mFixedBuf->addLine(mBuf.c_str()); | ||
255 | } | ||
256 | #if LL_WINDOWS | ||
257 | if (mWinDebugActive) | ||
258 | { | ||
259 | llutf16string utf16str = wstring_to_utf16str(utf8str_to_wstring(mBuf)); | ||
260 | utf16str += '\n'; | ||
261 | OutputDebugString(utf16str.c_str()); | ||
262 | } | ||
263 | #endif // LL_WINDOWS | ||
264 | // Is there a better way to truncate a string? | ||
265 | mBuf.erase(0, mBuf.length()); // Hack, Linux doesn't implement clear()! | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | mBuf += c; | ||
270 | } | ||
271 | } | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | LLErrorBuffer::ELevel LLErrorBuffer::mergeLevel(const LLErrorBuffer::ELevel l) | ||
276 | { | ||
277 | mLevel = llmin(mLevel, l); | ||
278 | return mLevel; | ||
279 | } | ||
diff --git a/linden/indra/llcommon/llerrorbuffer.h b/linden/indra/llcommon/llerrorbuffer.h deleted file mode 100644 index b52de3a..0000000 --- a/linden/indra/llcommon/llerrorbuffer.h +++ /dev/null | |||
@@ -1,117 +0,0 @@ | |||
1 | /** | ||
2 | * @file llerrorbuffer.h | ||
3 | * @brief Buffer implementation for logging. | ||
4 | * | ||
5 | * Copyright (c) 2002-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 | #ifndef LL_LLERRORBUFFER_H | ||
29 | #define LL_LLERRORBUFFER_H | ||
30 | |||
31 | #include <fstream> | ||
32 | #include <iostream> | ||
33 | #include <string> | ||
34 | |||
35 | #include "lldefs.h" | ||
36 | #include "stdtypes.h" | ||
37 | #include "llfile.h" | ||
38 | |||
39 | // A streambuf that sends it's output into a file, stderr, or syslog. | ||
40 | // | ||
41 | // Each output can be enabled/disabled, and a priority can be set. | ||
42 | |||
43 | class LLFixedBuffer; | ||
44 | |||
45 | class LLErrorBuffer : public std::streambuf | ||
46 | { | ||
47 | public: | ||
48 | |||
49 | // Specify error levels | ||
50 | enum ELevel | ||
51 | { | ||
52 | DEBUG = 0, | ||
53 | INFO = 1, | ||
54 | WARN = 2, | ||
55 | FATAL = 3, | ||
56 | NONE = 4 // Do NO error logging (for use in signal handlers) | ||
57 | }; | ||
58 | |||
59 | LLErrorBuffer(); | ||
60 | ~LLErrorBuffer(); | ||
61 | BOOL setFile(const char *filename); | ||
62 | void closeFile(); | ||
63 | const char *getFilename() const; | ||
64 | void setFixedBuffer(LLFixedBuffer *b) { mFixedBuf = b; }; | ||
65 | |||
66 | // Sets the priority of the current message | ||
67 | void setPriority(const ELevel l) { mPriority = l; } | ||
68 | |||
69 | // Only display messages >= to this level | ||
70 | void setLevel(const ELevel l) { mLevel = l; } | ||
71 | ELevel getLevel() { return mLevel; } | ||
72 | // Display messages >= to level l, if l < current level | ||
73 | ELevel mergeLevel(const ELevel l); | ||
74 | |||
75 | // on linux, this sets syslog info to be a LOG_NOTICE which will | ||
76 | // be centrally logged. *NOTE: This is very | ||
77 | // linux/syslog/configuration dependent. | ||
78 | void setElevatedRemote(BOOL b) { mElevatedRemote = b; } | ||
79 | |||
80 | // logs are in utc rather than local | ||
81 | void setUTCTimestamp(BOOL utc); | ||
82 | |||
83 | // Turn on or off logging outputs | ||
84 | void enableError(BOOL active); | ||
85 | void enableErrorTimestamp(BOOL active); | ||
86 | void enableFile(BOOL active); | ||
87 | void enableSyslog(BOOL active); | ||
88 | #if LL_WINDOWS | ||
89 | void enableWinDebug(BOOL active); | ||
90 | #endif // LL_WINDOWS | ||
91 | |||
92 | protected: | ||
93 | int overflow(int c = EOF); | ||
94 | |||
95 | private: | ||
96 | char mFilename[LL_MAX_PATH]; /* Flawfinder: ignore */ | ||
97 | int ELevelToSyslogPriority(const ELevel l); | ||
98 | |||
99 | llofstream *mFile; | ||
100 | std::string mBuf; | ||
101 | LLFixedBuffer *mFixedBuf; | ||
102 | |||
103 | BOOL mErrorActive; | ||
104 | BOOL mErrorTimestamp; | ||
105 | BOOL mFileActive; | ||
106 | BOOL mSyslogActive; | ||
107 | BOOL mWinDebugActive; | ||
108 | BOOL mElevatedRemote; | ||
109 | BOOL mIsUTC; | ||
110 | |||
111 | // If priority < level, output is thrown away | ||
112 | ELevel mLevel; | ||
113 | // Current message priority | ||
114 | ELevel mPriority; | ||
115 | }; | ||
116 | |||
117 | #endif // LL_LLERRORBUFFER_H | ||
diff --git a/linden/indra/llcommon/llerrorcontrol.h b/linden/indra/llcommon/llerrorcontrol.h new file mode 100644 index 0000000..f2c8755 --- /dev/null +++ b/linden/indra/llcommon/llerrorcontrol.h | |||
@@ -0,0 +1,142 @@ | |||
1 | /** | ||
2 | * @file llerrorcontrol.h | ||
3 | * @date December 2006 | ||
4 | * @brief error message system control | ||
5 | * | ||
6 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #ifndef LL_LLERRORCONTROL_H | ||
30 | #define LL_LLERRORCONTROL_H | ||
31 | |||
32 | #include "llerror.h" | ||
33 | |||
34 | #include <string> | ||
35 | |||
36 | class LLFixedBuffer; | ||
37 | class LLSD; | ||
38 | |||
39 | /* | ||
40 | This is the part of the LLError namespace that manages the messages | ||
41 | produced by the logging. The logging support is defined in llerror.h. | ||
42 | Most files do not need to include this. | ||
43 | |||
44 | These implementations are in llerror.cpp. | ||
45 | */ | ||
46 | |||
47 | |||
48 | namespace LLError | ||
49 | { | ||
50 | void initForServer(const std::string& identity); | ||
51 | // resets all logging settings to defaults needed by server processes | ||
52 | // logs to stderr, syslog, and windows debug log | ||
53 | // the identity string is used for in the syslog | ||
54 | |||
55 | void initForApplication(const std::string& dir); | ||
56 | // resets all logging settings to defaults needed by applicaitons | ||
57 | // logs to stderr and windows debug log | ||
58 | // sets up log configuration from the file logcontrol.xml in dir | ||
59 | |||
60 | |||
61 | /* | ||
62 | Settings that control what is logged. | ||
63 | Setting a level means log messages at that level or above. | ||
64 | */ | ||
65 | |||
66 | void setPrintLocation(bool); | ||
67 | void setDefaultLevel(LLError::ELevel); | ||
68 | void setFunctionLevel(const std::string& function_name, LLError::ELevel); | ||
69 | void setClassLevel(const std::string& class_name, LLError::ELevel); | ||
70 | void setFileLevel(const std::string& file_name, LLError::ELevel); | ||
71 | |||
72 | void configure(const LLSD&); | ||
73 | // the LLSD can configure all of the settings | ||
74 | // usually read automatically from the live errorlog.xml file | ||
75 | |||
76 | |||
77 | /* | ||
78 | Control functions. | ||
79 | */ | ||
80 | |||
81 | typedef void (*FatalFunction)(const std::string& message); | ||
82 | void crashAndLoop(const std::string& message); | ||
83 | // Default fatal funtion: divides by zero and loops forever | ||
84 | |||
85 | void setFatalFunction(FatalFunction); | ||
86 | // The fatal function will be called when an message of LEVEL_ERROR | ||
87 | // is logged. Note: supressing a LEVEL_ERROR message from being logged | ||
88 | // (by, for example, setting a class level to LEVEL_NONE), will keep | ||
89 | // the that message from causing the fatal funciton to be invoked. | ||
90 | |||
91 | typedef std::string (*TimeFunction)(); | ||
92 | std::string utcTime(); | ||
93 | |||
94 | void setTimeFunction(TimeFunction); | ||
95 | // The function is use to return the current time, formatted for | ||
96 | // display by those error recorders that want the time included. | ||
97 | |||
98 | |||
99 | |||
100 | class Recorder | ||
101 | { | ||
102 | // An object that handles the actual output or error messages. | ||
103 | public: | ||
104 | virtual ~Recorder(); | ||
105 | |||
106 | virtual void recordMessage(LLError::ELevel, const std::string& message) = 0; | ||
107 | // use the level for better display, not for filtering | ||
108 | |||
109 | virtual bool wantsTime(); // default returns false | ||
110 | // override and return true if the recorder wants the time string | ||
111 | // included in the text of the message | ||
112 | }; | ||
113 | |||
114 | void addRecorder(Recorder*); | ||
115 | void removeRecorder(Recorder*); | ||
116 | // each error message is passed to each recorder via recordMessage() | ||
117 | |||
118 | void logToFile(const std::string& filename); | ||
119 | void logToFixedBuffer(LLFixedBuffer*); | ||
120 | // Utilities to add recorders for logging to a file or a fixed buffer | ||
121 | // A second call to the same function will remove the logger added | ||
122 | // with the first. | ||
123 | // Passing the empty string or NULL to just removes any prior. | ||
124 | std::string logFileName(); | ||
125 | // returns name of current logging file, empty string if none | ||
126 | |||
127 | |||
128 | /* | ||
129 | Utilities for use by the unit tests of LLError itself. | ||
130 | */ | ||
131 | |||
132 | class Settings; | ||
133 | Settings* saveAndResetSettings(); | ||
134 | void restoreSettings(Settings *); | ||
135 | |||
136 | std::string abbreviateFile(const std::string& filePath); | ||
137 | int shouldLogCallCount(); | ||
138 | |||
139 | }; | ||
140 | |||
141 | #endif // LL_LLERRORCONTROL_H | ||
142 | |||
diff --git a/linden/indra/llcommon/llerrorlegacy.h b/linden/indra/llcommon/llerrorlegacy.h new file mode 100644 index 0000000..5438a21 --- /dev/null +++ b/linden/indra/llcommon/llerrorlegacy.h | |||
@@ -0,0 +1,117 @@ | |||
1 | /** | ||
2 | * @file llerrorlegacy.h | ||
3 | * @date January 2007 | ||
4 | * @brief old things from the older error system | ||
5 | * | ||
6 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #ifndef LL_LLERRORLEGACY_H | ||
30 | #define LL_LLERRORLEGACY_H | ||
31 | |||
32 | |||
33 | |||
34 | /* | ||
35 | LEGACY -- DO NOT USE THIS STUFF ANYMORE | ||
36 | */ | ||
37 | |||
38 | // Specific error codes | ||
39 | const int LL_ERR_NOERR = 0; | ||
40 | const int LL_ERR_ASSET_REQUEST_FAILED = -1; | ||
41 | //const int LL_ERR_ASSET_REQUEST_INVALID = -2; | ||
42 | const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3; | ||
43 | const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4; | ||
44 | const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5; | ||
45 | const int LL_ERR_EOF = -39; | ||
46 | const int LL_ERR_CANNOT_OPEN_FILE = -42; | ||
47 | const int LL_ERR_FILE_NOT_FOUND = -43; | ||
48 | const int LL_ERR_FILE_EMPTY = -44; | ||
49 | const int LL_ERR_TCP_TIMEOUT = -23016; | ||
50 | const int LL_ERR_CIRCUIT_GONE = -23017; | ||
51 | |||
52 | |||
53 | |||
54 | // Define one of these for different error levels in release... | ||
55 | // #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output. | ||
56 | #define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output | ||
57 | #define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output. | ||
58 | |||
59 | |||
60 | ////////////////////////////////////////// | ||
61 | // | ||
62 | // Implementation - ignore | ||
63 | // | ||
64 | // | ||
65 | #ifdef _DEBUG | ||
66 | #define SHOW_DEBUG | ||
67 | #define SHOW_WARN | ||
68 | #define SHOW_INFO | ||
69 | #define SHOW_ASSERT | ||
70 | #else // _DEBUG | ||
71 | |||
72 | #ifdef RELEASE_SHOW_DEBUG | ||
73 | #define SHOW_DEBUG | ||
74 | #endif | ||
75 | |||
76 | #ifdef RELEASE_SHOW_WARN | ||
77 | #define SHOW_WARN | ||
78 | #endif | ||
79 | |||
80 | #ifdef RELEASE_SHOW_INFO | ||
81 | #define SHOW_INFO | ||
82 | #endif | ||
83 | |||
84 | #ifdef RELEASE_SHOW_ASSERT | ||
85 | #define SHOW_ASSERT | ||
86 | #endif | ||
87 | |||
88 | #endif // _DEBUG | ||
89 | |||
90 | |||
91 | |||
92 | #define lldebugst(type) lldebugs | ||
93 | #define llendflush llendl | ||
94 | |||
95 | |||
96 | #define llerror(msg, num) llerrs << "Error # " << num << ": " << msg << llendl; | ||
97 | |||
98 | #define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl; | ||
99 | |||
100 | #ifdef SHOW_ASSERT | ||
101 | #define llassert(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; | ||
102 | #else | ||
103 | #define llassert(func) | ||
104 | #endif | ||
105 | #define llassert_always(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; | ||
106 | |||
107 | #ifdef SHOW_ASSERT | ||
108 | #define llverify(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; | ||
109 | #else | ||
110 | #define llverify(func) (func); // get rid of warning C4189 | ||
111 | #endif | ||
112 | |||
113 | // handy compile-time assert - enforce those template parameters! | ||
114 | #define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */ | ||
115 | //XXX: used in two places in llcommon/llskipmap.h | ||
116 | |||
117 | #endif // LL_LLERRORLEGACY_H | ||
diff --git a/linden/indra/llcommon/llerrorstream.cpp b/linden/indra/llcommon/llerrorstream.cpp deleted file mode 100644 index ed54d88..0000000 --- a/linden/indra/llcommon/llerrorstream.cpp +++ /dev/null | |||
@@ -1,188 +0,0 @@ | |||
1 | /** | ||
2 | * @file llerrorstream.cpp | ||
3 | * @brief Implementation of c++ log straming. | ||
4 | * | ||
5 | * Copyright (c) 2002-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 | |||
30 | #include "llerrorstream.h" | ||
31 | #include "llerrorbuffer.h" | ||
32 | #include "llerror.h" | ||
33 | |||
34 | using namespace std; | ||
35 | |||
36 | // Define this if we're using APR mutexes. | ||
37 | #include "llapr.h" | ||
38 | extern apr_thread_mutex_t *gLogMutexp; | ||
39 | |||
40 | // In order to compile in Visual C++ 6.0, you must use std:: in the header, and then | ||
41 | // use the std namespace in the cpp. Otherwise, you'll break the (very) fragile C++ parser. | ||
42 | LLErrorStream::LLErrorStream(LLErrorBuffer *eb): | ||
43 | ostream(eb), | ||
44 | mErrorBuffer(eb), | ||
45 | mKill(FALSE), | ||
46 | mErrorCallback(NULL) | ||
47 | { | ||
48 | #ifdef SHOW_DEBUG | ||
49 | setErrorLevel(LLErrorBuffer::DEBUG); | ||
50 | #else | ||
51 | #ifdef SHOW_INFO | ||
52 | setErrorLevel(LLErrorBuffer::INFO); | ||
53 | #else | ||
54 | #ifdef SHOW_WARN | ||
55 | setErrorLevel(LLErrorBuffer::WARN); | ||
56 | #else | ||
57 | setErrorLevel(LLErrorBuffer::FATAL); | ||
58 | #endif // SHOW_WARN | ||
59 | #endif // SHOW_INFO | ||
60 | #endif // SHOW_DEBUG | ||
61 | |||
62 | setDebugMask(LLERR_NONE); | ||
63 | setPrintLocation(FALSE); | ||
64 | } | ||
65 | |||
66 | LLErrorBuffer::ELevel LLErrorStream::ELevelToBufferELevel(const ELevel l) | ||
67 | { | ||
68 | switch (l) | ||
69 | { | ||
70 | case DEBUG: | ||
71 | return LLErrorBuffer::DEBUG; | ||
72 | case INFO: | ||
73 | return LLErrorBuffer::INFO; | ||
74 | case WARN: | ||
75 | return LLErrorBuffer::WARN; | ||
76 | case FATAL: | ||
77 | return LLErrorBuffer::FATAL; | ||
78 | default: | ||
79 | return LLErrorBuffer::FATAL; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | LLErrorStream::ELevel LLErrorStream::BufferELevelToELevel(const LLErrorBuffer::ELevel l) | ||
84 | { | ||
85 | switch(l) | ||
86 | { | ||
87 | case LLErrorBuffer::DEBUG: | ||
88 | return DEBUG; | ||
89 | case LLErrorBuffer::INFO: | ||
90 | return INFO; | ||
91 | case LLErrorBuffer::WARN: | ||
92 | return WARN; | ||
93 | case LLErrorBuffer::FATAL: | ||
94 | return FATAL; | ||
95 | default: | ||
96 | return FATAL; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | |||
101 | BOOL LLErrorStream::isEnabledFor(const LLErrorBuffer::ELevel l) | ||
102 | { | ||
103 | if (l == LLErrorBuffer::FATAL) | ||
104 | { | ||
105 | if (LLErrorBuffer::FATAL < getErrorLevel()) | ||
106 | { | ||
107 | // Fatal error, but we're at log level NONE (used by signal handlers) | ||
108 | // We want to crash this process now instead of logging | ||
109 | _llcrash_and_loop(); | ||
110 | } | ||
111 | } | ||
112 | // Always returns false if not safe (recursive call) | ||
113 | return (getErrorLevel() <= l); | ||
114 | } | ||
115 | |||
116 | |||
117 | BOOL LLErrorStream::isEnabledFor(const LLErrorBuffer::ELevel l, const U32 type) | ||
118 | { | ||
119 | // Always returns false if not safe (recursive call) | ||
120 | return (getErrorLevel() <= l) && (mDebugMask & type); | ||
121 | } | ||
122 | |||
123 | |||
124 | |||
125 | void LLErrorStream::crashOnError(std::ostringstream &oss, LLErrorBuffer::ELevel l) | ||
126 | { | ||
127 | if (gLogMutexp) | ||
128 | { | ||
129 | const S32 MAX_RETRIES = 5; | ||
130 | S32 attempts = 0; | ||
131 | while (attempts < MAX_RETRIES) | ||
132 | { | ||
133 | apr_status_t s = apr_thread_mutex_trylock(gLogMutexp); | ||
134 | if (!APR_STATUS_IS_EBUSY(s)) | ||
135 | { | ||
136 | break; | ||
137 | } | ||
138 | else | ||
139 | { | ||
140 | attempts++; | ||
141 | ms_sleep(1); | ||
142 | |||
143 | // | ||
144 | // Just yielding won't necessarily work, I had problems with this on Linux - doug 12/02/04 | ||
145 | //apr_thread_yield(); | ||
146 | } | ||
147 | } | ||
148 | if (attempts == MAX_RETRIES) | ||
149 | { | ||
150 | // We're hosed, we can't get the mutex. | ||
151 | // I guess we just won't log, then. Blah. | ||
152 | fprintf(stderr, "LLErrorStream::crashOnError() failed to get mutex for log\n"); | ||
153 | return; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | mErrorBuffer->setPriority(l); | ||
158 | if (LLErrorBuffer::FATAL == l) | ||
159 | { | ||
160 | setError(); | ||
161 | } | ||
162 | |||
163 | *this << oss.str(); | ||
164 | |||
165 | if (mKill) | ||
166 | { | ||
167 | // We want to flush this stream. | ||
168 | flush(); | ||
169 | } | ||
170 | |||
171 | BOOL crashme = FALSE; | ||
172 | if (mKill) | ||
173 | { | ||
174 | crashme = TRUE; | ||
175 | } | ||
176 | mKill = FALSE; | ||
177 | |||
178 | if (gLogMutexp) | ||
179 | { | ||
180 | apr_thread_mutex_unlock(gLogMutexp); | ||
181 | } | ||
182 | |||
183 | if (crashme) | ||
184 | { | ||
185 | mErrorCallback(oss.str()); | ||
186 | _llcrash_and_loop(); | ||
187 | } | ||
188 | } | ||
diff --git a/linden/indra/llcommon/llerrorstream.h b/linden/indra/llcommon/llerrorstream.h deleted file mode 100644 index 4028583..0000000 --- a/linden/indra/llcommon/llerrorstream.h +++ /dev/null | |||
@@ -1,126 +0,0 @@ | |||
1 | /** | ||
2 | * @file llerrorstream.h | ||
3 | * @brief Declaration of c++ log straming. | ||
4 | * | ||
5 | * Copyright (c) 2002-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 | #ifndef LL_LLERRORSTREAM_H | ||
29 | #define LL_LLERRORSTREAM_H | ||
30 | |||
31 | // Usage: | ||
32 | // LLErrorStream gErrorStream(gErrorBuffer); | ||
33 | // | ||
34 | // gErrorStream << debug << "This is a debug message" << endl; | ||
35 | // | ||
36 | // gErrorStream << fatal << "This message will cause a crash!" << endl; | ||
37 | |||
38 | #include <iostream> | ||
39 | #include "llerrorbuffer.h" | ||
40 | #include "stdtypes.h" | ||
41 | |||
42 | class LLFixedBuffer; | ||
43 | |||
44 | class LLErrorStream : public std::ostream | ||
45 | { | ||
46 | public: | ||
47 | LLErrorStream(LLErrorBuffer *eb); | ||
48 | |||
49 | // Specify error levels-- Use LLErrorBuffer::ELevel instead | ||
50 | enum ELevel | ||
51 | { | ||
52 | DEBUG = 0, | ||
53 | INFO = 1, | ||
54 | WARN = 2, | ||
55 | FATAL = 3, | ||
56 | NONE = 4 // Don't log anything | ||
57 | }; | ||
58 | |||
59 | LLErrorBuffer *mErrorBuffer; | ||
60 | |||
61 | // This is used to specify if we need to merge the DebugMask | ||
62 | // or replace it | ||
63 | enum EControl | ||
64 | { | ||
65 | REPLACE = 0, | ||
66 | MERGE = 1 | ||
67 | }; | ||
68 | |||
69 | void setDebugMask(U32 mask) { mDebugMask = mask; } | ||
70 | void mergeDebugMask(U32 mask) { mDebugMask |= mask; } | ||
71 | U32 getDebugMask() { return mDebugMask; } | ||
72 | void setDebugFlag(U32 flag) { mDebugMask |= flag; } | ||
73 | void clearDebugFlag(U32 flag) { mDebugMask &= ~flag; } | ||
74 | BOOL setFile(const char *path) { return mErrorBuffer->setFile(path); } | ||
75 | void closeFile() { mErrorBuffer->closeFile(); } | ||
76 | const char *getFilename() const { return mErrorBuffer->getFilename(); } | ||
77 | void setFixedBuffer(LLFixedBuffer *b) { mErrorBuffer->setFixedBuffer(b); } | ||
78 | void setErrorLevel(const LLErrorBuffer::ELevel l) { mErrorBuffer->setLevel(l); } | ||
79 | LLErrorBuffer::ELevel getErrorLevel() { return mErrorBuffer->getLevel(); } | ||
80 | void mergeErrorLevel(const LLErrorBuffer::ELevel l) { mErrorBuffer->mergeLevel(l); } | ||
81 | void setError() { mKill = TRUE; }; | ||
82 | void crashOnError(std::ostringstream &ss, LLErrorBuffer::ELevel l); | ||
83 | |||
84 | BOOL isEnabledFor(const LLErrorBuffer::ELevel l); | ||
85 | BOOL isEnabledFor(const LLErrorBuffer::ELevel l, const U32 type); | ||
86 | |||
87 | |||
88 | void mergeLevel(const LLErrorBuffer::ELevel l) { mErrorBuffer->mergeLevel(l); } | ||
89 | |||
90 | void setPrintLocation(BOOL b) { mPrintLocation = b; } | ||
91 | BOOL getPrintLocation() { return mPrintLocation; } | ||
92 | |||
93 | void setElevatedRemote(BOOL b) { mErrorBuffer->setElevatedRemote(b); } | ||
94 | void setUTCTimestamp(BOOL utc) { mErrorBuffer->setUTCTimestamp(utc); } | ||
95 | |||
96 | // Deprecated | ||
97 | void setLevel(const ELevel l) { setErrorLevel(ELevelToBufferELevel(l)); } | ||
98 | ELevel getLevel() { return BufferELevelToELevel(getErrorLevel()); } | ||
99 | void mergeLevel(const ELevel l) { mergeErrorLevel(ELevelToBufferELevel(l)); } | ||
100 | |||
101 | |||
102 | // Backwards compatilibity cruft. Should be removed | ||
103 | void mergeTime(BOOL b) { } // NOP | ||
104 | void mergeLocation(BOOL b) { } // NOP | ||
105 | void setTime(BOOL b) { } // NOP | ||
106 | char *getTime() { return ""; } // NOP | ||
107 | |||
108 | typedef void(*LLErrorCallback)(const std::string &error_string); | ||
109 | void setErrorCallback(LLErrorCallback callback) {mErrorCallback = callback;} | ||
110 | |||
111 | private: | ||
112 | // This maintains the existing ELevel interface, but new code should use | ||
113 | // LLErrorBuffer::ELevel instead. | ||
114 | LLErrorBuffer::ELevel ELevelToBufferELevel(const ELevel l); | ||
115 | ELevel BufferELevelToELevel(const LLErrorBuffer::ELevel l); | ||
116 | U32 mDebugMask; // Mask for debugst() output | ||
117 | |||
118 | BOOL mPrintLocation; | ||
119 | |||
120 | S32 mSafeDepth; // Counter so we can safely do recursive calls, 0 means we're OK | ||
121 | BOOL mKill; | ||
122 | LLErrorCallback mErrorCallback; | ||
123 | }; | ||
124 | |||
125 | |||
126 | #endif // LL_LLERRORSTREAM_H | ||
diff --git a/linden/indra/llcommon/llevent.cpp b/linden/indra/llcommon/llevent.cpp index e9b6a51..bbb37c5 100644 --- a/linden/indra/llcommon/llevent.cpp +++ b/linden/indra/llcommon/llevent.cpp | |||
@@ -186,16 +186,14 @@ void LLSimpleDispatcher::addListener(LLEventListener* listener, LLSD filter, con | |||
186 | 186 | ||
187 | void LLSimpleDispatcher::removeListener(LLEventListener* listener) | 187 | void LLSimpleDispatcher::removeListener(LLEventListener* listener) |
188 | { | 188 | { |
189 | std::vector<LLListenerEntry>::iterator itor; | 189 | std::vector<LLListenerEntry>::iterator itor = mListeners.begin(); |
190 | for (itor=mListeners.begin(); itor!=mListeners.end();) | 190 | std::vector<LLListenerEntry>::iterator end = mListeners.end(); |
191 | for (; itor != end; ++itor) | ||
191 | { | 192 | { |
192 | if ((*itor).listener == listener) | 193 | if ((*itor).listener == listener) |
193 | { | 194 | { |
194 | mListeners.erase(itor); | 195 | mListeners.erase(itor); |
195 | } | 196 | break; |
196 | else | ||
197 | { | ||
198 | ++itor; | ||
199 | } | 197 | } |
200 | } | 198 | } |
201 | listener->handleDetach(mParent); | 199 | listener->handleDetach(mParent); |
diff --git a/linden/indra/llcommon/llevent.h b/linden/indra/llcommon/llevent.h index c48817e..bcb6ee9 100644 --- a/linden/indra/llcommon/llevent.h +++ b/linden/indra/llcommon/llevent.h | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include "llsd.h" | 32 | #include "llsd.h" |
33 | #include "llmemory.h" | 33 | #include "llmemory.h" |
34 | #include "llthread.h" | ||
34 | 35 | ||
35 | class LLEventListener; | 36 | class LLEventListener; |
36 | class LLEvent; | 37 | class LLEvent; |
@@ -128,6 +129,7 @@ public: | |||
128 | 129 | ||
129 | // Adds a listener to this dispatcher, with a given user data | 130 | // Adds a listener to this dispatcher, with a given user data |
130 | // that will be passed to the listener when an event is fired. | 131 | // that will be passed to the listener when an event is fired. |
132 | // Duplicate pointers are removed on addtion. | ||
131 | void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata); | 133 | void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata); |
132 | 134 | ||
133 | // Removes a listener from this dispatcher | 135 | // Removes a listener from this dispatcher |
diff --git a/linden/indra/llcommon/llfasttimer.h b/linden/indra/llcommon/llfasttimer.h index b5e0734..47634ac 100644 --- a/linden/indra/llcommon/llfasttimer.h +++ b/linden/indra/llcommon/llfasttimer.h | |||
@@ -44,6 +44,7 @@ public: | |||
44 | FTM_UPDATE, | 44 | FTM_UPDATE, |
45 | FTM_RENDER, | 45 | FTM_RENDER, |
46 | FTM_SWAP, | 46 | FTM_SWAP, |
47 | FTM_CLIENT_COPY, | ||
47 | FTM_IDLE, | 48 | FTM_IDLE, |
48 | FTM_SLEEP, | 49 | FTM_SLEEP, |
49 | 50 | ||
@@ -56,13 +57,23 @@ public: | |||
56 | FTM_UPDATE_TERRAIN, | 57 | FTM_UPDATE_TERRAIN, |
57 | FTM_UPDATE_PRIMITIVES, | 58 | FTM_UPDATE_PRIMITIVES, |
58 | FTM_UPDATE_PARTICLES, | 59 | FTM_UPDATE_PARTICLES, |
60 | FTM_SIMULATE_PARTICLES, | ||
59 | FTM_UPDATE_SKY, | 61 | FTM_UPDATE_SKY, |
60 | FTM_UPDATE_TEXTURES, | 62 | FTM_UPDATE_TEXTURES, |
63 | FTM_UPDATE_WATER, | ||
64 | FTM_UPDATE_CLOUDS, | ||
65 | FTM_UPDATE_GRASS, | ||
66 | FTM_UPDATE_TREE, | ||
67 | FTM_UPDATE_AVATAR, | ||
61 | 68 | ||
62 | // common render components | 69 | // common render components |
63 | FTM_RENDER_GEOMETRY, | 70 | FTM_RENDER_GEOMETRY, |
64 | FTM_RENDER_TERRAIN, | 71 | FTM_RENDER_TERRAIN, |
65 | FTM_RENDER_SIMPLE, | 72 | FTM_RENDER_SIMPLE, |
73 | FTM_RENDER_FULLBRIGHT, | ||
74 | FTM_RENDER_GLOW, | ||
75 | FTM_RENDER_GRASS, | ||
76 | FTM_RENDER_INVISIBLE, | ||
66 | FTM_RENDER_SHINY, | 77 | FTM_RENDER_SHINY, |
67 | FTM_RENDER_BUMP, | 78 | FTM_RENDER_BUMP, |
68 | FTM_RENDER_TREES, | 79 | FTM_RENDER_TREES, |
@@ -81,6 +92,20 @@ public: | |||
81 | FTM_MESSAGES, | 92 | FTM_MESSAGES, |
82 | FTM_REBUILD, | 93 | FTM_REBUILD, |
83 | FTM_STATESORT, | 94 | FTM_STATESORT, |
95 | FTM_STATESORT_DRAWABLE, | ||
96 | FTM_STATESORT_POSTSORT, | ||
97 | FTM_REBUILD_VBO, | ||
98 | FTM_REBUILD_VOLUME_VB, | ||
99 | FTM_REBUILD_BRIDGE_VB, | ||
100 | FTM_REBUILD_HUD_VB, | ||
101 | FTM_REBUILD_TERRAIN_VB, | ||
102 | FTM_REBUILD_WATER_VB, | ||
103 | FTM_REBUILD_TREE_VB, | ||
104 | FTM_REBUILD_PARTICLE_VB, | ||
105 | FTM_REBUILD_CLOUD_VB, | ||
106 | FTM_REBUILD_GRASS_VB, | ||
107 | FTM_REBUILD_NONE_VB, | ||
108 | FTM_REBUILD_OCCLUSION_VB, | ||
84 | FTM_POOLS, | 109 | FTM_POOLS, |
85 | FTM_POOLRENDER, | 110 | FTM_POOLRENDER, |
86 | FTM_IDLE_CB, | 111 | FTM_IDLE_CB, |
@@ -90,6 +115,7 @@ public: | |||
90 | FTM_UPDATE_LIGHTS, | 115 | FTM_UPDATE_LIGHTS, |
91 | FTM_CULL, | 116 | FTM_CULL, |
92 | FTM_CULL_REBOUND, | 117 | FTM_CULL_REBOUND, |
118 | FTM_FRUSTUM_CULL, | ||
93 | FTM_GEO_UPDATE, | 119 | FTM_GEO_UPDATE, |
94 | FTM_GEO_RESERVE, | 120 | FTM_GEO_RESERVE, |
95 | FTM_GEO_LIGHT, | 121 | FTM_GEO_LIGHT, |
@@ -116,6 +142,7 @@ public: | |||
116 | FTM_IMAGE_UPDATE, | 142 | FTM_IMAGE_UPDATE, |
117 | FTM_IMAGE_CREATE, | 143 | FTM_IMAGE_CREATE, |
118 | FTM_IMAGE_DECODE, | 144 | FTM_IMAGE_DECODE, |
145 | FTM_IMAGE_MARK_DIRTY, | ||
119 | FTM_PIPELINE, | 146 | FTM_PIPELINE, |
120 | FTM_VFILE_WAIT, | 147 | FTM_VFILE_WAIT, |
121 | FTM_FLEXIBLE_UPDATE, | 148 | FTM_FLEXIBLE_UPDATE, |
diff --git a/linden/indra/llcommon/llfile.cpp b/linden/indra/llcommon/llfile.cpp index d9fd360..feac28f 100644 --- a/linden/indra/llcommon/llfile.cpp +++ b/linden/indra/llcommon/llfile.cpp | |||
@@ -48,6 +48,19 @@ int LLFile::mkdir(const char* dirname, int perms) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | // static | 50 | // static |
51 | int LLFile::rmdir(const char* dirname) | ||
52 | { | ||
53 | #if LL_WINDOWS | ||
54 | // permissions are ignored on Windows | ||
55 | std::string utf8dirname = dirname; | ||
56 | llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname); | ||
57 | return _wrmdir(utf16dirname.c_str()); | ||
58 | #else | ||
59 | return ::rmdir(dirname); | ||
60 | #endif | ||
61 | } | ||
62 | |||
63 | // static | ||
51 | LLFILE* LLFile::fopen(const char* filename, const char* mode) /* Flawfinder: ignore */ | 64 | LLFILE* LLFile::fopen(const char* filename, const char* mode) /* Flawfinder: ignore */ |
52 | { | 65 | { |
53 | #if LL_WINDOWS | 66 | #if LL_WINDOWS |
@@ -184,9 +197,9 @@ void llifstream::close() | |||
184 | } | 197 | } |
185 | } | 198 | } |
186 | 199 | ||
187 | void llifstream::open(const char *_Filename, | 200 | void llifstream::open(const char* _Filename, /* Flawfinder: ignore */ |
188 | ios_base::openmode _Mode, | 201 | ios_base::openmode _Mode, |
189 | int _Prot) /* Flawfinder: ignore */ | 202 | int _Prot) |
190 | { // open a C stream with specified mode | 203 | { // open a C stream with specified mode |
191 | 204 | ||
192 | FILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot); | 205 | FILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot); |
@@ -197,6 +210,7 @@ void llifstream::open(const char *_Filename, | |||
197 | } | 210 | } |
198 | llassert(_Filebuffer == NULL); | 211 | llassert(_Filebuffer == NULL); |
199 | _Filebuffer = new _Myfb(filep); | 212 | _Filebuffer = new _Myfb(filep); |
213 | _ShouldClose = true; | ||
200 | _Myios::init(_Filebuffer); | 214 | _Myios::init(_Filebuffer); |
201 | } | 215 | } |
202 | 216 | ||
@@ -208,13 +222,17 @@ bool llifstream::is_open() const | |||
208 | } | 222 | } |
209 | llifstream::~llifstream() | 223 | llifstream::~llifstream() |
210 | { | 224 | { |
225 | if (_ShouldClose) | ||
226 | { | ||
227 | close(); | ||
228 | } | ||
211 | delete _Filebuffer; | 229 | delete _Filebuffer; |
212 | } | 230 | } |
213 | 231 | ||
214 | llifstream::llifstream(const char *_Filename, | 232 | llifstream::llifstream(const char *_Filename, |
215 | ios_base::openmode _Mode, | 233 | ios_base::openmode _Mode, |
216 | int _Prot) | 234 | int _Prot) |
217 | : std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL) | 235 | : std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) |
218 | 236 | ||
219 | { // construct with named file and specified mode | 237 | { // construct with named file and specified mode |
220 | open(_Filename, _Mode | ios_base::in, _Prot); /* Flawfinder: ignore */ | 238 | open(_Filename, _Mode | ios_base::in, _Prot); /* Flawfinder: ignore */ |
@@ -230,9 +248,9 @@ bool llofstream::is_open() const | |||
230 | return false; | 248 | return false; |
231 | } | 249 | } |
232 | 250 | ||
233 | void llofstream::open(const char *_Filename, | 251 | void llofstream::open(const char* _Filename, /* Flawfinder: ignore */ |
234 | ios_base::openmode _Mode, | 252 | ios_base::openmode _Mode, |
235 | int _Prot) /* Flawfinder: ignore */ | 253 | int _Prot) |
236 | { // open a C stream with specified mode | 254 | { // open a C stream with specified mode |
237 | 255 | ||
238 | FILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot); | 256 | FILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot); |
diff --git a/linden/indra/llcommon/llfile.h b/linden/indra/llcommon/llfile.h index 554308f..5034cf7 100644 --- a/linden/indra/llcommon/llfile.h +++ b/linden/indra/llcommon/llfile.h | |||
@@ -69,6 +69,7 @@ public: | |||
69 | // be overridden by the user's umask. It is ignored on Windows. | 69 | // be overridden by the user's umask. It is ignored on Windows. |
70 | static int mkdir(const char* filename, int perms = 0700); | 70 | static int mkdir(const char* filename, int perms = 0700); |
71 | 71 | ||
72 | static int rmdir(const char* filename); | ||
72 | static int remove(const char* filename); | 73 | static int remove(const char* filename); |
73 | static int rename(const char* filename,const char* newname); | 74 | static int rename(const char* filename,const char* newname); |
74 | static int stat(const char* filename,llstat* file_status); | 75 | static int stat(const char* filename,llstat* file_status); |
@@ -87,7 +88,7 @@ public: | |||
87 | typedef std::basic_ios<char,std::char_traits< char > > _Myios; | 88 | typedef std::basic_ios<char,std::char_traits< char > > _Myios; |
88 | 89 | ||
89 | llifstream() | 90 | llifstream() |
90 | : std::basic_istream<char,std::char_traits< char > >(NULL,true),_Filebuffer(NULL) | 91 | : std::basic_istream<char,std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) |
91 | { // construct unopened | 92 | { // construct unopened |
92 | } | 93 | } |
93 | 94 | ||
@@ -97,7 +98,8 @@ public: | |||
97 | 98 | ||
98 | explicit llifstream(_Filet *_File) | 99 | explicit llifstream(_Filet *_File) |
99 | : std::basic_istream<char,std::char_traits< char > >(NULL,true), | 100 | : std::basic_istream<char,std::char_traits< char > >(NULL,true), |
100 | _Filebuffer(new _Myfb(_File)) | 101 | _Filebuffer(new _Myfb(_File)), |
102 | _ShouldClose(false) | ||
101 | { // construct with specified C stream | 103 | { // construct with specified C stream |
102 | } | 104 | } |
103 | virtual ~llifstream(); | 105 | virtual ~llifstream(); |
@@ -107,13 +109,14 @@ public: | |||
107 | return _Filebuffer; | 109 | return _Filebuffer; |
108 | } | 110 | } |
109 | bool is_open() const; | 111 | bool is_open() const; |
110 | void open(const char *_Filename, | 112 | void open(const char* _Filename, /* Flawfinder: ignore */ |
111 | ios_base::openmode _Mode = ios_base::in, | 113 | ios_base::openmode _Mode = ios_base::in, |
112 | int _Prot = (int)ios_base::_Openprot); /* Flawfinder: ignore */ | 114 | int _Prot = (int)ios_base::_Openprot); |
113 | void close(); | 115 | void close(); |
114 | 116 | ||
115 | private: | 117 | private: |
116 | _Myfb* _Filebuffer; // the file buffer | 118 | _Myfb* _Filebuffer; // the file buffer |
119 | bool _ShouldClose; | ||
117 | }; | 120 | }; |
118 | 121 | ||
119 | 122 | ||
diff --git a/linden/indra/llcommon/llformat.cpp b/linden/indra/llcommon/llformat.cpp new file mode 100644 index 0000000..f088bc6 --- /dev/null +++ b/linden/indra/llcommon/llformat.cpp | |||
@@ -0,0 +1,47 @@ | |||
1 | /** | ||
2 | * @file llformat.cpp | ||
3 | * @date January 2007 | ||
4 | * @brief string formatting utility | ||
5 | * | ||
6 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #include "llformat.h" | ||
32 | |||
33 | #include <stdarg.h> | ||
34 | |||
35 | std::string llformat(const char *fmt, ...) | ||
36 | { | ||
37 | char tstr[1024]; /* Flawfinder: ignore */ | ||
38 | va_list va; | ||
39 | va_start(va, fmt); | ||
40 | #if LL_WINDOWS | ||
41 | _vsnprintf(tstr, 1024, fmt, va); | ||
42 | #else | ||
43 | vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */ | ||
44 | #endif | ||
45 | va_end(va); | ||
46 | return std::string(tstr); | ||
47 | } | ||
diff --git a/linden/indra/llcommon/llformat.h b/linden/indra/llcommon/llformat.h new file mode 100644 index 0000000..135f9d2 --- /dev/null +++ b/linden/indra/llcommon/llformat.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /** | ||
2 | * @file llformat.h | ||
3 | * @date January 2007 | ||
4 | * @brief string formatting utility | ||
5 | * | ||
6 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #ifndef LL_LLFORMAT_H | ||
30 | #define LL_LLFORMAT_H | ||
31 | |||
32 | #include <string> | ||
33 | |||
34 | // Use as follows: | ||
35 | // llinfos << llformat("Test:%d (%.2f %.2f)", idx, x, y) << llendl; | ||
36 | // | ||
37 | // *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun) | ||
38 | // should perhaps be replaced with boost::format. | ||
39 | |||
40 | std::string llformat(const char *fmt, ...); | ||
41 | |||
42 | #endif // LL_LLFORMAT_H | ||
diff --git a/linden/indra/llcommon/llliveappconfig.cpp b/linden/indra/llcommon/llliveappconfig.cpp new file mode 100644 index 0000000..bcffa7c --- /dev/null +++ b/linden/indra/llcommon/llliveappconfig.cpp | |||
@@ -0,0 +1,65 @@ | |||
1 | /** | ||
2 | * @file llliveappconfig.cpp | ||
3 | * @brief Configuration information for an LLApp that overrides indra.xml | ||
4 | * | ||
5 | * Copyright (c) 2003-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 | |||
30 | #include "llliveappconfig.h" | ||
31 | |||
32 | #include "llapp.h" | ||
33 | #include "llsd.h" | ||
34 | #include "llsdserialize.h" | ||
35 | |||
36 | LLLiveAppConfig::LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period) | ||
37 | : LLLiveFile(filename, refresh_period), | ||
38 | mApp(app) | ||
39 | { } | ||
40 | |||
41 | |||
42 | LLLiveAppConfig::~LLLiveAppConfig() | ||
43 | { } | ||
44 | |||
45 | // virtual | ||
46 | void LLLiveAppConfig::loadFile() | ||
47 | { | ||
48 | llinfos << "LLLiveAppConfig::loadFile(): reading from " | ||
49 | << filename() << llendl; | ||
50 | llifstream file(filename().c_str()); | ||
51 | LLSD config; | ||
52 | if (file.is_open()) | ||
53 | { | ||
54 | LLSDSerialize::fromXML(config, file); | ||
55 | if(!config.isMap()) | ||
56 | { | ||
57 | llinfos << "LLDataserverConfig::loadFile(): not an map!" | ||
58 | << " Ignoring the data." << llendl; | ||
59 | return; | ||
60 | } | ||
61 | file.close(); | ||
62 | } | ||
63 | mApp->setOptionData( | ||
64 | LLApp::PRIORITY_SPECIFIC_CONFIGURATION, config); | ||
65 | } | ||
diff --git a/linden/indra/newview/lldrawpooltreenew.h b/linden/indra/llcommon/llliveappconfig.h index 9150331..822410f 100644 --- a/linden/indra/newview/lldrawpooltreenew.h +++ b/linden/indra/llcommon/llliveappconfig.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /** | 1 | /** |
2 | * @file lldrawpooltreenew.h | 2 | * @file llliveappconfig.h |
3 | * @brief LLDrawPoolTreeNew class definition | 3 | * @brief Configuration information for an LLApp that overrides indra.xml |
4 | * | 4 | * |
5 | * Copyright (c) 2003-2007, Linden Research, Inc. | 5 | * Copyright (c) 2003-2007, Linden Research, Inc. |
6 | * | 6 | * |
@@ -25,31 +25,28 @@ | |||
25 | * COMPLETENESS OR PERFORMANCE. | 25 | * COMPLETENESS OR PERFORMANCE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #ifndef LL_LLDRAWPOOLTREENEW_H | 28 | #ifndef LLLIVEAPPCONFIG_H |
29 | #define LL_LLDRAWPOOLTREENEW_H | 29 | #define LLLIVEAPPCONFIG_H |
30 | 30 | ||
31 | #include "lldrawpool.h" | 31 | #include "lllivefile.h" |
32 | 32 | ||
33 | class LLDrawPoolTreeNew : public LLDrawPool | 33 | class LLApp; |
34 | |||
35 | class LLLiveAppConfig : public LLLiveFile | ||
34 | { | 36 | { |
35 | LLPointer<LLViewerImage> mTexturep; | ||
36 | public: | 37 | public: |
37 | LLDrawPoolTreeNew(LLViewerImage *texturep); | 38 | // To use this, instantiate a LLLiveAppConfig object inside your main loop. |
39 | // The traditional name for it is live_config. | ||
40 | // Be sure to call live_config.checkAndReload() periodically. | ||
38 | 41 | ||
39 | /*virtual*/ LLDrawPool *instancePool(); | 42 | LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period); |
43 | ~LLLiveAppConfig(); | ||
40 | 44 | ||
41 | /*virtual*/ void prerender(); | 45 | protected: |
42 | /*virtual*/ void render( S32 pass ); | 46 | /*virtual*/ void loadFile(); |
43 | /*virtual*/ void renderForSelect(); | ||
44 | /*virtual*/ S32 rebuild(); | ||
45 | /*virtual*/ BOOL verify() const; | ||
46 | /*virtual*/ LLViewerImage *getTexture(); | ||
47 | /*virtual*/ LLViewerImage *getDebugTexture(); | ||
48 | /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display | ||
49 | virtual S32 getMaterialAttribIndex() { return 0; } | ||
50 | 47 | ||
51 | private: | 48 | private: |
52 | void renderTree(BOOL selecting = FALSE); | 49 | LLApp* mApp; |
53 | }; | 50 | }; |
54 | 51 | ||
55 | #endif // LL_LLDRAWPOOLTREE_H | 52 | #endif |
diff --git a/linden/indra/llcommon/lllivefile.cpp b/linden/indra/llcommon/lllivefile.cpp index 33e2014..d289671 100644 --- a/linden/indra/llcommon/lllivefile.cpp +++ b/linden/indra/llcommon/lllivefile.cpp | |||
@@ -27,24 +27,56 @@ | |||
27 | #include "linden_common.h" | 27 | #include "linden_common.h" |
28 | 28 | ||
29 | #include "lllivefile.h" | 29 | #include "lllivefile.h" |
30 | #include "llframetimer.h" | ||
31 | #include "lltimer.h" | ||
30 | 32 | ||
33 | class LLLiveFile::Impl | ||
34 | { | ||
35 | public: | ||
36 | Impl(const std::string &filename, const F32 refresh_period); | ||
37 | ~Impl(); | ||
38 | |||
39 | bool check(); | ||
40 | |||
41 | |||
42 | bool mForceCheck; | ||
43 | F32 mRefreshPeriod; | ||
44 | LLFrameTimer mRefreshTimer; | ||
31 | 45 | ||
32 | LLLiveFile::LLLiveFile(const std::string &filename, const F32 refresh_period) : | 46 | std::string mFilename; |
33 | mForceCheck(true), | 47 | time_t mLastModTime; |
34 | mRefreshPeriod(refresh_period), | 48 | bool mLastExists; |
35 | mFilename(filename), | 49 | |
36 | mLastModTime(0), | 50 | LLEventTimer* mEventTimer; |
37 | mLastExists(false) | 51 | }; |
52 | |||
53 | LLLiveFile::Impl::Impl(const std::string &filename, const F32 refresh_period) | ||
54 | : mForceCheck(true), | ||
55 | mRefreshPeriod(refresh_period), | ||
56 | mFilename(filename), | ||
57 | mLastModTime(0), | ||
58 | mLastExists(false), | ||
59 | mEventTimer(NULL) | ||
38 | { | 60 | { |
39 | } | 61 | } |
40 | 62 | ||
63 | LLLiveFile::Impl::~Impl() | ||
64 | { | ||
65 | delete mEventTimer; | ||
66 | } | ||
67 | |||
68 | LLLiveFile::LLLiveFile(const std::string &filename, const F32 refresh_period) | ||
69 | : impl(* new Impl(filename, refresh_period)) | ||
70 | { | ||
71 | } | ||
41 | 72 | ||
42 | LLLiveFile::~LLLiveFile() | 73 | LLLiveFile::~LLLiveFile() |
43 | { | 74 | { |
75 | delete &impl; | ||
44 | } | 76 | } |
45 | 77 | ||
46 | 78 | ||
47 | bool LLLiveFile::checkAndReload() | 79 | bool LLLiveFile::Impl::check() |
48 | { | 80 | { |
49 | if (!mForceCheck && mRefreshTimer.getElapsedTimeF32() < mRefreshPeriod) | 81 | if (!mForceCheck && mRefreshTimer.getElapsedTimeF32() < mRefreshPeriod) |
50 | { | 82 | { |
@@ -65,9 +97,8 @@ bool LLLiveFile::checkAndReload() | |||
65 | // broken somehow. Clear flags and return. | 97 | // broken somehow. Clear flags and return. |
66 | if (mLastExists) | 98 | if (mLastExists) |
67 | { | 99 | { |
68 | loadFile(); // Load the file, even though it's missing to allow it to clear state. | ||
69 | mLastExists = false; | 100 | mLastExists = false; |
70 | return true; | 101 | return true; // no longer existing is a change! |
71 | } | 102 | } |
72 | return false; | 103 | return false; |
73 | } | 104 | } |
@@ -87,7 +118,44 @@ bool LLLiveFile::checkAndReload() | |||
87 | mLastExists = true; | 118 | mLastExists = true; |
88 | mLastModTime = stat_data.st_mtime; | 119 | mLastModTime = stat_data.st_mtime; |
89 | 120 | ||
90 | loadFile(); | ||
91 | return true; | 121 | return true; |
92 | } | 122 | } |
93 | 123 | ||
124 | bool LLLiveFile::checkAndReload() | ||
125 | { | ||
126 | bool changed = impl.check(); | ||
127 | if (changed) | ||
128 | { | ||
129 | loadFile(); | ||
130 | } | ||
131 | return changed; | ||
132 | } | ||
133 | |||
134 | std::string LLLiveFile::filename() const | ||
135 | { | ||
136 | return impl.mFilename; | ||
137 | } | ||
138 | |||
139 | namespace | ||
140 | { | ||
141 | class LiveFileEventTimer : public LLEventTimer | ||
142 | { | ||
143 | public: | ||
144 | LiveFileEventTimer(LLLiveFile& f, F32 refresh) | ||
145 | : LLEventTimer(refresh), mLiveFile(f) | ||
146 | { } | ||
147 | |||
148 | void tick() | ||
149 | { mLiveFile.checkAndReload(); } | ||
150 | |||
151 | private: | ||
152 | LLLiveFile& mLiveFile; | ||
153 | }; | ||
154 | |||
155 | } | ||
156 | |||
157 | void LLLiveFile::addToEventTimer() | ||
158 | { | ||
159 | impl.mEventTimer = new LiveFileEventTimer(*this, impl.mRefreshPeriod); | ||
160 | } | ||
161 | |||
diff --git a/linden/indra/llcommon/lllivefile.h b/linden/indra/llcommon/lllivefile.h index b305531..fbf2bdf 100644 --- a/linden/indra/llcommon/lllivefile.h +++ b/linden/indra/llcommon/lllivefile.h | |||
@@ -28,7 +28,6 @@ | |||
28 | #ifndef LL_LLLIVEFILE_H | 28 | #ifndef LL_LLLIVEFILE_H |
29 | #define LL_LLLIVEFILE_H | 29 | #define LL_LLLIVEFILE_H |
30 | 30 | ||
31 | #include "llframetimer.h" | ||
32 | 31 | ||
33 | class LLLiveFile | 32 | class LLLiveFile |
34 | { | 33 | { |
@@ -36,18 +35,22 @@ public: | |||
36 | LLLiveFile(const std::string &filename, const F32 refresh_period = 5.f); | 35 | LLLiveFile(const std::string &filename, const F32 refresh_period = 5.f); |
37 | virtual ~LLLiveFile(); | 36 | virtual ~LLLiveFile(); |
38 | 37 | ||
39 | bool checkAndReload(); // Returns true if the file changed in any way | 38 | bool checkAndReload(); |
39 | // Returns true if the file changed in any way | ||
40 | // Call this before using anything that was read & cached from the file | ||
41 | |||
42 | std::string filename() const; | ||
43 | |||
44 | void addToEventTimer(); | ||
45 | // Normally, just calling checkAndReload() is enough. In some cases | ||
46 | // though, you may need to let the live file periodically check itself. | ||
40 | 47 | ||
41 | protected: | 48 | protected: |
42 | virtual void loadFile() = 0; // Implement this to load your file if it changed | 49 | virtual void loadFile() = 0; // Implement this to load your file if it changed |
43 | 50 | ||
44 | bool mForceCheck; | 51 | private: |
45 | F32 mRefreshPeriod; | 52 | class Impl; |
46 | LLFrameTimer mRefreshTimer; | 53 | Impl& impl; |
47 | |||
48 | std::string mFilename; | ||
49 | time_t mLastModTime; | ||
50 | bool mLastExists; | ||
51 | }; | 54 | }; |
52 | 55 | ||
53 | #endif //LL_LLLIVEFILE_H | 56 | #endif //LL_LLLIVEFILE_H |
diff --git a/linden/indra/llcommon/lllslconstants.h b/linden/indra/llcommon/lllslconstants.h index 52d2858..08c63e3 100644 --- a/linden/indra/llcommon/lllslconstants.h +++ b/linden/indra/llcommon/lllslconstants.h | |||
@@ -155,4 +155,8 @@ const S32 LIST_STAT_SUM_SQUARES = 7; | |||
155 | const S32 LIST_STAT_NUM_COUNT = 8; | 155 | const S32 LIST_STAT_NUM_COUNT = 8; |
156 | const S32 LIST_STAT_GEO_MEAN = 9; | 156 | const S32 LIST_STAT_GEO_MEAN = 9; |
157 | 157 | ||
158 | const S32 STRING_TRIM_HEAD = 0x01; | ||
159 | const S32 STRING_TRIM_TAIL = 0x02; | ||
160 | const S32 STRING_TRIM = STRING_TRIM_HEAD | STRING_TRIM_TAIL; | ||
161 | |||
158 | #endif | 162 | #endif |
diff --git a/linden/indra/llcommon/llmemory.cpp b/linden/indra/llcommon/llmemory.cpp index 9bfbf88..8528433 100644 --- a/linden/indra/llcommon/llmemory.cpp +++ b/linden/indra/llcommon/llmemory.cpp | |||
@@ -28,6 +28,12 @@ | |||
28 | #include "linden_common.h" | 28 | #include "linden_common.h" |
29 | 29 | ||
30 | #include "llmemory.h" | 30 | #include "llmemory.h" |
31 | #include "llmemtype.h" | ||
32 | |||
33 | // not defining nullfunc will currently crash when trying to use a LLHandle | ||
34 | template< typename _Ty > | ||
35 | const typename LLHandle< _Ty >::NullFunc | ||
36 | LLHandle< _Ty >::sNullFunc = LLHandle< _Ty >::defaultNullFunc; | ||
31 | 37 | ||
32 | //---------------------------------------------------------------------------- | 38 | //---------------------------------------------------------------------------- |
33 | 39 | ||
@@ -258,43 +264,6 @@ void operator delete[] (void *p) | |||
258 | 264 | ||
259 | //---------------------------------------------------------------------------- | 265 | //---------------------------------------------------------------------------- |
260 | 266 | ||
261 | //static | ||
262 | LLMutex* LLThreadSafeRefCount::sMutex = 0; | ||
263 | |||
264 | //static | ||
265 | void LLThreadSafeRefCount::initClass() | ||
266 | { | ||
267 | if (!sMutex) | ||
268 | { | ||
269 | sMutex = new LLMutex(0); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | //static | ||
274 | void LLThreadSafeRefCount::cleanupClass() | ||
275 | { | ||
276 | delete sMutex; | ||
277 | sMutex = NULL; | ||
278 | } | ||
279 | |||
280 | |||
281 | //---------------------------------------------------------------------------- | ||
282 | |||
283 | LLThreadSafeRefCount::LLThreadSafeRefCount() : | ||
284 | mRef(0) | ||
285 | { | ||
286 | } | ||
287 | |||
288 | LLThreadSafeRefCount::~LLThreadSafeRefCount() | ||
289 | { | ||
290 | if (mRef != 0) | ||
291 | { | ||
292 | llerrs << "deleting non-zero reference" << llendl; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | //---------------------------------------------------------------------------- | ||
297 | |||
298 | LLRefCount::LLRefCount() : | 267 | LLRefCount::LLRefCount() : |
299 | mRef(0) | 268 | mRef(0) |
300 | { | 269 | { |
diff --git a/linden/indra/llcommon/llmemory.h b/linden/indra/llcommon/llmemory.h index b40ab79..7a7996b 100644 --- a/linden/indra/llcommon/llmemory.h +++ b/linden/indra/llcommon/llmemory.h | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <cstdlib> | 31 | #include <cstdlib> |
32 | 32 | ||
33 | #include "llerror.h" | 33 | #include "llerror.h" |
34 | #include "llthread.h" | ||
35 | #include "llmemtype.h" | ||
36 | 34 | ||
37 | extern S32 gTotalDAlloc; | 35 | extern S32 gTotalDAlloc; |
38 | extern S32 gTotalDAUse; | 36 | extern S32 gTotalDAUse; |
@@ -61,53 +59,7 @@ private: | |||
61 | // LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting | 59 | // LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting |
62 | // x->instantiate(); // does stuff like place x into an update queue | 60 | // x->instantiate(); // does stuff like place x into an update queue |
63 | 61 | ||
64 | class LLThreadSafeRefCount | 62 | // see llthread.h for LLThreadSafeRefCount |
65 | { | ||
66 | public: | ||
67 | static void initClass(); // creates sMutex | ||
68 | static void cleanupClass(); // destroys sMutex | ||
69 | |||
70 | private: | ||
71 | static LLMutex* sMutex; | ||
72 | |||
73 | private: | ||
74 | LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented | ||
75 | LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented | ||
76 | |||
77 | protected: | ||
78 | virtual ~LLThreadSafeRefCount(); // use unref() | ||
79 | |||
80 | public: | ||
81 | LLThreadSafeRefCount(); | ||
82 | |||
83 | void ref() | ||
84 | { | ||
85 | if (sMutex) sMutex->lock(); | ||
86 | mRef++; | ||
87 | if (sMutex) sMutex->unlock(); | ||
88 | } | ||
89 | |||
90 | S32 unref() | ||
91 | { | ||
92 | llassert(mRef >= 1); | ||
93 | if (sMutex) sMutex->lock(); | ||
94 | S32 res = --mRef; | ||
95 | if (sMutex) sMutex->unlock(); | ||
96 | if (0 == res) | ||
97 | { | ||
98 | delete this; | ||
99 | res = 0; | ||
100 | } | ||
101 | return res; | ||
102 | } | ||
103 | S32 getNumRefs() const | ||
104 | { | ||
105 | return mRef; | ||
106 | } | ||
107 | |||
108 | private: | ||
109 | S32 mRef; | ||
110 | }; | ||
111 | 63 | ||
112 | //---------------------------------------------------------------------------- | 64 | //---------------------------------------------------------------------------- |
113 | 65 | ||
@@ -139,6 +91,7 @@ public: | |||
139 | } | 91 | } |
140 | return mRef; | 92 | return mRef; |
141 | } | 93 | } |
94 | |||
142 | S32 getNumRefs() const | 95 | S32 getNumRefs() const |
143 | { | 96 | { |
144 | return mRef; | 97 | return mRef; |
@@ -150,6 +103,7 @@ private: | |||
150 | 103 | ||
151 | //---------------------------------------------------------------------------- | 104 | //---------------------------------------------------------------------------- |
152 | 105 | ||
106 | // Note: relies on Type having ref() and unref() methods | ||
153 | template <class Type> class LLPointer | 107 | template <class Type> class LLPointer |
154 | { | 108 | { |
155 | public: | 109 | public: |
@@ -268,6 +222,154 @@ protected: | |||
268 | Type* mPointer; | 222 | Type* mPointer; |
269 | }; | 223 | }; |
270 | 224 | ||
225 | //template <class Type> | ||
226 | //class LLPointerTraits | ||
227 | //{ | ||
228 | // static Type* null(); | ||
229 | //}; | ||
230 | // | ||
231 | // Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. | ||
232 | // This is useful in instances where operations on NULL pointers are semantically safe and/or | ||
233 | // when error checking occurs at a different granularity or in a different part of the code | ||
234 | // than when referencing an object via a LLHandle. | ||
235 | // | ||
236 | |||
237 | template <class Type> | ||
238 | class LLHandle | ||
239 | { | ||
240 | public: | ||
241 | LLHandle() : | ||
242 | mPointer(sNullFunc()) | ||
243 | { | ||
244 | ref(); | ||
245 | } | ||
246 | |||
247 | LLHandle(Type* ptr) : | ||
248 | mPointer(nonNull(ptr)) | ||
249 | { | ||
250 | ref(); | ||
251 | } | ||
252 | |||
253 | LLHandle(const LLHandle<Type>& ptr) : | ||
254 | mPointer(ptr.mPointer) | ||
255 | { | ||
256 | ref(); | ||
257 | } | ||
258 | |||
259 | // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. | ||
260 | template<typename Subclass> | ||
261 | LLHandle(const LLHandle<Subclass>& ptr) : | ||
262 | mPointer(ptr.get()) | ||
263 | { | ||
264 | ref(); | ||
265 | } | ||
266 | |||
267 | ~LLHandle() | ||
268 | { | ||
269 | unref(); | ||
270 | } | ||
271 | |||
272 | Type* get() const { return mPointer; } | ||
273 | const Type* operator->() const { return mPointer; } | ||
274 | Type* operator->() { return mPointer; } | ||
275 | const Type& operator*() const { return *mPointer; } | ||
276 | Type& operator*() { return *mPointer; } | ||
277 | |||
278 | operator BOOL() const { return (mPointer != sNullFunc()); } | ||
279 | operator bool() const { return (mPointer != sNullFunc()); } | ||
280 | bool operator!() const { return (mPointer == sNullFunc()); } | ||
281 | bool isNull() const { return (mPointer == sNullFunc()); } | ||
282 | bool notNull() const { return (mPointer != sNullFunc()); } | ||
283 | |||
284 | |||
285 | operator Type*() const { return mPointer; } | ||
286 | operator const Type*() const { return mPointer; } | ||
287 | bool operator !=(Type* ptr) const { return (mPointer != nonNull(ptr)); } | ||
288 | bool operator ==(Type* ptr) const { return (mPointer == nonNull(ptr)); } | ||
289 | bool operator ==(const LLHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); } | ||
290 | bool operator < (const LLHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); } | ||
291 | bool operator > (const LLHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); } | ||
292 | |||
293 | LLHandle<Type>& operator =(Type* ptr) | ||
294 | { | ||
295 | if( mPointer != ptr ) | ||
296 | { | ||
297 | unref(); | ||
298 | mPointer = nonNull(ptr); | ||
299 | ref(); | ||
300 | } | ||
301 | |||
302 | return *this; | ||
303 | } | ||
304 | |||
305 | LLHandle<Type>& operator =(const LLHandle<Type>& ptr) | ||
306 | { | ||
307 | if( mPointer != ptr.mPointer ) | ||
308 | { | ||
309 | unref(); | ||
310 | mPointer = ptr.mPointer; | ||
311 | ref(); | ||
312 | } | ||
313 | return *this; | ||
314 | } | ||
315 | |||
316 | // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. | ||
317 | template<typename Subclass> | ||
318 | LLHandle<Type>& operator =(const LLHandle<Subclass>& ptr) | ||
319 | { | ||
320 | if( mPointer != ptr.get() ) | ||
321 | { | ||
322 | unref(); | ||
323 | mPointer = ptr.get(); | ||
324 | ref(); | ||
325 | } | ||
326 | return *this; | ||
327 | } | ||
328 | |||
329 | public: | ||
330 | typedef Type* (*NullFunc)(); | ||
331 | static const NullFunc sNullFunc; | ||
332 | |||
333 | protected: | ||
334 | void ref() | ||
335 | { | ||
336 | if (mPointer) | ||
337 | { | ||
338 | mPointer->ref(); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | void unref() | ||
343 | { | ||
344 | if (mPointer) | ||
345 | { | ||
346 | Type *tempp = mPointer; | ||
347 | mPointer = sNullFunc(); | ||
348 | tempp->unref(); | ||
349 | if (mPointer != sNullFunc()) | ||
350 | { | ||
351 | llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; | ||
352 | unref(); | ||
353 | } | ||
354 | } | ||
355 | } | ||
356 | |||
357 | static Type* nonNull(Type* ptr) | ||
358 | { | ||
359 | return ptr == NULL ? sNullFunc() : ptr; | ||
360 | } | ||
361 | |||
362 | static Type* defaultNullFunc() | ||
363 | { | ||
364 | llerrs << "No null value provided for LLHandle" << llendl; | ||
365 | return NULL; | ||
366 | } | ||
367 | |||
368 | protected: | ||
369 | |||
370 | Type* mPointer; | ||
371 | }; | ||
372 | |||
271 | // LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL | 373 | // LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL |
272 | // NOT a smart pointer like LLPointer<> | 374 | // NOT a smart pointer like LLPointer<> |
273 | // Useful for example in std::map<int,LLInitializedPointer<LLFoo> > | 375 | // Useful for example in std::map<int,LLInitializedPointer<LLFoo> > |
diff --git a/linden/indra/llcommon/llmemtype.h b/linden/indra/llcommon/llmemtype.h index 15ef924..0af1ed3 100644 --- a/linden/indra/llcommon/llmemtype.h +++ b/linden/indra/llcommon/llmemtype.h | |||
@@ -71,6 +71,7 @@ public: | |||
71 | 71 | ||
72 | MTYPE_DRAWABLE, | 72 | MTYPE_DRAWABLE, |
73 | MTYPE_OBJECT, | 73 | MTYPE_OBJECT, |
74 | MTYPE_VERTEX_DATA, | ||
74 | MTYPE_SPACE_PARTITION, | 75 | MTYPE_SPACE_PARTITION, |
75 | MTYPE_PIPELINE, | 76 | MTYPE_PIPELINE, |
76 | MTYPE_AVATAR, | 77 | MTYPE_AVATAR, |
diff --git a/linden/indra/llcommon/llpreprocessor.h b/linden/indra/llcommon/llpreprocessor.h index f03fe89..9db0108 100644 --- a/linden/indra/llcommon/llpreprocessor.h +++ b/linden/indra/llcommon/llpreprocessor.h | |||
@@ -51,7 +51,9 @@ | |||
51 | #define LL_LIBXUL_ENABLED 1 | 51 | #define LL_LIBXUL_ENABLED 1 |
52 | #elif LL_LINUX | 52 | #elif LL_LINUX |
53 | #define LL_QUICKTIME_ENABLED 0 | 53 | #define LL_QUICKTIME_ENABLED 0 |
54 | #define LL_LIBXUL_ENABLED 0 | 54 | #ifndef LL_LIBXUL_ENABLED |
55 | #define LL_LIBXUL_ENABLED 1 | ||
56 | #endif // def LL_LIBXUL_ENABLED | ||
55 | #endif | 57 | #endif |
56 | 58 | ||
57 | #if LL_LIBXUL_ENABLED && !defined(MOZILLA_INTERNAL_API) | 59 | #if LL_LIBXUL_ENABLED && !defined(MOZILLA_INTERNAL_API) |
@@ -80,7 +82,7 @@ | |||
80 | 82 | ||
81 | // Deal with the differeneces on Windows | 83 | // Deal with the differeneces on Windows |
82 | #if defined(LL_WINDOWS) | 84 | #if defined(LL_WINDOWS) |
83 | #define snprintf _snprintf | 85 | #define snprintf _snprintf /*Flawfinder: ignore*/ |
84 | #endif // LL_WINDOWS | 86 | #endif // LL_WINDOWS |
85 | 87 | ||
86 | // Static linking with apr on windows needs to be declared. | 88 | // Static linking with apr on windows needs to be declared. |
@@ -110,6 +112,7 @@ | |||
110 | #pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file | 112 | #pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file |
111 | #pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. | 113 | #pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. |
112 | #pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) | 114 | #pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) |
115 | #pragma warning( disable : 4996 ) // warning: deprecated | ||
113 | #endif // LL_WINDOWS | 116 | #endif // LL_WINDOWS |
114 | 117 | ||
115 | #endif // not LL_LINDEN_PREPROCESSOR_H | 118 | #endif // not LL_LINDEN_PREPROCESSOR_H |
diff --git a/linden/indra/llcommon/llprocessor.cpp b/linden/indra/llcommon/llprocessor.cpp index b811678..3408cb1 100644 --- a/linden/indra/llcommon/llprocessor.cpp +++ b/linden/indra/llcommon/llprocessor.cpp | |||
@@ -604,7 +604,7 @@ bool CProcessor::AnalyzeIntelProcessor() | |||
604 | mov sig3, edx | 604 | mov sig3, edx |
605 | } | 605 | } |
606 | // Then we convert the data to a readable string | 606 | // Then we convert the data to a readable string |
607 | snprintf( | 607 | snprintf( /* Flawfinder: ignore */ |
608 | CPUInfo.strProcessorSerial, | 608 | CPUInfo.strProcessorSerial, |
609 | sizeof(CPUInfo.strProcessorSerial), | 609 | sizeof(CPUInfo.strProcessorSerial), |
610 | "%04lX-%04lX-%04lX-%04lX-%04lX-%04lX", | 610 | "%04lX-%04lX-%04lX-%04lX-%04lX-%04lX", |
@@ -612,15 +612,15 @@ bool CProcessor::AnalyzeIntelProcessor() | |||
612 | sig1 & 0xFFFF, | 612 | sig1 & 0xFFFF, |
613 | sig3 >> 16, | 613 | sig3 >> 16, |
614 | sig3 & 0xFFFF, | 614 | sig3 & 0xFFFF, |
615 | sig2 >> 16, sig2 & 0xFFFF); /* Flawfinder: ignore */ | 615 | sig2 >> 16, sig2 & 0xFFFF); |
616 | } | 616 | } |
617 | else | 617 | else |
618 | { | 618 | { |
619 | // If there's no serial number support we just put "No serial number" | 619 | // If there's no serial number support we just put "No serial number" |
620 | snprintf( | 620 | snprintf( /* Flawfinder: ignore */ |
621 | CPUInfo.strProcessorSerial, | 621 | CPUInfo.strProcessorSerial, |
622 | sizeof(CPUInfo.strProcessorSerial), | 622 | sizeof(CPUInfo.strProcessorSerial), |
623 | "No Processor Serial Number"); /* Flawfinder: ignore */ | 623 | "No Processor Serial Number"); |
624 | } | 624 | } |
625 | 625 | ||
626 | // Now we get the standard processor extensions | 626 | // Now we get the standard processor extensions |
@@ -854,7 +854,7 @@ bool CProcessor::AnalyzeAMDProcessor() | |||
854 | break; | 854 | break; |
855 | case 0xD: // Model = 0xD: K6-2+ / K6-III+ | 855 | case 0xD: // Model = 0xD: K6-2+ / K6-III+ |
856 | strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)"); /* Flawfinder: ignore */ | 856 | strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)"); /* Flawfinder: ignore */ |
857 | strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); | 857 | strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ |
858 | break; | 858 | break; |
859 | default: // ... | 859 | default: // ... |
860 | strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model"); /* Flawfinder: ignore */ | 860 | strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model"); /* Flawfinder: ignore */ |
diff --git a/linden/indra/llcommon/llqueuedthread.cpp b/linden/indra/llcommon/llqueuedthread.cpp index 565836b..2e4324b 100644 --- a/linden/indra/llcommon/llqueuedthread.cpp +++ b/linden/indra/llcommon/llqueuedthread.cpp | |||
@@ -31,10 +31,9 @@ | |||
31 | //============================================================================ | 31 | //============================================================================ |
32 | 32 | ||
33 | // MAIN THREAD | 33 | // MAIN THREAD |
34 | LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool runalways) : | 34 | LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : |
35 | LLThread(name), | 35 | LLThread(name), |
36 | mThreaded(threaded), | 36 | mThreaded(threaded), |
37 | mRunAlways(runalways), | ||
38 | mIdleThread(TRUE), | 37 | mIdleThread(TRUE), |
39 | mNextHandle(0) | 38 | mNextHandle(0) |
40 | { | 39 | { |
@@ -47,6 +46,12 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool runa | |||
47 | // MAIN THREAD | 46 | // MAIN THREAD |
48 | LLQueuedThread::~LLQueuedThread() | 47 | LLQueuedThread::~LLQueuedThread() |
49 | { | 48 | { |
49 | shutdown(); | ||
50 | // ~LLThread() will be called here | ||
51 | } | ||
52 | |||
53 | void LLQueuedThread::shutdown() | ||
54 | { | ||
50 | setQuitting(); | 55 | setQuitting(); |
51 | 56 | ||
52 | unpause(); // MAIN THREAD | 57 | unpause(); // MAIN THREAD |
@@ -73,61 +78,69 @@ LLQueuedThread::~LLQueuedThread() | |||
73 | } | 78 | } |
74 | 79 | ||
75 | QueuedRequest* req; | 80 | QueuedRequest* req; |
81 | S32 active_count = 0; | ||
76 | while ( (req = (QueuedRequest*)mRequestHash.pop_element()) ) | 82 | while ( (req = (QueuedRequest*)mRequestHash.pop_element()) ) |
77 | { | 83 | { |
84 | if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS) | ||
85 | { | ||
86 | ++active_count; | ||
87 | } | ||
78 | req->deleteRequest(); | 88 | req->deleteRequest(); |
79 | } | 89 | } |
80 | 90 | if (active_count) | |
81 | // ~LLThread() will be called here | 91 | { |
92 | llwarns << "~LLQueuedThread() called with active requests: " << active_count << llendl; | ||
93 | } | ||
82 | } | 94 | } |
83 | 95 | ||
84 | //---------------------------------------------------------------------------- | 96 | //---------------------------------------------------------------------------- |
85 | 97 | ||
86 | // MAIN THREAD | 98 | // MAIN THREAD |
87 | void LLQueuedThread::update(U32 ms_elapsed) | 99 | // virtual |
100 | S32 LLQueuedThread::update(U32 max_time_ms) | ||
88 | { | 101 | { |
89 | updateQueue(0); | 102 | return updateQueue(max_time_ms); |
90 | } | 103 | } |
91 | 104 | ||
92 | void LLQueuedThread::updateQueue(S32 inc) | 105 | S32 LLQueuedThread::updateQueue(U32 max_time_ms) |
93 | { | 106 | { |
94 | // If mRunAlways == TRUE, unpause the thread whenever we put something into the queue. | 107 | F64 max_time = (F64)max_time_ms * .001; |
95 | // If mRunAlways == FALSE, we only unpause the thread when updateQueue() is called from the main loop (i.e. between rendered frames) | 108 | LLTimer timer; |
96 | 109 | S32 pending = 1; | |
97 | if (inc == 0) // Frame Update | 110 | |
111 | // Frame Update | ||
112 | if (mThreaded) | ||
98 | { | 113 | { |
99 | if (mThreaded) | 114 | pending = getPending(); |
100 | { | 115 | unpause(); |
101 | unpause(); | 116 | } |
102 | wake(); // Wake the thread up if necessary. | 117 | else |
103 | } | 118 | { |
104 | else | 119 | while (pending > 0) |
105 | { | 120 | { |
106 | while (processNextRequest() > 0) | 121 | pending = processNextRequest(); |
107 | ; | 122 | if (max_time && timer.getElapsedTimeF64() > max_time) |
123 | break; | ||
108 | } | 124 | } |
109 | } | 125 | } |
110 | else | 126 | return pending; |
127 | } | ||
128 | |||
129 | void LLQueuedThread::incQueue() | ||
130 | { | ||
131 | // Something has been added to the queue | ||
132 | if (!isPaused()) | ||
111 | { | 133 | { |
112 | // Something has been added to the queue | 134 | if (mThreaded) |
113 | if (mRunAlways) | ||
114 | { | 135 | { |
115 | if (mThreaded) | 136 | wake(); // Wake the thread up if necessary. |
116 | { | ||
117 | wake(); // Wake the thread up if necessary. | ||
118 | } | ||
119 | else | ||
120 | { | ||
121 | while(processNextRequest() > 0) | ||
122 | ; | ||
123 | } | ||
124 | } | 137 | } |
125 | } | 138 | } |
126 | } | 139 | } |
127 | 140 | ||
128 | //virtual | 141 | //virtual |
129 | // May be called from any thread | 142 | // May be called from any thread |
130 | S32 LLQueuedThread::getPending(bool child_thread) | 143 | S32 LLQueuedThread::getPending() |
131 | { | 144 | { |
132 | S32 res; | 145 | S32 res; |
133 | lockData(); | 146 | lockData(); |
@@ -141,7 +154,7 @@ void LLQueuedThread::waitOnPending() | |||
141 | { | 154 | { |
142 | while(1) | 155 | while(1) |
143 | { | 156 | { |
144 | updateQueue(0); | 157 | update(0); |
145 | 158 | ||
146 | if (mIdleThread) | 159 | if (mIdleThread) |
147 | { | 160 | { |
@@ -200,7 +213,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req) | |||
200 | #endif | 213 | #endif |
201 | unlockData(); | 214 | unlockData(); |
202 | 215 | ||
203 | updateQueue(1); | 216 | incQueue(); |
204 | 217 | ||
205 | return true; | 218 | return true; |
206 | } | 219 | } |
@@ -214,7 +227,7 @@ bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_co | |||
214 | bool done = false; | 227 | bool done = false; |
215 | while(!done) | 228 | while(!done) |
216 | { | 229 | { |
217 | updateQueue(0); // unpauses | 230 | update(0); // unpauses |
218 | lockData(); | 231 | lockData(); |
219 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); | 232 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); |
220 | if (!req) | 233 | if (!req) |
@@ -272,51 +285,47 @@ LLQueuedThread::status_t LLQueuedThread::getRequestStatus(handle_t handle) | |||
272 | return res; | 285 | return res; |
273 | } | 286 | } |
274 | 287 | ||
275 | LLQueuedThread::status_t LLQueuedThread::abortRequest(handle_t handle, U32 flags) | 288 | void LLQueuedThread::abortRequest(handle_t handle, bool autocomplete) |
276 | { | 289 | { |
277 | status_t res = STATUS_EXPIRED; | ||
278 | lockData(); | 290 | lockData(); |
279 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); | 291 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); |
280 | if (req) | 292 | if (req) |
281 | { | 293 | { |
282 | res = req->abortRequest(flags); | 294 | req->setFlags(FLAG_ABORT | (autocomplete ? FLAG_AUTO_COMPLETE : 0)); |
283 | if ((flags & AUTO_COMPLETE) && (res == STATUS_COMPLETE)) | ||
284 | { | ||
285 | mRequestHash.erase(handle); | ||
286 | req->deleteRequest(); | ||
287 | // check(); | ||
288 | } | ||
289 | #if _DEBUG | ||
290 | // llinfos << llformat("LLQueuedThread::Aborted req [%08d]",handle) << llendl; | ||
291 | #endif | ||
292 | } | 295 | } |
293 | unlockData(); | 296 | unlockData(); |
294 | return res; | ||
295 | } | 297 | } |
296 | 298 | ||
297 | // MAIN thread | 299 | // MAIN thread |
298 | LLQueuedThread::status_t LLQueuedThread::setFlags(handle_t handle, U32 flags) | 300 | void LLQueuedThread::setFlags(handle_t handle, U32 flags) |
299 | { | 301 | { |
300 | status_t res = STATUS_EXPIRED; | ||
301 | lockData(); | 302 | lockData(); |
302 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); | 303 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); |
303 | if (req) | 304 | if (req) |
304 | { | 305 | { |
305 | res = req->setFlags(flags); | 306 | req->setFlags(flags); |
306 | } | 307 | } |
307 | unlockData(); | 308 | unlockData(); |
308 | return res; | ||
309 | } | 309 | } |
310 | 310 | ||
311 | void LLQueuedThread::setPriority(handle_t handle, U32 priority) | 311 | void LLQueuedThread::setPriority(handle_t handle, U32 priority) |
312 | { | 312 | { |
313 | lockData(); | 313 | lockData(); |
314 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); | 314 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); |
315 | if (req && (req->getStatus() == STATUS_QUEUED)) | 315 | if (req) |
316 | { | 316 | { |
317 | llverify(mRequestQueue.erase(req) == 1); | 317 | if(req->getStatus() == STATUS_INPROGRESS) |
318 | req->setPriority(priority); | 318 | { |
319 | mRequestQueue.insert(req); | 319 | // not in list |
320 | req->setPriority(priority); | ||
321 | } | ||
322 | else if(req->getStatus() == STATUS_QUEUED) | ||
323 | { | ||
324 | // remove from list then re-insert | ||
325 | llverify(mRequestQueue.erase(req) == 1); | ||
326 | req->setPriority(priority); | ||
327 | mRequestQueue.insert(req); | ||
328 | } | ||
320 | } | 329 | } |
321 | unlockData(); | 330 | unlockData(); |
322 | } | 331 | } |
@@ -328,9 +337,10 @@ bool LLQueuedThread::completeRequest(handle_t handle) | |||
328 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); | 337 | QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); |
329 | if (req) | 338 | if (req) |
330 | { | 339 | { |
331 | llassert(req->getStatus() != STATUS_QUEUED && req->getStatus() != STATUS_ABORT); | 340 | llassert_always(req->getStatus() != STATUS_QUEUED); |
341 | llassert_always(req->getStatus() != STATUS_INPROGRESS); | ||
332 | #if _DEBUG | 342 | #if _DEBUG |
333 | // llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl; | 343 | // llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl; |
334 | #endif | 344 | #endif |
335 | mRequestHash.erase(handle); | 345 | mRequestHash.erase(handle); |
336 | req->deleteRequest(); | 346 | req->deleteRequest(); |
@@ -364,28 +374,34 @@ bool LLQueuedThread::check() | |||
364 | //============================================================================ | 374 | //============================================================================ |
365 | // Runs on its OWN thread | 375 | // Runs on its OWN thread |
366 | 376 | ||
367 | int LLQueuedThread::processNextRequest() | 377 | S32 LLQueuedThread::processNextRequest() |
368 | { | 378 | { |
369 | QueuedRequest *req = 0; | 379 | QueuedRequest *req; |
370 | // Get next request from pool | 380 | // Get next request from pool |
371 | lockData(); | 381 | lockData(); |
372 | while(1) | 382 | while(1) |
373 | { | 383 | { |
374 | if (!mRequestQueue.empty()) | 384 | req = NULL; |
385 | if (mRequestQueue.empty()) | ||
375 | { | 386 | { |
376 | req = *mRequestQueue.begin(); | 387 | break; |
377 | mRequestQueue.erase(mRequestQueue.begin()); | ||
378 | } | 388 | } |
379 | if (req && req->getStatus() == STATUS_ABORT) | 389 | req = *mRequestQueue.begin(); |
390 | mRequestQueue.erase(mRequestQueue.begin()); | ||
391 | if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING)) | ||
380 | { | 392 | { |
381 | req->setStatus(STATUS_ABORTED); | 393 | req->setStatus(STATUS_ABORTED); |
382 | req = 0; | 394 | req->finishRequest(false); |
383 | } | 395 | if (req->getFlags() & FLAG_AUTO_COMPLETE) |
384 | else | 396 | { |
385 | { | 397 | mRequestHash.erase(req); |
386 | llassert (!req || req->getStatus() == STATUS_QUEUED) | 398 | req->deleteRequest(); |
387 | break; | 399 | // check(); |
400 | } | ||
401 | continue; | ||
388 | } | 402 | } |
403 | llassert_always(req->getStatus() == STATUS_QUEUED); | ||
404 | break; | ||
389 | } | 405 | } |
390 | if (req) | 406 | if (req) |
391 | { | 407 | { |
@@ -393,22 +409,22 @@ int LLQueuedThread::processNextRequest() | |||
393 | } | 409 | } |
394 | unlockData(); | 410 | unlockData(); |
395 | 411 | ||
396 | // This is the only place we will cal req->setStatus() after | 412 | // This is the only place we will call req->setStatus() after |
397 | // it has initially been seet to STATUS_QUEUED, so it is | 413 | // it has initially been seet to STATUS_QUEUED, so it is |
398 | // safe to access req. | 414 | // safe to access req. |
399 | if (req) | 415 | if (req) |
400 | { | 416 | { |
401 | // process request | 417 | // process request |
402 | bool complete = processRequest(req); | 418 | bool complete = req->processRequest(); |
403 | 419 | ||
404 | if (complete) | 420 | if (complete) |
405 | { | 421 | { |
406 | lockData(); | 422 | lockData(); |
407 | req->setStatus(STATUS_COMPLETE); | 423 | req->setStatus(STATUS_COMPLETE); |
408 | req->finishRequest(); | 424 | req->finishRequest(true); |
409 | if (req->getFlags() & AUTO_COMPLETE) | 425 | if (req->getFlags() & FLAG_AUTO_COMPLETE) |
410 | { | 426 | { |
411 | llverify(mRequestHash.erase(req)) | 427 | mRequestHash.erase(req); |
412 | req->deleteRequest(); | 428 | req->deleteRequest(); |
413 | // check(); | 429 | // check(); |
414 | } | 430 | } |
@@ -419,12 +435,18 @@ int LLQueuedThread::processNextRequest() | |||
419 | lockData(); | 435 | lockData(); |
420 | req->setStatus(STATUS_QUEUED); | 436 | req->setStatus(STATUS_QUEUED); |
421 | mRequestQueue.insert(req); | 437 | mRequestQueue.insert(req); |
438 | U32 priority = req->getPriority(); | ||
422 | unlockData(); | 439 | unlockData(); |
440 | if (priority < PRIORITY_NORMAL) | ||
441 | { | ||
442 | ms_sleep(1); // sleep the thread a little | ||
443 | } | ||
423 | } | 444 | } |
424 | } | 445 | } |
425 | 446 | ||
426 | int res; | 447 | S32 res; |
427 | if (getPending(true) == 0) | 448 | S32 pending = getPending(); |
449 | if (pending == 0) | ||
428 | { | 450 | { |
429 | if (isQuitting()) | 451 | if (isQuitting()) |
430 | { | 452 | { |
@@ -437,7 +459,7 @@ int LLQueuedThread::processNextRequest() | |||
437 | } | 459 | } |
438 | else | 460 | else |
439 | { | 461 | { |
440 | res = 1; | 462 | res = pending; |
441 | } | 463 | } |
442 | return res; | 464 | return res; |
443 | } | 465 | } |
@@ -445,13 +467,14 @@ int LLQueuedThread::processNextRequest() | |||
445 | bool LLQueuedThread::runCondition() | 467 | bool LLQueuedThread::runCondition() |
446 | { | 468 | { |
447 | // mRunCondition must be locked here | 469 | // mRunCondition must be locked here |
448 | return (mRequestQueue.empty() && mIdleThread) ? FALSE : TRUE; | 470 | if (mRequestQueue.empty() && mIdleThread) |
471 | return false; | ||
472 | else | ||
473 | return true; | ||
449 | } | 474 | } |
450 | 475 | ||
451 | void LLQueuedThread::run() | 476 | void LLQueuedThread::run() |
452 | { | 477 | { |
453 | llinfos << "QUEUED THREAD STARTING" << llendl; | ||
454 | |||
455 | while (1) | 478 | while (1) |
456 | { | 479 | { |
457 | // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state. | 480 | // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state. |
@@ -474,6 +497,8 @@ void LLQueuedThread::run() | |||
474 | { | 497 | { |
475 | break; | 498 | break; |
476 | } | 499 | } |
500 | |||
501 | //LLThread::yield(); // thread should yield after each request | ||
477 | } | 502 | } |
478 | 503 | ||
479 | llinfos << "QUEUED THREAD " << mName << " EXITING." << llendl; | 504 | llinfos << "QUEUED THREAD " << mName << " EXITING." << llendl; |
@@ -491,20 +516,18 @@ LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U3 | |||
491 | 516 | ||
492 | LLQueuedThread::QueuedRequest::~QueuedRequest() | 517 | LLQueuedThread::QueuedRequest::~QueuedRequest() |
493 | { | 518 | { |
494 | if (mStatus != STATUS_DELETE) | 519 | llassert_always(mStatus == STATUS_DELETE); |
495 | { | ||
496 | llerrs << "Attemt to directly delete a LLQueuedThread::QueuedRequest; use deleteRequest()" << llendl; | ||
497 | } | ||
498 | } | 520 | } |
499 | 521 | ||
500 | //virtual | 522 | //virtual |
501 | void LLQueuedThread::QueuedRequest::finishRequest() | 523 | void LLQueuedThread::QueuedRequest::finishRequest(bool completed) |
502 | { | 524 | { |
503 | } | 525 | } |
504 | 526 | ||
505 | //virtual | 527 | //virtual |
506 | void LLQueuedThread::QueuedRequest::deleteRequest() | 528 | void LLQueuedThread::QueuedRequest::deleteRequest() |
507 | { | 529 | { |
530 | llassert_always(mStatus != STATUS_INPROGRESS); | ||
508 | setStatus(STATUS_DELETE); | 531 | setStatus(STATUS_DELETE); |
509 | delete this; | 532 | delete this; |
510 | } | 533 | } |
diff --git a/linden/indra/llcommon/llqueuedthread.h b/linden/indra/llcommon/llqueuedthread.h index cc21b3b..7231285 100644 --- a/linden/indra/llcommon/llqueuedthread.h +++ b/linden/indra/llcommon/llqueuedthread.h | |||
@@ -52,7 +52,8 @@ public: | |||
52 | PRIORITY_HIGH = 0x30000000, | 52 | PRIORITY_HIGH = 0x30000000, |
53 | PRIORITY_NORMAL = 0x20000000, | 53 | PRIORITY_NORMAL = 0x20000000, |
54 | PRIORITY_LOW = 0x10000000, | 54 | PRIORITY_LOW = 0x10000000, |
55 | PRIORITY_LOWBITS = 0x0FFFFFFF | 55 | PRIORITY_LOWBITS = 0x0FFFFFFF, |
56 | PRIORITY_HIGHBITS = 0x70000000 | ||
56 | }; | 57 | }; |
57 | enum status_t { | 58 | enum status_t { |
58 | STATUS_EXPIRED = -1, | 59 | STATUS_EXPIRED = -1, |
@@ -60,13 +61,13 @@ public: | |||
60 | STATUS_QUEUED = 1, | 61 | STATUS_QUEUED = 1, |
61 | STATUS_INPROGRESS = 2, | 62 | STATUS_INPROGRESS = 2, |
62 | STATUS_COMPLETE = 3, | 63 | STATUS_COMPLETE = 3, |
63 | STATUS_ABORT = 4, | 64 | STATUS_ABORTED = 4, |
64 | STATUS_ABORTED = 5, | 65 | STATUS_DELETE = 5 |
65 | STATUS_DELETE = 6 | ||
66 | }; | 66 | }; |
67 | enum flags_t { | 67 | enum flags_t { |
68 | AUTO_COMPLETE = 1, | 68 | FLAG_AUTO_COMPLETE = 1, |
69 | AUTO_DELETE = 2 // child-class dependent | 69 | FLAG_AUTO_DELETE = 2, // child-class dependent |
70 | FLAG_ABORT = 4 | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | typedef U32 handle_t; | 73 | typedef U32 handle_t; |
@@ -79,7 +80,7 @@ public: | |||
79 | friend class LLQueuedThread; | 80 | friend class LLQueuedThread; |
80 | 81 | ||
81 | protected: | 82 | protected: |
82 | ~QueuedRequest(); // use deleteRequest() | 83 | virtual ~QueuedRequest(); // use deleteRequest() |
83 | 84 | ||
84 | public: | 85 | public: |
85 | QueuedRequest(handle_t handle, U32 priority, U32 flags = 0); | 86 | QueuedRequest(handle_t handle, U32 priority, U32 flags = 0); |
@@ -111,26 +112,14 @@ public: | |||
111 | mStatus = newstatus; | 112 | mStatus = newstatus; |
112 | return oldstatus; | 113 | return oldstatus; |
113 | } | 114 | } |
114 | status_t abortRequest(U32 flags) | 115 | void setFlags(U32 flags) |
115 | { | 116 | { |
116 | // NOTE: flags are |'d | 117 | // NOTE: flags are |'d |
117 | if (mStatus == STATUS_QUEUED) | ||
118 | { | ||
119 | setStatus(STATUS_ABORT); | ||
120 | } | ||
121 | mFlags |= flags; | 118 | mFlags |= flags; |
122 | status_t status = mStatus; | ||
123 | return status; | ||
124 | } | ||
125 | status_t setFlags(U32 flags) | ||
126 | { | ||
127 | // NOTE: flags are |'d | ||
128 | mFlags |= flags; | ||
129 | status_t status = mStatus; | ||
130 | return status; | ||
131 | } | 119 | } |
132 | 120 | ||
133 | virtual void finishRequest(); // Always called when after has been processed | 121 | virtual bool processRequest() = 0; // Return true when request has completed |
122 | virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted | ||
134 | virtual void deleteRequest(); // Only method to delete a request | 123 | virtual void deleteRequest(); // Only method to delete a request |
135 | 124 | ||
136 | void setPriority(U32 pri) | 125 | void setPriority(U32 pri) |
@@ -160,9 +149,10 @@ public: | |||
160 | static handle_t nullHandle() { return handle_t(0); } | 149 | static handle_t nullHandle() { return handle_t(0); } |
161 | 150 | ||
162 | public: | 151 | public: |
163 | LLQueuedThread(const std::string& name, bool threaded = TRUE, bool runalways = TRUE); | 152 | LLQueuedThread(const std::string& name, bool threaded = true); |
164 | virtual ~LLQueuedThread(); | 153 | virtual ~LLQueuedThread(); |
165 | 154 | virtual void shutdown(); | |
155 | |||
166 | private: | 156 | private: |
167 | // No copy constructor or copy assignment | 157 | // No copy constructor or copy assignment |
168 | LLQueuedThread(const LLQueuedThread&); | 158 | LLQueuedThread(const LLQueuedThread&); |
@@ -174,26 +164,25 @@ private: | |||
174 | protected: | 164 | protected: |
175 | handle_t generateHandle(); | 165 | handle_t generateHandle(); |
176 | bool addRequest(QueuedRequest* req); | 166 | bool addRequest(QueuedRequest* req); |
177 | int processNextRequest(void); | 167 | S32 processNextRequest(void); |
168 | void incQueue(); | ||
178 | 169 | ||
179 | virtual bool processRequest(QueuedRequest* req) = 0; | ||
180 | |||
181 | public: | 170 | public: |
182 | bool waitForResult(handle_t handle, bool auto_complete = true); | 171 | bool waitForResult(handle_t handle, bool auto_complete = true); |
183 | 172 | ||
184 | void update(U32 ms_elapsed); | 173 | virtual S32 update(U32 max_time_ms); |
185 | void updateQueue(S32 inc); | 174 | S32 updateQueue(U32 max_time_ms); |
175 | |||
186 | void waitOnPending(); | 176 | void waitOnPending(); |
187 | void printQueueStats(); | 177 | void printQueueStats(); |
188 | 178 | ||
189 | S32 getPending(bool child_thread = false); | 179 | S32 getPending(); |
190 | bool getThreaded() { return mThreaded ? true : false; } | 180 | bool getThreaded() { return mThreaded ? true : false; } |
191 | bool getRunAlways() { return mRunAlways ? true : false; } | ||
192 | 181 | ||
193 | // Request accessors | 182 | // Request accessors |
194 | status_t getRequestStatus(handle_t handle); | 183 | status_t getRequestStatus(handle_t handle); |
195 | status_t abortRequest(handle_t handle, U32 flags = 0); | 184 | void abortRequest(handle_t handle, bool autocomplete); |
196 | status_t setFlags(handle_t handle, U32 flags); | 185 | void setFlags(handle_t handle, U32 flags); |
197 | void setPriority(handle_t handle, U32 priority); | 186 | void setPriority(handle_t handle, U32 priority); |
198 | bool completeRequest(handle_t handle); | 187 | bool completeRequest(handle_t handle); |
199 | // This is public for support classes like LLWorkerThread, | 188 | // This is public for support classes like LLWorkerThread, |
@@ -205,7 +194,6 @@ public: | |||
205 | 194 | ||
206 | protected: | 195 | protected: |
207 | BOOL mThreaded; // if false, run on main thread and do updates during update() | 196 | BOOL mThreaded; // if false, run on main thread and do updates during update() |
208 | BOOL mRunAlways; // if false, only wake the threads when updateClass() is called | ||
209 | LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle | 197 | LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle |
210 | 198 | ||
211 | typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; | 199 | typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; |
diff --git a/linden/indra/llcommon/llsd.cpp b/linden/indra/llcommon/llsd.cpp index 7a0ff9d..342e356 100644 --- a/linden/indra/llcommon/llsd.cpp +++ b/linden/indra/llcommon/llsd.cpp | |||
@@ -27,8 +27,12 @@ | |||
27 | 27 | ||
28 | #include "llsd.h" | 28 | #include "llsd.h" |
29 | 29 | ||
30 | #include <sstream> | ||
30 | #include <math.h> | 31 | #include <math.h> |
32 | |||
33 | #include "llerror.h" | ||
31 | #include "../llmath/llmath.h" | 34 | #include "../llmath/llmath.h" |
35 | #include "llformat.h" | ||
32 | 36 | ||
33 | namespace { | 37 | namespace { |
34 | class ImplMap; | 38 | class ImplMap; |
@@ -251,7 +255,7 @@ namespace { | |||
251 | public: | 255 | public: |
252 | ImplUUID(const LLSD::UUID& v) : Base(v) { } | 256 | ImplUUID(const LLSD::UUID& v) : Base(v) { } |
253 | 257 | ||
254 | virtual LLSD::String asString() const{ return mValue.getString(); } | 258 | virtual LLSD::String asString() const{ return mValue.asString(); } |
255 | virtual LLSD::UUID asUUID() const { return mValue; } | 259 | virtual LLSD::UUID asUUID() const { return mValue; } |
256 | }; | 260 | }; |
257 | 261 | ||
diff --git a/linden/indra/llcommon/llsdserialize.cpp b/linden/indra/llcommon/llsdserialize.cpp index 4c00c98..653fc66 100644 --- a/linden/indra/llcommon/llsdserialize.cpp +++ b/linden/indra/llcommon/llsdserialize.cpp | |||
@@ -804,7 +804,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const | |||
804 | // the size, and read it. | 804 | // the size, and read it. |
805 | // *FIX: Should we set a maximum size? | 805 | // *FIX: Should we set a maximum size? |
806 | U32 size_nbo = 0; | 806 | U32 size_nbo = 0; |
807 | istr.read((char*)&size_nbo, sizeof(U32)); | 807 | istr.read((char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/ |
808 | S32 size = (S32)ntohl(size_nbo); | 808 | S32 size = (S32)ntohl(size_nbo); |
809 | std::vector<U8> value; | 809 | std::vector<U8> value; |
810 | if(size) | 810 | if(size) |
@@ -944,7 +944,7 @@ void LLSDFormatter::realFormat(const std::string& format) | |||
944 | void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const | 944 | void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const |
945 | { | 945 | { |
946 | char buffer[MAX_STRING]; /* Flawfinder: ignore */ | 946 | char buffer[MAX_STRING]; /* Flawfinder: ignore */ |
947 | snprintf(buffer, MAX_STRING, mRealFormat.c_str(), real); | 947 | snprintf(buffer, MAX_STRING, mRealFormat.c_str(), real); /* Flawfinder: ignore */ |
948 | ostr << buffer; | 948 | ostr << buffer; |
949 | } | 949 | } |
950 | 950 | ||
diff --git a/linden/indra/llcommon/llsdserialize_xml.cpp b/linden/indra/llcommon/llsdserialize_xml.cpp index 892f454..bb36fa7 100644 --- a/linden/indra/llcommon/llsdserialize_xml.cpp +++ b/linden/indra/llcommon/llsdserialize_xml.cpp | |||
@@ -190,6 +190,7 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti | |||
190 | else | 190 | else |
191 | { | 191 | { |
192 | // *FIX: memory inefficient. | 192 | // *FIX: memory inefficient. |
193 | // *TODO: convert to use LLBase64 | ||
193 | ostr << pre << "<binary encoding=\"base64\">"; | 194 | ostr << pre << "<binary encoding=\"base64\">"; |
194 | int b64_buffer_length = apr_base64_encode_len(buffer.size()); | 195 | int b64_buffer_length = apr_base64_encode_len(buffer.size()); |
195 | char* b64_buffer = new char[b64_buffer_length]; | 196 | char* b64_buffer = new char[b64_buffer_length]; |
diff --git a/linden/indra/llcommon/llsecondlifeurls.cpp b/linden/indra/llcommon/llsecondlifeurls.cpp index 6050d7f..4372373 100644 --- a/linden/indra/llcommon/llsecondlifeurls.cpp +++ b/linden/indra/llcommon/llsecondlifeurls.cpp | |||
@@ -76,7 +76,5 @@ const char LSL_DOC_URL[] = | |||
76 | const char SL_KB_URL[] = | 76 | const char SL_KB_URL[] = |
77 | "http://secondlife.com/knowledgebase/"; | 77 | "http://secondlife.com/knowledgebase/"; |
78 | 78 | ||
79 | const char ACCOUNT_TRANSACTIONS_URL[] = | ||
80 | "https://secondlife.com/account/transactions.php"; | ||
81 | |||
82 | const char RELEASE_NOTES[] = "releasenotes.txt"; | 79 | const char RELEASE_NOTES[] = "releasenotes.txt"; |
80 | |||
diff --git a/linden/indra/llcommon/llsecondlifeurls.h b/linden/indra/llcommon/llsecondlifeurls.h index f338bc3..1f7d359 100644 --- a/linden/indra/llcommon/llsecondlifeurls.h +++ b/linden/indra/llcommon/llsecondlifeurls.h | |||
@@ -50,18 +50,9 @@ extern const char UPGRADE_TO_PREMIUM_URL[]; | |||
50 | // How to get DirectX 9 | 50 | // How to get DirectX 9 |
51 | extern const char DIRECTX_9_URL[]; | 51 | extern const char DIRECTX_9_URL[]; |
52 | 52 | ||
53 | // On AMD with bad AGP controller | ||
54 | extern const char AMD_AGP_URL[]; | ||
55 | |||
56 | // Out of date VIA chipset | 53 | // Out of date VIA chipset |
57 | extern const char VIA_URL[]; | 54 | extern const char VIA_URL[]; |
58 | 55 | ||
59 | // Out of date intel chipset driver | ||
60 | extern const char INTEL_CHIPSET_URL[]; | ||
61 | |||
62 | // Out of date SiS chipset driver | ||
63 | extern const char SIS_CHIPSET_URL[]; | ||
64 | |||
65 | // Linden Blogs page | 56 | // Linden Blogs page |
66 | extern const char BLOGS_URL[]; | 57 | extern const char BLOGS_URL[]; |
67 | 58 | ||
@@ -74,9 +65,6 @@ extern const char LSL_DOC_URL[]; | |||
74 | // SL KnowledgeBase page | 65 | // SL KnowledgeBase page |
75 | extern const char SL_KB_URL[]; | 66 | extern const char SL_KB_URL[]; |
76 | 67 | ||
77 | // Account transactions | ||
78 | extern const char ACCOUNT_TRANSACTIONS_URL[]; | ||
79 | |||
80 | // Local Url Release Notes | 68 | // Local Url Release Notes |
81 | extern const char RELEASE_NOTES[]; | 69 | extern const char RELEASE_NOTES[]; |
82 | 70 | ||
diff --git a/linden/indra/llcommon/llstreamtools.cpp b/linden/indra/llcommon/llstreamtools.cpp index b68edd3..2c78e05 100644 --- a/linden/indra/llcommon/llstreamtools.cpp +++ b/linden/indra/llcommon/llstreamtools.cpp | |||
@@ -553,7 +553,7 @@ std::istream& fullread(std::istream& str, char *buf, std::streamsize requested) | |||
553 | 553 | ||
554 | std::istream& operator>>(std::istream& str, const char *tocheck) | 554 | std::istream& operator>>(std::istream& str, const char *tocheck) |
555 | { | 555 | { |
556 | char c; | 556 | char c = '\0'; |
557 | const char *p; | 557 | const char *p; |
558 | p = tocheck; | 558 | p = tocheck; |
559 | while (*p && !str.bad()) | 559 | while (*p && !str.bad()) |
diff --git a/linden/indra/llcommon/llstrider.h b/linden/indra/llcommon/llstrider.h index 07b8c48..efc2ae4 100644 --- a/linden/indra/llcommon/llstrider.h +++ b/linden/indra/llcommon/llstrider.h | |||
@@ -51,6 +51,7 @@ public: | |||
51 | Object* operator->() { return mObjectp; } | 51 | Object* operator->() { return mObjectp; } |
52 | Object& operator *() { return *mObjectp; } | 52 | Object& operator *() { return *mObjectp; } |
53 | Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } | 53 | Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } |
54 | Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } | ||
54 | Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } | 55 | Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } |
55 | }; | 56 | }; |
56 | 57 | ||
diff --git a/linden/indra/llcommon/llstring.cpp b/linden/indra/llcommon/llstring.cpp index 5cb42cc..c9f684f 100644 --- a/linden/indra/llcommon/llstring.cpp +++ b/linden/indra/llcommon/llstring.cpp | |||
@@ -195,6 +195,7 @@ llutf16string utf8str_to_utf16str ( const LLString& utf8str ) | |||
195 | LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len) | 195 | LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len) |
196 | { | 196 | { |
197 | LLWString wout; | 197 | LLWString wout; |
198 | if((len <= 0) || utf16str.empty()) return wout; | ||
198 | 199 | ||
199 | S32 i = 0; | 200 | S32 i = 0; |
200 | // craziness to make gcc happy (llutf16string.c_str() is tweaked on linux): | 201 | // craziness to make gcc happy (llutf16string.c_str() is tweaked on linux): |
diff --git a/linden/indra/llcommon/llstring.h b/linden/indra/llcommon/llstring.h index a83b7cf..0485a1e 100644 --- a/linden/indra/llcommon/llstring.h +++ b/linden/indra/llcommon/llstring.h | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #include "stdtypes.h" | 31 | #include "stdtypes.h" |
32 | #include "llerror.h" | 32 | #include "llerror.h" |
33 | #include "llfile.h" | ||
33 | #include <algorithm> | 34 | #include <algorithm> |
34 | #include <map> | 35 | #include <map> |
35 | #include <stdio.h> | 36 | #include <stdio.h> |
@@ -101,7 +102,7 @@ struct char_traits<U16> | |||
101 | 102 | ||
102 | static char_type* | 103 | static char_type* |
103 | copy(char_type* __s1, const char_type* __s2, size_t __n) | 104 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
104 | { return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); } | 105 | { return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); } /* Flawfinder: ignore */ |
105 | 106 | ||
106 | static char_type* | 107 | static char_type* |
107 | assign(char_type* __s, size_t __n, char_type __a) | 108 | assign(char_type* __s, size_t __n, char_type __a) |
@@ -922,7 +923,7 @@ void LLStringBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T r | |||
922 | 923 | ||
923 | //static | 924 | //static |
924 | template<class T> | 925 | template<class T> |
925 | void LLStringBase<T>::replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab ) | 926 | void LLStringBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab ) |
926 | { | 927 | { |
927 | llassert( spaces_per_tab >= 0 ); | 928 | llassert( spaces_per_tab >= 0 ); |
928 | 929 | ||
@@ -931,19 +932,19 @@ void LLStringBase<T>::replaceTabsWithSpaces( std::basic_string<T>& string, size_ | |||
931 | 932 | ||
932 | LLStringBase<T> out_str; | 933 | LLStringBase<T> out_str; |
933 | // Replace tabs with spaces | 934 | // Replace tabs with spaces |
934 | for (size_type i = 0; i < string.length(); i++) | 935 | for (size_type i = 0; i < str.length(); i++) |
935 | { | 936 | { |
936 | if (string[i] == TAB) | 937 | if (str[i] == TAB) |
937 | { | 938 | { |
938 | for (size_type j = 0; j < spaces_per_tab; j++) | 939 | for (size_type j = 0; j < spaces_per_tab; j++) |
939 | out_str += SPACE; | 940 | out_str += SPACE; |
940 | } | 941 | } |
941 | else | 942 | else |
942 | { | 943 | { |
943 | out_str += string[i]; | 944 | out_str += str[i]; |
944 | } | 945 | } |
945 | } | 946 | } |
946 | string = out_str; | 947 | str = out_str; |
947 | } | 948 | } |
948 | 949 | ||
949 | //static | 950 | //static |
diff --git a/linden/indra/llcommon/llstringtable.h b/linden/indra/llcommon/llstringtable.h index d53c0e1..ddfef88 100644 --- a/linden/indra/llcommon/llstringtable.h +++ b/linden/indra/llcommon/llstringtable.h | |||
@@ -29,14 +29,15 @@ | |||
29 | #ifndef LL_STRING_TABLE_H | 29 | #ifndef LL_STRING_TABLE_H |
30 | #define LL_STRING_TABLE_H | 30 | #define LL_STRING_TABLE_H |
31 | 31 | ||
32 | #include "lldefs.h" | ||
33 | #include "llformat.h" | ||
32 | #include "llstl.h" | 34 | #include "llstl.h" |
33 | #include <list> | 35 | #include <list> |
34 | #include <set> | 36 | #include <set> |
35 | 37 | ||
36 | #if LL_WINDOWS | 38 | #if LL_WINDOWS |
37 | # if (_MSC_VER >= 1300) | 39 | # if (_MSC_VER >= 1300 && _MSC_VER < 1400) |
38 | # define STRING_TABLE_HASH_MAP 1 | 40 | # define STRING_TABLE_HASH_MAP 1 |
39 | # pragma warning(disable : 4996) | ||
40 | # endif | 41 | # endif |
41 | #else | 42 | #else |
42 | //# define STRING_TABLE_HASH_MAP 1 | 43 | //# define STRING_TABLE_HASH_MAP 1 |
diff --git a/linden/indra/llcommon/llsys.cpp b/linden/indra/llcommon/llsys.cpp index 148e4de..906bc65 100644 --- a/linden/indra/llcommon/llsys.cpp +++ b/linden/indra/llcommon/llsys.cpp | |||
@@ -132,23 +132,23 @@ LLOSInfo::LLOSInfo() : | |||
132 | char tmp[MAX_STRING]; /* Flawfinder: ignore */ | 132 | char tmp[MAX_STRING]; /* Flawfinder: ignore */ |
133 | if(osvi.dwMajorVersion <= 4) | 133 | if(osvi.dwMajorVersion <= 4) |
134 | { | 134 | { |
135 | snprintf( | 135 | snprintf( /* Flawfinder: ignore */ |
136 | tmp, | 136 | tmp, |
137 | sizeof(tmp), | 137 | sizeof(tmp), |
138 | "version %d.%d %s (Build %d)", | 138 | "version %d.%d %s (Build %d)", |
139 | osvi.dwMajorVersion, | 139 | osvi.dwMajorVersion, |
140 | osvi.dwMinorVersion, | 140 | osvi.dwMinorVersion, |
141 | csdversion.c_str(), | 141 | csdversion.c_str(), |
142 | (osvi.dwBuildNumber & 0xffff)); /* Flawfinder: ignore */ | 142 | (osvi.dwBuildNumber & 0xffff)); |
143 | } | 143 | } |
144 | else | 144 | else |
145 | { | 145 | { |
146 | snprintf( | 146 | snprintf( /* Flawfinder: ignore */ |
147 | tmp, | 147 | tmp, |
148 | sizeof(tmp), | 148 | sizeof(tmp), |
149 | "%s (Build %d)", | 149 | "%s (Build %d)", |
150 | csdversion.c_str(), | 150 | csdversion.c_str(), |
151 | (osvi.dwBuildNumber & 0xffff)); /*Flawfinder: ignore*/ | 151 | (osvi.dwBuildNumber & 0xffff)); |
152 | } | 152 | } |
153 | mOSString += tmp; | 153 | mOSString += tmp; |
154 | } | 154 | } |
@@ -250,7 +250,7 @@ U32 LLOSInfo::getProcessVirtualSizeKB() | |||
250 | #if LL_WINDOWS | 250 | #if LL_WINDOWS |
251 | #endif | 251 | #endif |
252 | #if LL_LINUX | 252 | #if LL_LINUX |
253 | FILE *status_filep = LLFile::fopen("/proc/self/status", "r"); | 253 | FILE* status_filep = LLFile::fopen("/proc/self/status", "r"); /* Flawfinder: ignore */ |
254 | S32 numRead = 0; | 254 | S32 numRead = 0; |
255 | char buff[STATUS_SIZE]; /* Flawfinder: ignore */ | 255 | char buff[STATUS_SIZE]; /* Flawfinder: ignore */ |
256 | bzero(buff, STATUS_SIZE); | 256 | bzero(buff, STATUS_SIZE); |
@@ -276,7 +276,7 @@ U32 LLOSInfo::getProcessResidentSizeKB() | |||
276 | #if LL_WINDOWS | 276 | #if LL_WINDOWS |
277 | #endif | 277 | #endif |
278 | #if LL_LINUX | 278 | #if LL_LINUX |
279 | FILE *status_filep = LLFile::fopen("/proc/self/status", "r"); | 279 | FILE* status_filep = LLFile::fopen("/proc/self/status", "r"); /* Flawfinder: ignore */ |
280 | if (status_filep != NULL) | 280 | if (status_filep != NULL) |
281 | { | 281 | { |
282 | S32 numRead = 0; | 282 | S32 numRead = 0; |
diff --git a/linden/indra/llcommon/llthread.cpp b/linden/indra/llcommon/llthread.cpp index 290879d..d6b52f7 100644 --- a/linden/indra/llcommon/llthread.cpp +++ b/linden/indra/llcommon/llthread.cpp | |||
@@ -100,6 +100,11 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : | |||
100 | 100 | ||
101 | LLThread::~LLThread() | 101 | LLThread::~LLThread() |
102 | { | 102 | { |
103 | shutdown(); | ||
104 | } | ||
105 | |||
106 | void LLThread::shutdown() | ||
107 | { | ||
103 | // Warning! If you somehow call the thread destructor from itself, | 108 | // Warning! If you somehow call the thread destructor from itself, |
104 | // the thread will die in an unclean fashion! | 109 | // the thread will die in an unclean fashion! |
105 | if (mAPRThreadp) | 110 | if (mAPRThreadp) |
@@ -205,18 +210,6 @@ void LLThread::checkPause() | |||
205 | 210 | ||
206 | //============================================================================ | 211 | //============================================================================ |
207 | 212 | ||
208 | bool LLThread::isQuitting() const | ||
209 | { | ||
210 | return (QUITTING == mStatus); | ||
211 | } | ||
212 | |||
213 | |||
214 | bool LLThread::isStopped() const | ||
215 | { | ||
216 | return (STOPPED == mStatus); | ||
217 | } | ||
218 | |||
219 | |||
220 | void LLThread::setQuitting() | 213 | void LLThread::setQuitting() |
221 | { | 214 | { |
222 | mRunCondition->lock(); | 215 | mRunCondition->lock(); |
@@ -347,3 +340,49 @@ void LLCondition::broadcast() | |||
347 | apr_thread_cond_broadcast(mAPRCondp); | 340 | apr_thread_cond_broadcast(mAPRCondp); |
348 | } | 341 | } |
349 | 342 | ||
343 | //============================================================================ | ||
344 | |||
345 | //---------------------------------------------------------------------------- | ||
346 | |||
347 | //static | ||
348 | LLMutex* LLThreadSafeRefCount::sMutex = 0; | ||
349 | |||
350 | //static | ||
351 | void LLThreadSafeRefCount::initClass() | ||
352 | { | ||
353 | if (!sMutex) | ||
354 | { | ||
355 | sMutex = new LLMutex(0); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | //static | ||
360 | void LLThreadSafeRefCount::cleanupClass() | ||
361 | { | ||
362 | delete sMutex; | ||
363 | sMutex = NULL; | ||
364 | } | ||
365 | |||
366 | |||
367 | //---------------------------------------------------------------------------- | ||
368 | |||
369 | LLThreadSafeRefCount::LLThreadSafeRefCount() : | ||
370 | mRef(0) | ||
371 | { | ||
372 | } | ||
373 | |||
374 | LLThreadSafeRefCount::~LLThreadSafeRefCount() | ||
375 | { | ||
376 | if (mRef != 0) | ||
377 | { | ||
378 | llerrs << "deleting non-zero reference" << llendl; | ||
379 | } | ||
380 | } | ||
381 | |||
382 | //============================================================================ | ||
383 | |||
384 | LLResponder::~LLResponder() | ||
385 | { | ||
386 | } | ||
387 | |||
388 | //============================================================================ | ||
diff --git a/linden/indra/llcommon/llthread.h b/linden/indra/llcommon/llthread.h index 2a13d72..cdf1d33 100644 --- a/linden/indra/llcommon/llthread.h +++ b/linden/indra/llcommon/llthread.h | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #include "llapr.h" | 31 | #include "llapr.h" |
32 | #include "llapp.h" | 32 | #include "llapp.h" |
33 | #include "llmemory.h" | ||
33 | 34 | ||
34 | #include "apr-1/apr_thread_cond.h" | 35 | #include "apr-1/apr_thread_cond.h" |
35 | 36 | ||
@@ -49,19 +50,20 @@ public: | |||
49 | 50 | ||
50 | LLThread(const std::string& name, apr_pool_t *poolp = NULL); | 51 | LLThread(const std::string& name, apr_pool_t *poolp = NULL); |
51 | virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state. | 52 | virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state. |
52 | 53 | virtual void shutdown(); // stops the thread | |
54 | |||
53 | static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. | 55 | static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. |
54 | 56 | ||
55 | 57 | ||
56 | bool isQuitting() const; | 58 | bool isQuitting() const { return (QUITTING == mStatus); } |
57 | bool isStopped() const; | 59 | bool isStopped() const { return (STOPPED == mStatus); } |
58 | 60 | ||
59 | // PAUSE / RESUME functionality. See source code for important usage notes. | 61 | // PAUSE / RESUME functionality. See source code for important usage notes. |
60 | public: | 62 | public: |
61 | // Called from MAIN THREAD. | 63 | // Called from MAIN THREAD. |
62 | void pause(); | 64 | void pause(); |
63 | void unpause(); | 65 | void unpause(); |
64 | bool isPaused() { return mPaused ? true : false; } | 66 | bool isPaused() { return isStopped() || mPaused == TRUE; } |
65 | 67 | ||
66 | // Cause the thread to wake up and check its condition | 68 | // Cause the thread to wake up and check its condition |
67 | void wake(); | 69 | void wake(); |
@@ -79,7 +81,7 @@ public: | |||
79 | 81 | ||
80 | private: | 82 | private: |
81 | BOOL mPaused; | 83 | BOOL mPaused; |
82 | 84 | ||
83 | // static function passed to APR thread creation routine | 85 | // static function passed to APR thread creation routine |
84 | static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap); | 86 | static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap); |
85 | 87 | ||
@@ -180,4 +182,67 @@ void LLThread::unlockData() | |||
180 | 182 | ||
181 | //============================================================================ | 183 | //============================================================================ |
182 | 184 | ||
185 | // see llmemory.h for LLPointer<> definition | ||
186 | |||
187 | class LLThreadSafeRefCount | ||
188 | { | ||
189 | public: | ||
190 | static void initClass(); // creates sMutex | ||
191 | static void cleanupClass(); // destroys sMutex | ||
192 | |||
193 | private: | ||
194 | static LLMutex* sMutex; | ||
195 | |||
196 | private: | ||
197 | LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented | ||
198 | LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented | ||
199 | |||
200 | protected: | ||
201 | virtual ~LLThreadSafeRefCount(); // use unref() | ||
202 | |||
203 | public: | ||
204 | LLThreadSafeRefCount(); | ||
205 | |||
206 | void ref() | ||
207 | { | ||
208 | if (sMutex) sMutex->lock(); | ||
209 | mRef++; | ||
210 | if (sMutex) sMutex->unlock(); | ||
211 | } | ||
212 | |||
213 | S32 unref() | ||
214 | { | ||
215 | llassert(mRef >= 1); | ||
216 | if (sMutex) sMutex->lock(); | ||
217 | S32 res = --mRef; | ||
218 | if (sMutex) sMutex->unlock(); | ||
219 | if (0 == res) | ||
220 | { | ||
221 | delete this; | ||
222 | res = 0; | ||
223 | } | ||
224 | return res; | ||
225 | } | ||
226 | S32 getNumRefs() const | ||
227 | { | ||
228 | return mRef; | ||
229 | } | ||
230 | |||
231 | private: | ||
232 | S32 mRef; | ||
233 | }; | ||
234 | |||
235 | //============================================================================ | ||
236 | |||
237 | // Simple responder for self destructing callbacks | ||
238 | // Pure virtual class | ||
239 | class LLResponder : public LLThreadSafeRefCount | ||
240 | { | ||
241 | public: | ||
242 | virtual ~LLResponder(); | ||
243 | virtual void completed(bool success) = 0; | ||
244 | }; | ||
245 | |||
246 | //============================================================================ | ||
247 | |||
183 | #endif // LL_LLTHREAD_H | 248 | #endif // LL_LLTHREAD_H |
diff --git a/linden/indra/llcommon/lluri.cpp b/linden/indra/llcommon/lluri.cpp index e697ec1..bc3540e 100644 --- a/linden/indra/llcommon/lluri.cpp +++ b/linden/indra/llcommon/lluri.cpp | |||
@@ -32,273 +32,86 @@ | |||
32 | #include "llapp.h" | 32 | #include "llapp.h" |
33 | #include "lluri.h" | 33 | #include "lluri.h" |
34 | #include "llsd.h" | 34 | #include "llsd.h" |
35 | 35 | #include <iomanip> | |
36 | |||
36 | #include "../llmath/lluuid.h" | 37 | #include "../llmath/lluuid.h" |
37 | 38 | ||
38 | // uric = reserved | unreserved | escaped | 39 | |
39 | // reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," | 40 | // static |
40 | // unreserved = alphanum | mark | 41 | std::string LLURI::escape(const std::string& str, const std::string & allowed) |
41 | // mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" | ||
42 | // escaped = "%" hex hex | ||
43 | static const char* ESCAPED_CHARACTERS[256] = | ||
44 | { | 42 | { |
45 | "%00", // 0 | 43 | std::ostringstream ostr; |
46 | "%01", // 1 | 44 | |
47 | "%02", // 2 | 45 | std::string::const_iterator it = str.begin(); |
48 | "%03", // 3 | 46 | std::string::const_iterator end = str.end(); |
49 | "%04", // 4 | 47 | for(; it != end; ++it) |
50 | "%05", // 5 | 48 | { |
51 | "%06", // 6 | 49 | std::string::value_type c = *it; |
52 | "%07", // 7 | 50 | if(allowed.find(c) == std::string::npos) |
53 | "%08", // 8 | 51 | { |
54 | "%09", // 9 | 52 | ostr << "%" |
55 | "%0a", // 10 | 53 | << std::uppercase << std::hex << std::setw(2) << std::setfill('0') |
56 | "%0b", // 11 | 54 | << static_cast<U32>(c); |
57 | "%0c", // 12 | 55 | } |
58 | "%0d", // 13 | 56 | else |
59 | "%0e", // 14 | 57 | { |
60 | "%0f", // 15 | 58 | ostr << c; |
61 | "%10", // 16 | 59 | } |
62 | "%11", // 17 | 60 | } |
63 | "%12", // 18 | 61 | return ostr.str(); |
64 | "%13", // 19 | 62 | } |
65 | "%14", // 20 | 63 | |
66 | "%15", // 21 | 64 | // static |
67 | "%16", // 22 | 65 | std::string LLURI::unescape(const std::string& str) |
68 | "%17", // 23 | 66 | { |
69 | "%18", // 24 | 67 | std::ostringstream ostr; |
70 | "%19", // 25 | 68 | std::string::const_iterator it = str.begin(); |
71 | "%1a", // 26 | 69 | std::string::const_iterator end = str.end(); |
72 | "%1b", // 27 | 70 | for(; it != end; ++it) |
73 | "%1c", // 28 | 71 | { |
74 | "%1d", // 29 | 72 | if((*it) == '%') |
75 | "%1e", // 30 | 73 | { |
76 | "%1f", // 31 | 74 | ++it; |
77 | "%20", // 32 | 75 | if(it == end) break; |
78 | "!", // 33 | 76 | U8 c = hex_as_nybble(*it++); |
79 | "%22", // 34 | 77 | c = c << 4; |
80 | "%23", // 35 | 78 | if (it == end) break; |
81 | "$", // 36 | 79 | c |= hex_as_nybble(*it); |
82 | "%25", // 37 | 80 | ostr.put((char)c); |
83 | "&", // 38 | 81 | } |
84 | "'", // 39 | 82 | else |
85 | "(", // 40 | 83 | { |
86 | ")", // 41 | 84 | ostr.put(*it); |
87 | "*", // 42 | 85 | } |
88 | "+", // 43 | 86 | } |
89 | ",", // 44 | 87 | return ostr.str(); |
90 | "-", // 45 | 88 | } |
91 | ".", // 46 | 89 | |
92 | "/", // 47 | 90 | namespace |
93 | "0", // 48 | 91 | { |
94 | "1", // 49 | 92 | const std::string unreserved() |
95 | "2", // 50 | 93 | { |
96 | "3", // 51 | 94 | static const std::string s = |
97 | "4", // 52 | 95 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" |
98 | "5", // 53 | 96 | "0123456789" |
99 | "6", // 54 | 97 | "-._~"; |
100 | "7", // 55 | 98 | return s; |
101 | "8", // 56 | 99 | } |
102 | "9", // 57 | 100 | const std::string sub_delims() |
103 | ":", // 58 | 101 | { |
104 | ";", // 59 | 102 | static const std::string s = "!$&'()*+,;="; |
105 | "%3c", // 60 | 103 | return s; |
106 | "=", // 61 | 104 | } |
107 | "%3e", // 62 | 105 | |
108 | "?", // 63 | 106 | std::string escapeHostAndPort(const std::string& s) |
109 | "@", // 64 | 107 | { return LLURI::escape(s, unreserved() + sub_delims() +":"); } |
110 | "A", // 65 | 108 | std::string escapePathComponent(const std::string& s) |
111 | "B", // 66 | 109 | { return LLURI::escape(s, unreserved() + sub_delims() + ":@"); } |
112 | "C", // 67 | 110 | std::string escapeQueryVariable(const std::string& s) |
113 | "D", // 68 | 111 | { return LLURI::escape(s, unreserved() + ":@!$'()*+,"); } // sub_delims - "&;=" + ":@" |
114 | "E", // 69 | 112 | std::string escapeQueryValue(const std::string& s) |
115 | "F", // 70 | 113 | { return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@" |
116 | "G", // 71 | 114 | } |
117 | "H", // 72 | ||
118 | "I", // 73 | ||
119 | "J", // 74 | ||
120 | "K", // 75 | ||
121 | "L", // 76 | ||
122 | "M", // 77 | ||
123 | "N", // 78 | ||
124 | "O", // 79 | ||
125 | "P", // 80 | ||
126 | "Q", // 81 | ||
127 | "R", // 82 | ||
128 | "S", // 83 | ||
129 | "T", // 84 | ||
130 | "U", // 85 | ||
131 | "V", // 86 | ||
132 | "W", // 87 | ||
133 | "X", // 88 | ||
134 | "Y", // 89 | ||
135 | "Z", // 90 | ||
136 | "%5b", // 91 | ||
137 | "%5c", // 92 | ||
138 | "%5d", // 93 | ||
139 | "%5e", // 94 | ||
140 | "_", // 95 | ||
141 | "%60", // 96 | ||
142 | "a", // 97 | ||
143 | "b", // 98 | ||
144 | "c", // 99 | ||
145 | "d", // 100 | ||
146 | "e", // 101 | ||
147 | "f", // 102 | ||
148 | "g", // 103 | ||
149 | "h", // 104 | ||
150 | "i", // 105 | ||
151 | "j", // 106 | ||
152 | "k", // 107 | ||
153 | "l", // 108 | ||
154 | "m", // 109 | ||
155 | "n", // 110 | ||
156 | "o", // 111 | ||
157 | "p", // 112 | ||
158 | "q", // 113 | ||
159 | "r", // 114 | ||
160 | "s", // 115 | ||
161 | "t", // 116 | ||
162 | "u", // 117 | ||
163 | "v", // 118 | ||
164 | "w", // 119 | ||
165 | "x", // 120 | ||
166 | "y", // 121 | ||
167 | "z", // 122 | ||
168 | "%7b", // 123 | ||
169 | "%7c", // 124 | ||
170 | "%7d", // 125 | ||
171 | "~", // 126 | ||
172 | "%7f", // 127 | ||
173 | "%80", // 128 | ||
174 | "%81", // 129 | ||
175 | "%82", // 130 | ||
176 | "%83", // 131 | ||
177 | "%84", // 132 | ||
178 | "%85", // 133 | ||
179 | "%86", // 134 | ||
180 | "%87", // 135 | ||
181 | "%88", // 136 | ||
182 | "%89", // 137 | ||
183 | "%8a", // 138 | ||
184 | "%8b", // 139 | ||
185 | "%8c", // 140 | ||
186 | "%8d", // 141 | ||
187 | "%8e", // 142 | ||
188 | "%8f", // 143 | ||
189 | "%90", // 144 | ||
190 | "%91", // 145 | ||
191 | "%92", // 146 | ||
192 | "%93", // 147 | ||
193 | "%94", // 148 | ||
194 | "%95", // 149 | ||
195 | "%96", // 150 | ||
196 | "%97", // 151 | ||
197 | "%98", // 152 | ||
198 | "%99", // 153 | ||
199 | "%9a", // 154 | ||
200 | "%9b", // 155 | ||
201 | "%9c", // 156 | ||
202 | "%9d", // 157 | ||
203 | "%9e", // 158 | ||
204 | "%9f", // 159 | ||
205 | "%a0", // 160 | ||
206 | "%a1", // 161 | ||
207 | "%a2", // 162 | ||
208 | "%a3", // 163 | ||
209 | "%a4", // 164 | ||
210 | "%a5", // 165 | ||
211 | "%a6", // 166 | ||
212 | "%a7", // 167 | ||
213 | "%a8", // 168 | ||
214 | "%a9", // 169 | ||
215 | "%aa", // 170 | ||
216 | "%ab", // 171 | ||
217 | "%ac", // 172 | ||
218 | "%ad", // 173 | ||
219 | "%ae", // 174 | ||
220 | "%af", // 175 | ||
221 | "%b0", // 176 | ||
222 | "%b1", // 177 | ||
223 | "%b2", // 178 | ||
224 | "%b3", // 179 | ||
225 | "%b4", // 180 | ||
226 | "%b5", // 181 | ||
227 | "%b6", // 182 | ||
228 | "%b7", // 183 | ||
229 | "%b8", // 184 | ||
230 | "%b9", // 185 | ||
231 | "%ba", // 186 | ||
232 | "%bb", // 187 | ||
233 | "%bc", // 188 | ||
234 | "%bd", // 189 | ||
235 | "%be", // 190 | ||
236 | "%bf", // 191 | ||
237 | "%c0", // 192 | ||
238 | "%c1", // 193 | ||
239 | "%c2", // 194 | ||
240 | "%c3", // 195 | ||
241 | "%c4", // 196 | ||
242 | "%c5", // 197 | ||
243 | "%c6", // 198 | ||
244 | "%c7", // 199 | ||
245 | "%c8", // 200 | ||
246 | "%c9", // 201 | ||
247 | "%ca", // 202 | ||
248 | "%cb", // 203 | ||
249 | "%cc", // 204 | ||
250 | "%cd", // 205 | ||
251 | "%ce", // 206 | ||
252 | "%cf", // 207 | ||
253 | "%d0", // 208 | ||
254 | "%d1", // 209 | ||
255 | "%d2", // 210 | ||
256 | "%d3", // 211 | ||
257 | "%d4", // 212 | ||
258 | "%d5", // 213 | ||
259 | "%d6", // 214 | ||
260 | "%d7", // 215 | ||
261 | "%d8", // 216 | ||
262 | "%d9", // 217 | ||
263 | "%da", // 218 | ||
264 | "%db", // 219 | ||
265 | "%dc", // 220 | ||
266 | "%dd", // 221 | ||
267 | "%de", // 222 | ||
268 | "%df", // 223 | ||
269 | "%e0", // 224 | ||
270 | "%e1", // 225 | ||
271 | "%e2", // 226 | ||
272 | "%e3", // 227 | ||
273 | "%e4", // 228 | ||
274 | "%e5", // 229 | ||
275 | "%e6", // 230 | ||
276 | "%e7", // 231 | ||
277 | "%e8", // 232 | ||
278 | "%e9", // 233 | ||
279 | "%ea", // 234 | ||
280 | "%eb", // 235 | ||
281 | "%ec", // 236 | ||
282 | "%ed", // 237 | ||
283 | "%ee", // 238 | ||
284 | "%ef", // 239 | ||
285 | "%f0", // 240 | ||
286 | "%f1", // 241 | ||
287 | "%f2", // 242 | ||
288 | "%f3", // 243 | ||
289 | "%f4", // 244 | ||
290 | "%f5", // 245 | ||
291 | "%f6", // 246 | ||
292 | "%f7", // 247 | ||
293 | "%f8", // 248 | ||
294 | "%f9", // 249 | ||
295 | "%fa", // 250 | ||
296 | "%fb", // 251 | ||
297 | "%fc", // 252 | ||
298 | "%fd", // 253 | ||
299 | "%fe", // 254 | ||
300 | "%ff" // 255 | ||
301 | }; | ||
302 | 115 | ||
303 | LLURI::LLURI() | 116 | LLURI::LLURI() |
304 | { | 117 | { |
@@ -371,24 +184,23 @@ LLURI::~LLURI() | |||
371 | { | 184 | { |
372 | } | 185 | } |
373 | 186 | ||
374 | 187 | // static | |
375 | LLURI LLURI::buildHTTP(const std::string& host_port, | 188 | LLURI LLURI::buildHTTP(const std::string& prefix, |
376 | const LLSD& path) | 189 | const LLSD& path) |
377 | { | 190 | { |
378 | LLURI result; | 191 | LLURI result; |
379 | 192 | ||
380 | // TODO: deal with '/' '?' '#' in host_port | 193 | // TODO: deal with '/' '?' '#' in host_port |
381 | S32 index = host_port.find("://"); | 194 | if (prefix.find("://") != prefix.npos) |
382 | if (index != host_port.npos) | ||
383 | { | 195 | { |
384 | // The scheme is part of the host_port | 196 | // it is a prefix |
385 | result.mScheme = ""; | 197 | result = LLURI(prefix); |
386 | result.mEscapedAuthority = escape(host_port); | ||
387 | } | 198 | } |
388 | else | 199 | else |
389 | { | 200 | { |
390 | result.mScheme = "HTTP"; | 201 | // it is just a host and optional port |
391 | result.mEscapedAuthority = "//" + escape(host_port); | 202 | result.mScheme = "http"; |
203 | result.mEscapedAuthority = escapeHostAndPort(prefix); | ||
392 | } | 204 | } |
393 | 205 | ||
394 | if (path.isArray()) | 206 | if (path.isArray()) |
@@ -399,20 +211,20 @@ LLURI LLURI::buildHTTP(const std::string& host_port, | |||
399 | ++it) | 211 | ++it) |
400 | { | 212 | { |
401 | lldebugs << "PATH: inserting " << it->asString() << llendl; | 213 | lldebugs << "PATH: inserting " << it->asString() << llendl; |
402 | result.mEscapedPath += "/" + escape(it->asString()); | 214 | result.mEscapedPath += "/" + escapePathComponent(it->asString()); |
403 | } | 215 | } |
404 | } | 216 | } |
405 | result.mEscapedOpaque = result.mEscapedAuthority + | 217 | result.mEscapedOpaque = "//" + result.mEscapedAuthority + |
406 | result.mEscapedPath; | 218 | result.mEscapedPath; |
407 | return result; | 219 | return result; |
408 | } | 220 | } |
409 | 221 | ||
410 | // static | 222 | // static |
411 | LLURI LLURI::buildHTTP(const std::string& host_port, | 223 | LLURI LLURI::buildHTTP(const std::string& prefix, |
412 | const LLSD& path, | 224 | const LLSD& path, |
413 | const LLSD& query) | 225 | const LLSD& query) |
414 | { | 226 | { |
415 | LLURI result = buildHTTP(host_port, path); | 227 | LLURI result = buildHTTP(prefix, path); |
416 | // break out and escape each query component | 228 | // break out and escape each query component |
417 | if (query.isMap()) | 229 | if (query.isMap()) |
418 | { | 230 | { |
@@ -420,8 +232,8 @@ LLURI LLURI::buildHTTP(const std::string& host_port, | |||
420 | it != query.endMap(); | 232 | it != query.endMap(); |
421 | it++) | 233 | it++) |
422 | { | 234 | { |
423 | result.mEscapedQuery += escape(it->first) + | 235 | result.mEscapedQuery += escapeQueryVariable(it->first) + |
424 | (it->second.isUndefined() ? "" : "=" + it->second.asString()) + | 236 | (it->second.isUndefined() ? "" : "=" + escapeQueryValue(it->second.asString())) + |
425 | "&"; | 237 | "&"; |
426 | } | 238 | } |
427 | if (query.size() > 0) | 239 | if (query.size() > 0) |
@@ -433,8 +245,61 @@ LLURI LLURI::buildHTTP(const std::string& host_port, | |||
433 | } | 245 | } |
434 | 246 | ||
435 | // static | 247 | // static |
248 | LLURI LLURI::buildHTTP(const std::string& host, | ||
249 | const U32& port, | ||
250 | const LLSD& path) | ||
251 | { | ||
252 | return LLURI::buildHTTP(llformat("%s:%u", host.c_str(), port), path); | ||
253 | } | ||
254 | |||
255 | // static | ||
256 | LLURI LLURI::buildHTTP(const std::string& host, | ||
257 | const U32& port, | ||
258 | const LLSD& path, | ||
259 | const LLSD& query) | ||
260 | { | ||
261 | return LLURI::buildHTTP(llformat("%s:%u", host.c_str(), port), path, query); | ||
262 | } | ||
263 | |||
264 | |||
265 | namespace { | ||
266 | LLURI buildBackboneURL(LLApp* app, | ||
267 | const std::string& p1 = "", | ||
268 | const std::string& p2 = "", | ||
269 | const std::string& p3 = "") | ||
270 | { | ||
271 | std::string host = "localhost:12040"; | ||
272 | |||
273 | if (app) | ||
274 | { | ||
275 | host = app->getOption("backbone-host-port").asString(); | ||
276 | } | ||
277 | |||
278 | LLSD path = LLSD::emptyArray(); | ||
279 | if (!p1.empty()) path.append(p1); | ||
280 | if (!p2.empty()) path.append(p2); | ||
281 | if (!p3.empty()) path.append(p3); | ||
282 | |||
283 | return LLURI::buildHTTP(host, path); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | |||
288 | // static | ||
436 | LLURI LLURI::buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app) | 289 | LLURI LLURI::buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app) |
437 | { | 290 | { |
291 | return buildBackboneURL(app, "agent", agent_id.asString(), "presence"); | ||
292 | } | ||
293 | |||
294 | // static | ||
295 | LLURI LLURI::buildBulkAgentPresenceURI(LLApp* app) | ||
296 | { | ||
297 | return buildBackboneURL(app, "agent", "presence"); | ||
298 | } | ||
299 | |||
300 | // static | ||
301 | LLURI LLURI::buildBulkAgentNamesURI(LLApp* app) | ||
302 | { | ||
438 | std::string host = "localhost:12040"; | 303 | std::string host = "localhost:12040"; |
439 | 304 | ||
440 | if (app) | 305 | if (app) |
@@ -444,14 +309,19 @@ LLURI LLURI::buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app) | |||
444 | 309 | ||
445 | LLSD path = LLSD::emptyArray(); | 310 | LLSD path = LLSD::emptyArray(); |
446 | path.append("agent"); | 311 | path.append("agent"); |
447 | path.append(agent_id); | 312 | path.append("names"); |
448 | path.append("presence"); | ||
449 | 313 | ||
450 | return buildHTTP(host, path); | 314 | return buildHTTP(host, path); |
451 | } | 315 | } |
452 | 316 | ||
453 | // static | 317 | // static |
454 | LLURI LLURI::buildBulkAgentPresenceURI(LLApp* app) | 318 | LLURI LLURI::buildAgentSessionURI(const LLUUID& agent_id, LLApp* app) |
319 | { | ||
320 | return buildBackboneURL(app, "agent", agent_id.asString(), "session"); | ||
321 | } | ||
322 | |||
323 | // static | ||
324 | LLURI LLURI::buildInventoryHostURI(const LLUUID& agent_id, LLApp* app) | ||
455 | { | 325 | { |
456 | std::string host = "localhost:12040"; | 326 | std::string host = "localhost:12040"; |
457 | 327 | ||
@@ -462,13 +332,15 @@ LLURI LLURI::buildBulkAgentPresenceURI(LLApp* app) | |||
462 | 332 | ||
463 | LLSD path = LLSD::emptyArray(); | 333 | LLSD path = LLSD::emptyArray(); |
464 | path.append("agent"); | 334 | path.append("agent"); |
465 | path.append("presence"); | 335 | path.append(agent_id); |
336 | path.append("inventory"); | ||
337 | path.append("host"); | ||
466 | 338 | ||
467 | return buildHTTP(host, path); | 339 | return buildHTTP(host, path); |
468 | } | 340 | } |
469 | 341 | ||
470 | // static | 342 | // static |
471 | LLURI LLURI::buildAgentSessionURI(const LLUUID& agent_id, LLApp* app) | 343 | LLURI LLURI::buildAgentNameURI(const LLUUID& agent_id, LLApp* app) |
472 | { | 344 | { |
473 | std::string host = "localhost:12040"; | 345 | std::string host = "localhost:12040"; |
474 | 346 | ||
@@ -480,7 +352,7 @@ LLURI LLURI::buildAgentSessionURI(const LLUUID& agent_id, LLApp* app) | |||
480 | LLSD path = LLSD::emptyArray(); | 352 | LLSD path = LLSD::emptyArray(); |
481 | path.append("agent"); | 353 | path.append("agent"); |
482 | path.append(agent_id); | 354 | path.append(agent_id); |
483 | path.append("session"); | 355 | path.append("name"); |
484 | 356 | ||
485 | return buildHTTP(host, path); | 357 | return buildHTTP(host, path); |
486 | } | 358 | } |
@@ -636,43 +508,3 @@ LLSD LLURI::queryMap(std::string escaped_query_string) | |||
636 | return result; | 508 | return result; |
637 | } | 509 | } |
638 | 510 | ||
639 | // static | ||
640 | std::string LLURI::escape(const std::string& str) | ||
641 | { | ||
642 | std::ostringstream ostr; | ||
643 | std::string::const_iterator it = str.begin(); | ||
644 | std::string::const_iterator end = str.end(); | ||
645 | S32 c; | ||
646 | for(; it != end; ++it) | ||
647 | { | ||
648 | c = (S32)(*it); | ||
649 | ostr << ESCAPED_CHARACTERS[c]; | ||
650 | } | ||
651 | return ostr.str(); | ||
652 | } | ||
653 | |||
654 | // static | ||
655 | std::string LLURI::unescape(const std::string& str) | ||
656 | { | ||
657 | std::ostringstream ostr; | ||
658 | std::string::const_iterator it = str.begin(); | ||
659 | std::string::const_iterator end = str.end(); | ||
660 | for(; it != end; ++it) | ||
661 | { | ||
662 | if((*it) == '%') | ||
663 | { | ||
664 | ++it; | ||
665 | if(it == end) break; | ||
666 | U8 c = hex_as_nybble(*it++); | ||
667 | c = c << 4; | ||
668 | if (it == end) break; | ||
669 | c |= hex_as_nybble(*it); | ||
670 | ostr.put((char)c); | ||
671 | } | ||
672 | else | ||
673 | { | ||
674 | ostr.put(*it); | ||
675 | } | ||
676 | } | ||
677 | return ostr.str(); | ||
678 | } | ||
diff --git a/linden/indra/llcommon/lluri.h b/linden/indra/llcommon/lluri.h index f69472f..60b3d48 100644 --- a/linden/indra/llcommon/lluri.h +++ b/linden/indra/llcommon/lluri.h | |||
@@ -45,54 +45,70 @@ class LLApp; | |||
45 | class LLURI | 45 | class LLURI |
46 | { | 46 | { |
47 | public: | 47 | public: |
48 | LLURI(); | 48 | LLURI(); |
49 | LLURI(const std::string& escaped_str); | 49 | LLURI(const std::string& escaped_str); |
50 | // construct from escaped string, as would be transmitted on the net | 50 | // construct from escaped string, as would be transmitted on the net |
51 | 51 | ||
52 | ~LLURI(); | 52 | ~LLURI(); |
53 | 53 | ||
54 | static LLURI buildHTTP(const std::string& host_port, | 54 | static LLURI buildHTTP(const std::string& prefix, |
55 | const LLSD& path); | 55 | const LLSD& path); |
56 | static LLURI buildHTTP(const std::string& host_port, | 56 | static LLURI buildHTTP(const std::string& prefix, |
57 | const LLSD& path, | 57 | const LLSD& path, |
58 | const LLSD& query); | 58 | const LLSD& query); |
59 | 59 | // prefix is either a full URL prefix of the form "http://example.com:8080", | |
60 | std::string asString() const; | 60 | // or it can be simply a host and optional port like "example.com" or |
61 | // the whole URI, escaped as needed | 61 | // "example.com:8080", in these cases, the "http://" will be added |
62 | 62 | ||
63 | // Parts of a URI | 63 | static LLURI buildHTTP(const std::string& host, |
64 | // These functions return parts of the decoded URI. The returned | 64 | const U32& port, |
65 | // strings are un-escaped as needed | 65 | const LLSD& path); |
66 | 66 | static LLURI buildHTTP(const std::string& host, | |
67 | // for all schemes | 67 | const U32& port, |
68 | std::string scheme() const; // ex.: "http", note lack of colon | 68 | const LLSD& path, |
69 | std::string opaque() const; // everything after the colon | 69 | const LLSD& query); |
70 | |||
71 | |||
72 | std::string asString() const; | ||
73 | // the whole URI, escaped as needed | ||
74 | |||
75 | // Parts of a URI | ||
76 | // These functions return parts of the decoded URI. The returned | ||
77 | // strings are un-escaped as needed | ||
78 | |||
79 | // for all schemes | ||
80 | std::string scheme() const; // ex.: "http", note lack of colon | ||
81 | std::string opaque() const; // everything after the colon | ||
82 | |||
83 | // for schemes that follow path like syntax (http, https, ftp) | ||
84 | std::string authority() const; // ex.: "host.com:80" | ||
85 | std::string hostName() const; // ex.: "host.com" | ||
86 | U16 hostPort() const; // ex.: 80, will include implicit port | ||
87 | std::string path() const; // ex.: "/abc/def", includes leading slash | ||
88 | // LLSD pathArray() const; // above decoded into an array of strings | ||
89 | std::string query() const; // ex.: "x=34", section after "?" | ||
90 | LLSD queryMap() const; // above decoded into a map | ||
91 | static LLSD queryMap(std::string escaped_query_string); | ||
70 | 92 | ||
71 | // for schemes that follow path like syntax (http, https, ftp) | 93 | // Escaping Utilities |
72 | std::string authority() const; // ex.: "bob@host.com:80" | 94 | // Escape a string by urlencoding all the characters that aren't in the allowed string. |
73 | std::string hostName() const; // ex.: "host.com" | 95 | static std::string escape(const std::string& str, const std::string & allowed); |
74 | U16 hostPort() const; // ex.: 80, will include implicit port | 96 | static std::string unescape(const std::string& str); |
75 | std::string path() const; // ex.: "/abc/def", includes leading slash | ||
76 | // LLSD pathArray() const; // above decoded into an array of strings | ||
77 | std::string query() const; // ex.: "x=34", section after "?" | ||
78 | LLSD queryMap() const; // above decoded into a map | ||
79 | static LLSD queryMap(std::string escaped_query_string); | ||
80 | |||
81 | // Escaping Utilities | ||
82 | static std::string escape(const std::string& str); | ||
83 | static std::string unescape(const std::string& str); | ||
84 | 97 | ||
85 | // Functions for building specific URIs for web services | 98 | // Functions for building specific URIs for web services |
86 | static LLURI buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app); | 99 | static LLURI buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app); |
87 | static LLURI buildBulkAgentPresenceURI(LLApp* app); | 100 | static LLURI buildBulkAgentPresenceURI(LLApp* app); |
101 | static LLURI buildBulkAgentNamesURI(LLApp* app); | ||
88 | static LLURI buildAgentSessionURI(const LLUUID& agent_id, LLApp* app); | 102 | static LLURI buildAgentSessionURI(const LLUUID& agent_id, LLApp* app); |
89 | static LLURI buildAgentLoginInfoURI(const LLUUID& agent_id, const std::string& dataserver); | 103 | static LLURI buildAgentLoginInfoURI(const LLUUID& agent_id, const std::string& dataserver); |
104 | static LLURI buildInventoryHostURI(const LLUUID& agent_id, LLApp* app); | ||
105 | static LLURI buildAgentNameURI(const LLUUID& agent_id, LLApp* app); | ||
90 | private: | 106 | private: |
91 | std::string mScheme; | 107 | std::string mScheme; |
92 | std::string mEscapedOpaque; | 108 | std::string mEscapedOpaque; |
93 | std::string mEscapedAuthority; | 109 | std::string mEscapedAuthority; |
94 | std::string mEscapedPath; | 110 | std::string mEscapedPath; |
95 | std::string mEscapedQuery; | 111 | std::string mEscapedQuery; |
96 | }; | 112 | }; |
97 | 113 | ||
98 | #endif // LL_LLURI_H | 114 | #endif // LL_LLURI_H |
diff --git a/linden/indra/llcommon/llversion.h b/linden/indra/llcommon/llversion.h index af21f72..a3e5152 100644 --- a/linden/indra/llcommon/llversion.h +++ b/linden/indra/llcommon/llversion.h | |||
@@ -32,9 +32,9 @@ | |||
32 | 32 | ||
33 | // MUST ALSO change version number in secondlife setup.nsi | 33 | // MUST ALSO change version number in secondlife setup.nsi |
34 | const S32 LL_VERSION_MAJOR = 1; | 34 | const S32 LL_VERSION_MAJOR = 1; |
35 | const S32 LL_VERSION_MINOR = 13; | 35 | const S32 LL_VERSION_MINOR = 14; |
36 | const S32 LL_VERSION_PATCH = 3; | 36 | const S32 LL_VERSION_PATCH = 0; |
37 | const S32 LL_VERSION_BUILD = 2; | 37 | const S32 LL_VERSION_BUILD = 0; |
38 | 38 | ||
39 | 39 | ||
40 | 40 | ||
diff --git a/linden/indra/llcommon/llworkerthread.cpp b/linden/indra/llcommon/llworkerthread.cpp index 3190046..4f99393 100644 --- a/linden/indra/llcommon/llworkerthread.cpp +++ b/linden/indra/llcommon/llworkerthread.cpp | |||
@@ -33,98 +33,86 @@ | |||
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | //============================================================================ | 35 | //============================================================================ |
36 | |||
37 | /*static*/ LLWorkerThread* LLWorkerThread::sLocal = NULL; | ||
38 | /*static*/ std::set<LLWorkerThread*> LLWorkerThread::sThreadList; | ||
39 | |||
40 | //============================================================================ | ||
41 | // Run on MAIN thread | 36 | // Run on MAIN thread |
42 | 37 | ||
43 | //static | 38 | LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) : |
44 | void LLWorkerThread::initClass(bool local_is_threaded, bool local_run_always) | 39 | LLQueuedThread(name, threaded), |
40 | mWorkerAPRPoolp(NULL) | ||
45 | { | 41 | { |
46 | if (!sLocal) | 42 | apr_pool_create(&mWorkerAPRPoolp, NULL); |
47 | { | 43 | mDeleteMutex = new LLMutex(getAPRPool()); |
48 | sLocal = new LLWorkerThread(local_is_threaded, local_run_always); | ||
49 | } | ||
50 | } | 44 | } |
51 | 45 | ||
52 | //static | 46 | LLWorkerThread::~LLWorkerThread() |
53 | void LLWorkerThread::cleanupClass() | ||
54 | { | 47 | { |
55 | if (sLocal) | 48 | // Delete any workers in the delete queue (should be safe - had better be!) |
49 | if (!mDeleteList.empty()) | ||
56 | { | 50 | { |
57 | while (sLocal->getPending()) | 51 | llwarns << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size() |
58 | { | 52 | << " entries in delete list." << llendl; |
59 | sLocal->update(0); | ||
60 | } | ||
61 | delete sLocal; | ||
62 | sLocal = NULL; | ||
63 | llassert(sThreadList.size() == 0); | ||
64 | } | 53 | } |
65 | } | ||
66 | 54 | ||
67 | //static | 55 | delete mDeleteMutex; |
68 | S32 LLWorkerThread::updateClass(U32 ms_elapsed) | 56 | |
69 | { | 57 | // ~LLQueuedThread() will be called here |
70 | for (std::set<LLWorkerThread*>::iterator iter = sThreadList.begin(); iter != sThreadList.end(); iter++) | ||
71 | { | ||
72 | (*iter)->update(ms_elapsed); | ||
73 | } | ||
74 | return getAllPending(); | ||
75 | } | 58 | } |
76 | 59 | ||
77 | //static | 60 | // virtual |
78 | S32 LLWorkerThread::getAllPending() | 61 | S32 LLWorkerThread::update(U32 max_time_ms) |
79 | { | 62 | { |
80 | S32 res = 0; | 63 | S32 res = LLQueuedThread::update(max_time_ms); |
81 | for (std::set<LLWorkerThread*>::iterator iter = sThreadList.begin(); iter != sThreadList.end(); iter++) | 64 | // Delete scheduled workers |
65 | std::vector<LLWorkerClass*> delete_list; | ||
66 | std::vector<LLWorkerClass*> abort_list; | ||
67 | mDeleteMutex->lock(); | ||
68 | for (delete_list_t::iterator iter = mDeleteList.begin(); | ||
69 | iter != mDeleteList.end(); ) | ||
82 | { | 70 | { |
83 | res += (*iter)->getPending(); | 71 | delete_list_t::iterator curiter = iter++; |
72 | LLWorkerClass* worker = *curiter; | ||
73 | if (worker->deleteOK()) | ||
74 | { | ||
75 | if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED)) | ||
76 | { | ||
77 | delete_list.push_back(worker); | ||
78 | mDeleteList.erase(curiter); | ||
79 | } | ||
80 | else if (!worker->getFlags(LLWorkerClass::WCF_ABORT_REQUESTED)) | ||
81 | { | ||
82 | abort_list.push_back(worker); | ||
83 | } | ||
84 | } | ||
84 | } | 85 | } |
85 | return res; | 86 | mDeleteMutex->unlock(); |
86 | } | 87 | // abort and delete after releasing mutex |
87 | 88 | for (std::vector<LLWorkerClass*>::iterator iter = abort_list.begin(); | |
88 | //static | 89 | iter != abort_list.end(); ++iter) |
89 | void LLWorkerThread::pauseAll() | ||
90 | { | ||
91 | for (std::set<LLWorkerThread*>::iterator iter = sThreadList.begin(); iter != sThreadList.end(); iter++) | ||
92 | { | 90 | { |
93 | (*iter)->pause(); | 91 | (*iter)->abortWork(false); |
94 | } | 92 | } |
95 | } | 93 | for (std::vector<LLWorkerClass*>::iterator iter = delete_list.begin(); |
96 | 94 | iter != delete_list.end(); ++iter) | |
97 | //static | ||
98 | void LLWorkerThread::waitOnAllPending() | ||
99 | { | ||
100 | for (std::set<LLWorkerThread*>::iterator iter = sThreadList.begin(); iter != sThreadList.end(); iter++) | ||
101 | { | 95 | { |
102 | (*iter)->waitOnPending(); | 96 | LLWorkerClass* worker = *iter; |
97 | if (worker->mRequestHandle) | ||
98 | { | ||
99 | // Finished but not completed | ||
100 | completeRequest(worker->mRequestHandle); | ||
101 | worker->mRequestHandle = LLWorkerThread::nullHandle(); | ||
102 | worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK); | ||
103 | } | ||
104 | delete *iter; | ||
103 | } | 105 | } |
106 | return res; | ||
104 | } | 107 | } |
105 | 108 | ||
106 | //---------------------------------------------------------------------------- | 109 | //---------------------------------------------------------------------------- |
107 | 110 | ||
108 | LLWorkerThread::LLWorkerThread(bool threaded, bool runalways) : | 111 | LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority) |
109 | LLQueuedThread("Worker", threaded, runalways) | ||
110 | { | ||
111 | sThreadList.insert(this); | ||
112 | } | ||
113 | |||
114 | LLWorkerThread::~LLWorkerThread() | ||
115 | { | ||
116 | llverify(sThreadList.erase(this) == 1); | ||
117 | // ~LLQueuedThread() will be called here | ||
118 | } | ||
119 | |||
120 | //---------------------------------------------------------------------------- | ||
121 | |||
122 | |||
123 | LLWorkerThread::handle_t LLWorkerThread::add(LLWorkerClass* workerclass, S32 param, U32 priority) | ||
124 | { | 112 | { |
125 | handle_t handle = generateHandle(); | 113 | handle_t handle = generateHandle(); |
126 | 114 | ||
127 | Request* req = new Request(handle, priority, workerclass, param); | 115 | WorkRequest* req = new WorkRequest(handle, priority, workerclass, param); |
128 | 116 | ||
129 | bool res = addRequest(req); | 117 | bool res = addRequest(req); |
130 | if (!res) | 118 | if (!res) |
@@ -137,63 +125,80 @@ LLWorkerThread::handle_t LLWorkerThread::add(LLWorkerClass* workerclass, S32 par | |||
137 | return handle; | 125 | return handle; |
138 | } | 126 | } |
139 | 127 | ||
140 | //============================================================================ | 128 | void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass) |
141 | // Runs on its OWN thread | ||
142 | |||
143 | bool LLWorkerThread::processRequest(QueuedRequest* qreq) | ||
144 | { | 129 | { |
145 | Request *req = (Request*)qreq; | 130 | mDeleteMutex->lock(); |
146 | 131 | mDeleteList.push_back(workerclass); | |
147 | req->getWorkerClass()->setWorking(true); | 132 | mDeleteMutex->unlock(); |
148 | |||
149 | bool complete = req->getWorkerClass()->doWork(req->getParam()); | ||
150 | |||
151 | req->getWorkerClass()->setWorking(false); | ||
152 | |||
153 | LLThread::yield(); // worker thread should yield after each request | ||
154 | |||
155 | return complete; | ||
156 | } | 133 | } |
157 | 134 | ||
158 | //============================================================================ | 135 | //============================================================================ |
136 | // Runs on its OWN thread | ||
159 | 137 | ||
160 | LLWorkerThread::Request::Request(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param) : | 138 | LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param) : |
161 | LLQueuedThread::QueuedRequest(handle, priority), | 139 | LLQueuedThread::QueuedRequest(handle, priority), |
162 | mWorkerClass(workerclass), | 140 | mWorkerClass(workerclass), |
163 | mParam(param) | 141 | mParam(param) |
164 | { | 142 | { |
165 | } | 143 | } |
166 | 144 | ||
167 | void LLWorkerThread::Request::deleteRequest() | 145 | LLWorkerThread::WorkRequest::~WorkRequest() |
146 | { | ||
147 | } | ||
148 | |||
149 | // virtual (required for access by LLWorkerThread) | ||
150 | void LLWorkerThread::WorkRequest::deleteRequest() | ||
168 | { | 151 | { |
169 | LLQueuedThread::QueuedRequest::deleteRequest(); | 152 | LLQueuedThread::QueuedRequest::deleteRequest(); |
170 | } | 153 | } |
171 | 154 | ||
155 | // virtual | ||
156 | bool LLWorkerThread::WorkRequest::processRequest() | ||
157 | { | ||
158 | LLWorkerClass* workerclass = getWorkerClass(); | ||
159 | workerclass->setWorking(true); | ||
160 | bool complete = workerclass->doWork(getParam()); | ||
161 | workerclass->setWorking(false); | ||
162 | return complete; | ||
163 | } | ||
164 | |||
165 | // virtual | ||
166 | void LLWorkerThread::WorkRequest::finishRequest(bool completed) | ||
167 | { | ||
168 | LLWorkerClass* workerclass = getWorkerClass(); | ||
169 | workerclass->finishWork(getParam(), completed); | ||
170 | U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED); | ||
171 | workerclass->setFlags(flags); | ||
172 | } | ||
173 | |||
172 | //============================================================================ | 174 | //============================================================================ |
173 | // LLWorkerClass:: operates in main thread | 175 | // LLWorkerClass:: operates in main thread |
174 | 176 | ||
175 | LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& name) | 177 | LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& name) |
176 | : mWorkerThread(workerthread), | 178 | : mWorkerThread(workerthread), |
177 | mWorkerClassName(name), | 179 | mWorkerClassName(name), |
178 | mWorkHandle(LLWorkerThread::nullHandle()), | 180 | mRequestHandle(LLWorkerThread::nullHandle()), |
181 | mMutex(workerthread->getWorkerAPRPool()), | ||
179 | mWorkFlags(0) | 182 | mWorkFlags(0) |
180 | { | 183 | { |
181 | if (!mWorkerThread) | 184 | if (!mWorkerThread) |
182 | { | 185 | { |
183 | mWorkerThread = LLWorkerThread::sLocal; | 186 | llerrs << "LLWorkerClass() called with NULL workerthread: " << name << llendl; |
184 | } | 187 | } |
185 | } | 188 | } |
189 | |||
186 | LLWorkerClass::~LLWorkerClass() | 190 | LLWorkerClass::~LLWorkerClass() |
187 | { | 191 | { |
188 | if (mWorkHandle != LLWorkerThread::nullHandle()) | 192 | llassert_always(!(mWorkFlags & WCF_WORKING)); |
193 | llassert_always(mWorkFlags & WCF_DELETE_REQUESTED); | ||
194 | if (mRequestHandle != LLWorkerThread::nullHandle()) | ||
189 | { | 195 | { |
190 | LLWorkerThread::Request* workreq = (LLWorkerThread::Request*)mWorkerThread->getRequest(mWorkHandle); | 196 | LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle); |
191 | if (!workreq) | 197 | if (!workreq) |
192 | { | 198 | { |
193 | llerrs << "LLWorkerClass destroyed with stale work handle" << llendl; | 199 | llerrs << "LLWorkerClass destroyed with stale work handle" << llendl; |
194 | } | 200 | } |
195 | if (workreq->getStatus() != LLWorkerThread::STATUS_ABORT && | 201 | if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED && |
196 | workreq->getStatus() != LLWorkerThread::STATUS_ABORTED && | ||
197 | workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE) | 202 | workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE) |
198 | { | 203 | { |
199 | llerrs << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << llendl; | 204 | llerrs << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << llendl; |
@@ -203,21 +208,58 @@ LLWorkerClass::~LLWorkerClass() | |||
203 | 208 | ||
204 | void LLWorkerClass::setWorkerThread(LLWorkerThread* workerthread) | 209 | void LLWorkerClass::setWorkerThread(LLWorkerThread* workerthread) |
205 | { | 210 | { |
206 | if (mWorkHandle != LLWorkerThread::nullHandle()) | 211 | mMutex.lock(); |
212 | if (mRequestHandle != LLWorkerThread::nullHandle()) | ||
207 | { | 213 | { |
208 | llerrs << "LLWorkerClass attempt to change WorkerThread with active worker!" << llendl; | 214 | llerrs << "LLWorkerClass attempt to change WorkerThread with active worker!" << llendl; |
209 | } | 215 | } |
210 | mWorkerThread = workerthread; | 216 | mWorkerThread = workerthread; |
217 | mMutex.unlock(); | ||
218 | } | ||
219 | |||
220 | //---------------------------------------------------------------------------- | ||
221 | |||
222 | //virtual | ||
223 | void LLWorkerClass::finishWork(S32 param, bool success) | ||
224 | { | ||
225 | } | ||
226 | |||
227 | //virtual | ||
228 | bool LLWorkerClass::deleteOK() | ||
229 | { | ||
230 | return true; // default always OK | ||
231 | } | ||
232 | |||
233 | //---------------------------------------------------------------------------- | ||
234 | |||
235 | // Called from worker thread | ||
236 | void LLWorkerClass::setWorking(bool working) | ||
237 | { | ||
238 | mMutex.lock(); | ||
239 | if (working) | ||
240 | { | ||
241 | llassert_always(!(mWorkFlags & WCF_WORKING)); | ||
242 | setFlags(WCF_WORKING); | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | llassert_always((mWorkFlags & WCF_WORKING)); | ||
247 | clearFlags(WCF_WORKING); | ||
248 | } | ||
249 | mMutex.unlock(); | ||
211 | } | 250 | } |
212 | 251 | ||
213 | //---------------------------------------------------------------------------- | 252 | //---------------------------------------------------------------------------- |
214 | 253 | ||
215 | bool LLWorkerClass::yield() | 254 | bool LLWorkerClass::yield() |
216 | { | 255 | { |
217 | llassert(mWorkFlags & WCF_WORKING); | ||
218 | LLThread::yield(); | 256 | LLThread::yield(); |
219 | mWorkerThread->checkPause(); | 257 | mWorkerThread->checkPause(); |
220 | return (getFlags() & WCF_ABORT_REQUESTED) ? true : false; | 258 | bool res; |
259 | mMutex.lock(); | ||
260 | res = (getFlags() & WCF_ABORT_REQUESTED) ? true : false; | ||
261 | mMutex.unlock(); | ||
262 | return res; | ||
221 | } | 263 | } |
222 | 264 | ||
223 | //---------------------------------------------------------------------------- | 265 | //---------------------------------------------------------------------------- |
@@ -225,7 +267,9 @@ bool LLWorkerClass::yield() | |||
225 | // calls startWork, adds doWork() to queue | 267 | // calls startWork, adds doWork() to queue |
226 | void LLWorkerClass::addWork(S32 param, U32 priority) | 268 | void LLWorkerClass::addWork(S32 param, U32 priority) |
227 | { | 269 | { |
228 | if (mWorkHandle != LLWorkerThread::nullHandle()) | 270 | mMutex.lock(); |
271 | llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK))); | ||
272 | if (mRequestHandle != LLWorkerThread::nullHandle()) | ||
229 | { | 273 | { |
230 | llerrs << "LLWorkerClass attempt to add work with active worker!" << llendl; | 274 | llerrs << "LLWorkerClass attempt to add work with active worker!" << llendl; |
231 | } | 275 | } |
@@ -233,70 +277,93 @@ void LLWorkerClass::addWork(S32 param, U32 priority) | |||
233 | // llinfos << "addWork: " << mWorkerClassName << " Param: " << param << llendl; | 277 | // llinfos << "addWork: " << mWorkerClassName << " Param: " << param << llendl; |
234 | #endif | 278 | #endif |
235 | startWork(param); | 279 | startWork(param); |
236 | mWorkHandle = mWorkerThread->add(this, param, priority); | 280 | clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED); |
281 | setFlags(WCF_HAVE_WORK); | ||
282 | mRequestHandle = mWorkerThread->addWorkRequest(this, param, priority); | ||
283 | mMutex.unlock(); | ||
237 | } | 284 | } |
238 | 285 | ||
239 | void LLWorkerClass::abortWork() | 286 | void LLWorkerClass::abortWork(bool autocomplete) |
240 | { | 287 | { |
288 | mMutex.lock(); | ||
241 | #if _DEBUG | 289 | #if _DEBUG |
242 | // LLWorkerThread::Request* workreq = mWorkerThread->getRequest(mWorkHandle); | 290 | // LLWorkerThread::WorkRequest* workreq = mWorkerThread->getRequest(mRequestHandle); |
243 | // if (workreq) | 291 | // if (workreq) |
244 | // llinfos << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << llendl; | 292 | // llinfos << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << llendl; |
245 | #endif | 293 | #endif |
246 | mWorkerThread->abortRequest(mWorkHandle); | 294 | if (mRequestHandle != LLWorkerThread::nullHandle()) |
247 | setFlags(WCF_ABORT_REQUESTED); | 295 | { |
296 | mWorkerThread->abortRequest(mRequestHandle, autocomplete); | ||
297 | mWorkerThread->setPriority(mRequestHandle, LLQueuedThread::PRIORITY_IMMEDIATE); | ||
298 | setFlags(WCF_ABORT_REQUESTED); | ||
299 | } | ||
300 | mMutex.unlock(); | ||
248 | } | 301 | } |
249 | 302 | ||
250 | // if doWork is complete or aborted, call endWork() and return true | 303 | // if doWork is complete or aborted, call endWork() and return true |
251 | bool LLWorkerClass::checkWork() | 304 | bool LLWorkerClass::checkWork(bool aborting) |
252 | { | 305 | { |
306 | LLMutexLock lock(&mMutex); | ||
253 | bool complete = false, abort = false; | 307 | bool complete = false, abort = false; |
254 | LLWorkerThread::Request* workreq = (LLWorkerThread::Request*)mWorkerThread->getRequest(mWorkHandle); | 308 | if (mRequestHandle != LLWorkerThread::nullHandle()) |
255 | llassert(workreq); | ||
256 | if (getFlags(WCF_ABORT_REQUESTED) || workreq->getStatus() == LLWorkerThread::STATUS_ABORTED) | ||
257 | { | 309 | { |
258 | complete = true; | 310 | LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle); |
259 | abort = true; | 311 | llassert_always(workreq); |
312 | LLQueuedThread::status_t status = workreq->getStatus(); | ||
313 | if (status == LLWorkerThread::STATUS_ABORTED) | ||
314 | { | ||
315 | complete = true; | ||
316 | abort = true; | ||
317 | } | ||
318 | else if (status == LLWorkerThread::STATUS_COMPLETE) | ||
319 | { | ||
320 | complete = true; | ||
321 | } | ||
322 | else | ||
323 | { | ||
324 | llassert_always(!aborting || (workreq->getFlags() & LLQueuedThread::FLAG_ABORT)); | ||
325 | } | ||
326 | if (complete) | ||
327 | { | ||
328 | llassert_always(!(getFlags(WCF_WORKING))); | ||
329 | endWork(workreq->getParam(), abort); | ||
330 | mWorkerThread->completeRequest(mRequestHandle); | ||
331 | mRequestHandle = LLWorkerThread::nullHandle(); | ||
332 | clearFlags(WCF_HAVE_WORK); | ||
333 | } | ||
260 | } | 334 | } |
261 | else if (workreq->getStatus() == LLWorkerThread::STATUS_COMPLETE) | 335 | else |
262 | { | 336 | { |
263 | complete = true; | 337 | complete = true; |
264 | } | 338 | } |
265 | if (complete) | ||
266 | { | ||
267 | #if _DEBUG | ||
268 | // llinfos << "endWork: " << mWorkerClassName << " Param: " << workreq->getParam() << llendl; | ||
269 | #endif | ||
270 | endWork(workreq->getParam(), abort); | ||
271 | mWorkerThread->completeRequest(mWorkHandle); | ||
272 | mWorkHandle = LLWorkerThread::nullHandle(); | ||
273 | } | ||
274 | return complete; | 339 | return complete; |
275 | } | 340 | } |
276 | 341 | ||
277 | void LLWorkerClass::killWork() | 342 | void LLWorkerClass::scheduleDelete() |
278 | { | 343 | { |
279 | if (haveWork()) | 344 | bool do_delete = false; |
345 | mMutex.lock(); | ||
346 | if (!(getFlags(WCF_DELETE_REQUESTED))) | ||
280 | { | 347 | { |
281 | abortWork(); | 348 | setFlags(WCF_DELETE_REQUESTED); |
282 | bool paused = mWorkerThread->isPaused(); | 349 | do_delete = true; |
283 | while (!checkWork()) | 350 | } |
284 | { | 351 | mMutex.unlock(); |
285 | mWorkerThread->updateQueue(0); | 352 | if (do_delete) |
286 | } | 353 | { |
287 | if (paused) | 354 | mWorkerThread->deleteWorker(this); |
288 | { | ||
289 | mWorkerThread->pause(); | ||
290 | } | ||
291 | } | 355 | } |
292 | } | 356 | } |
293 | 357 | ||
294 | void LLWorkerClass::setPriority(U32 priority) | 358 | void LLWorkerClass::setPriority(U32 priority) |
295 | { | 359 | { |
296 | if (haveWork()) | 360 | mMutex.lock(); |
361 | if (mRequestHandle != LLWorkerThread::nullHandle()) | ||
297 | { | 362 | { |
298 | mWorkerThread->setPriority(mWorkHandle, priority); | 363 | mRequestPriority = priority; |
364 | mWorkerThread->setPriority(mRequestHandle, priority); | ||
299 | } | 365 | } |
366 | mMutex.unlock(); | ||
300 | } | 367 | } |
301 | 368 | ||
302 | //============================================================================ | 369 | //============================================================================ |
diff --git a/linden/indra/llcommon/llworkerthread.h b/linden/indra/llcommon/llworkerthread.h index f01e67b..17b7e7b 100644 --- a/linden/indra/llcommon/llworkerthread.h +++ b/linden/indra/llcommon/llworkerthread.h | |||
@@ -47,13 +47,13 @@ class LLWorkerClass; | |||
47 | class LLWorkerThread : public LLQueuedThread | 47 | class LLWorkerThread : public LLQueuedThread |
48 | { | 48 | { |
49 | public: | 49 | public: |
50 | class Request : public LLQueuedThread::QueuedRequest | 50 | class WorkRequest : public LLQueuedThread::QueuedRequest |
51 | { | 51 | { |
52 | protected: | 52 | protected: |
53 | ~Request() {}; // use deleteRequest() | 53 | virtual ~WorkRequest(); // use deleteRequest() |
54 | 54 | ||
55 | public: | 55 | public: |
56 | Request(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param); | 56 | WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param); |
57 | 57 | ||
58 | S32 getParam() | 58 | S32 getParam() |
59 | { | 59 | { |
@@ -64,6 +64,8 @@ public: | |||
64 | return mWorkerClass; | 64 | return mWorkerClass; |
65 | } | 65 | } |
66 | 66 | ||
67 | /*virtual*/ bool processRequest(); | ||
68 | /*virtual*/ void finishRequest(bool completed); | ||
67 | /*virtual*/ void deleteRequest(); | 69 | /*virtual*/ void deleteRequest(); |
68 | 70 | ||
69 | private: | 71 | private: |
@@ -71,26 +73,24 @@ public: | |||
71 | S32 mParam; | 73 | S32 mParam; |
72 | }; | 74 | }; |
73 | 75 | ||
74 | public: | 76 | private: |
75 | LLWorkerThread(bool threaded = true, bool runalways = true); | 77 | typedef std::list<LLWorkerClass*> delete_list_t; |
76 | ~LLWorkerThread(); | 78 | delete_list_t mDeleteList; |
77 | 79 | LLMutex* mDeleteMutex; | |
78 | protected: | 80 | apr_pool_t* mWorkerAPRPoolp; |
79 | /*virtual*/ bool processRequest(QueuedRequest* req); | ||
80 | 81 | ||
81 | public: | 82 | public: |
82 | handle_t add(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL); | 83 | LLWorkerThread(const std::string& name, bool threaded = true); |
83 | 84 | ~LLWorkerThread(); | |
84 | static void initClass(bool local_is_threaded = true, bool local_run_always = true); // Setup sLocal | ||
85 | static S32 updateClass(U32 ms_elapsed); | ||
86 | static S32 getAllPending(); | ||
87 | static void pauseAll(); | ||
88 | static void waitOnAllPending(); | ||
89 | static void cleanupClass(); // Delete sLocal | ||
90 | 85 | ||
91 | public: | 86 | apr_pool_t* getWorkerAPRPool() { return mWorkerAPRPoolp; } |
92 | static LLWorkerThread* sLocal; // Default worker thread | 87 | |
93 | static std::set<LLWorkerThread*> sThreadList; // array of threads (includes sLocal) | 88 | /*virtual*/ S32 update(U32 max_time_ms); |
89 | |||
90 | handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL); | ||
91 | |||
92 | void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion | ||
93 | S32 getNumDeletes() { return mDeleteList.size(); } // debug | ||
94 | }; | 94 | }; |
95 | 95 | ||
96 | //============================================================================ | 96 | //============================================================================ |
@@ -112,11 +112,17 @@ public: | |||
112 | 112 | ||
113 | class LLWorkerClass | 113 | class LLWorkerClass |
114 | { | 114 | { |
115 | friend class LLWorkerThread; | ||
116 | friend class LLWorkerThread::WorkRequest; | ||
115 | public: | 117 | public: |
116 | typedef LLWorkerThread::handle_t handle_t; | 118 | typedef LLWorkerThread::handle_t handle_t; |
117 | enum FLAGS | 119 | enum FLAGS |
118 | { | 120 | { |
119 | WCF_WORKING = 0x01, | 121 | WCF_HAVE_WORK = 0x01, |
122 | WCF_WORKING = 0x02, | ||
123 | WCF_WORK_FINISHED = 0x10, | ||
124 | WCF_WORK_ABORTED = 0x20, | ||
125 | WCF_DELETE_REQUESTED = 0x40, | ||
120 | WCF_ABORT_REQUESTED = 0x80 | 126 | WCF_ABORT_REQUESTED = 0x80 |
121 | }; | 127 | }; |
122 | 128 | ||
@@ -125,17 +131,29 @@ public: | |||
125 | virtual ~LLWorkerClass(); | 131 | virtual ~LLWorkerClass(); |
126 | 132 | ||
127 | // pure virtual, called from WORKER THREAD, returns TRUE if done | 133 | // pure virtual, called from WORKER THREAD, returns TRUE if done |
128 | virtual bool doWork(S32 param)=0; // Called from LLWorkerThread::processRequest() | 134 | virtual bool doWork(S32 param)=0; // Called from WorkRequest::processRequest() |
129 | 135 | // virtual, called from finishRequest() after completed or aborted | |
130 | // called from WORKER THREAD | 136 | virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD) |
131 | void setWorking(bool working) { working ? setFlags(WCF_WORKING) : clearFlags(WCF_WORKING); } | 137 | // virtual, returns true if safe to delete the worker |
138 | virtual bool deleteOK(); // called from update() (WORK THREAD) | ||
132 | 139 | ||
140 | // schedlueDelete(): schedules deletion once aborted or completed | ||
141 | void scheduleDelete(); | ||
142 | |||
143 | bool haveWork() { return getFlags(WCF_HAVE_WORK); } // may still be true if aborted | ||
133 | bool isWorking() { return getFlags(WCF_WORKING); } | 144 | bool isWorking() { return getFlags(WCF_WORKING); } |
134 | bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); } | 145 | bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); } |
146 | |||
147 | // setPriority(): changes the priority of a request | ||
148 | void setPriority(U32 priority); | ||
149 | U32 getPriority() { return mRequestPriority; } | ||
135 | 150 | ||
136 | const std::string& getName() const { return mWorkerClassName; } | 151 | const std::string& getName() const { return mWorkerClassName; } |
137 | 152 | ||
138 | protected: | 153 | protected: |
154 | // called from WORKER THREAD | ||
155 | void setWorking(bool working); | ||
156 | |||
139 | // Call from doWork only to avoid eating up cpu time. | 157 | // Call from doWork only to avoid eating up cpu time. |
140 | // Returns true if work has been aborted | 158 | // Returns true if work has been aborted |
141 | // yields the current thread and calls mWorkerThread->checkPause() | 159 | // yields the current thread and calls mWorkerThread->checkPause() |
@@ -147,20 +165,11 @@ protected: | |||
147 | void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL); | 165 | void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL); |
148 | 166 | ||
149 | // abortWork(): requests that work be aborted | 167 | // abortWork(): requests that work be aborted |
150 | void abortWork(); | 168 | void abortWork(bool autocomplete); |
151 | 169 | ||
152 | // checkWork(): if doWork is complete or aborted, call endWork() and return true | 170 | // checkWork(): if doWork is complete or aborted, call endWork() and return true |
153 | bool checkWork(); | 171 | bool checkWork(bool aborting = false); |
154 | 172 | ||
155 | // haveWork(): return true if mWorkHandle != null | ||
156 | bool haveWork() { return mWorkHandle != LLWorkerThread::nullHandle(); } | ||
157 | |||
158 | // killWork(): aborts work and waits for the abort to process | ||
159 | void killWork(); | ||
160 | |||
161 | // setPriority(): changes the priority of a request | ||
162 | void setPriority(U32 priority); | ||
163 | |||
164 | private: | 173 | private: |
165 | void setFlags(U32 flags) { mWorkFlags = mWorkFlags | flags; } | 174 | void setFlags(U32 flags) { mWorkFlags = mWorkFlags | flags; } |
166 | void clearFlags(U32 flags) { mWorkFlags = mWorkFlags & ~flags; } | 175 | void clearFlags(U32 flags) { mWorkFlags = mWorkFlags & ~flags; } |
@@ -175,9 +184,11 @@ private: | |||
175 | protected: | 184 | protected: |
176 | LLWorkerThread* mWorkerThread; | 185 | LLWorkerThread* mWorkerThread; |
177 | std::string mWorkerClassName; | 186 | std::string mWorkerClassName; |
178 | handle_t mWorkHandle; | 187 | handle_t mRequestHandle; |
188 | U32 mRequestPriority; // last priority set | ||
179 | 189 | ||
180 | private: | 190 | private: |
191 | LLMutex mMutex; | ||
181 | LLAtomicU32 mWorkFlags; | 192 | LLAtomicU32 mWorkFlags; |
182 | }; | 193 | }; |
183 | 194 | ||
diff --git a/linden/indra/llcommon/metaproperty.cpp b/linden/indra/llcommon/metaproperty.cpp index e4983cc..312dd9d 100644 --- a/linden/indra/llcommon/metaproperty.cpp +++ b/linden/indra/llcommon/metaproperty.cpp | |||
@@ -44,7 +44,7 @@ const LLMetaClass& LLMetaProperty::getObjectMetaClass() const | |||
44 | { | 44 | { |
45 | return mObjectClass; | 45 | return mObjectClass; |
46 | } | 46 | } |
47 | 47 | ||
48 | void LLMetaProperty::checkObjectClass(const LLReflective* object) const | 48 | void LLMetaProperty::checkObjectClass(const LLReflective* object) const |
49 | { | 49 | { |
50 | if(! mObjectClass.isInstance(object)) | 50 | if(! mObjectClass.isInstance(object)) |
diff --git a/linden/indra/llcommon/u64.cpp b/linden/indra/llcommon/u64.cpp index 45baa13..744e0ab 100644 --- a/linden/indra/llcommon/u64.cpp +++ b/linden/indra/llcommon/u64.cpp | |||
@@ -33,7 +33,7 @@ | |||
33 | U64 str_to_U64(const char *str) | 33 | U64 str_to_U64(const char *str) |
34 | { | 34 | { |
35 | U64 result = 0; | 35 | U64 result = 0; |
36 | char *aptr = strpbrk(str,"0123456789"); | 36 | const char *aptr = strpbrk(str,"0123456789"); |
37 | 37 | ||
38 | if (!aptr) | 38 | if (!aptr) |
39 | { | 39 | { |
@@ -66,27 +66,27 @@ char* U64_to_str(U64 value, char* result, S32 result_size) | |||
66 | 66 | ||
67 | if (part1) | 67 | if (part1) |
68 | { | 68 | { |
69 | snprintf( | 69 | snprintf( /* Flawfinder: ignore */ |
70 | result, | 70 | result, |
71 | result_size, | 71 | result_size, |
72 | "%u%07u%07u", | 72 | "%u%07u%07u", |
73 | part1,part2,part3); /* Flawfinder: ignore */ | 73 | part1,part2,part3); |
74 | } | 74 | } |
75 | else if (part2) | 75 | else if (part2) |
76 | { | 76 | { |
77 | snprintf( | 77 | snprintf( /* Flawfinder: ignore */ |
78 | result, | 78 | result, |
79 | result_size, | 79 | result_size, |
80 | "%u%07u", | 80 | "%u%07u", |
81 | part2,part3); /* Flawfinder: ignore */ | 81 | part2,part3); |
82 | } | 82 | } |
83 | else | 83 | else |
84 | { | 84 | { |
85 | snprintf( | 85 | snprintf( /* Flawfinder: ignore */ |
86 | result, | 86 | result, |
87 | result_size, | 87 | result_size, |
88 | "%u", | 88 | "%u", |
89 | part3); /* Flawfinder: ignore */ | 89 | part3); |
90 | } | 90 | } |
91 | return (result); | 91 | return (result); |
92 | } | 92 | } |