aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon
diff options
context:
space:
mode:
authorJacek Antonelli2010-02-08 17:01:00 -0600
committerJacek Antonelli2010-02-08 17:01:00 -0600
commitd96e672c7fa0cb59ef0c30163326bb40220e745a (patch)
tree0578f6258788f44f91dbf84eebdb09d994e2a0e5 /linden/indra/llcommon
parentFixed login screen only allowing 16 chars per name. (diff)
downloadmeta-impy-d96e672c7fa0cb59ef0c30163326bb40220e745a.zip
meta-impy-d96e672c7fa0cb59ef0c30163326bb40220e745a.tar.gz
meta-impy-d96e672c7fa0cb59ef0c30163326bb40220e745a.tar.bz2
meta-impy-d96e672c7fa0cb59ef0c30163326bb40220e745a.tar.xz
Ported many APR changes from Snowglobe.
Diffstat (limited to '')
-rw-r--r--linden/indra/llcommon/llapr.cpp284
-rw-r--r--linden/indra/llcommon/llapr.h47
-rw-r--r--linden/indra/llcommon/llthread.cpp11
-rw-r--r--linden/indra/llcommon/llthread.h6
-rw-r--r--linden/indra/llcommon/llworkerthread.cpp5
5 files changed, 175 insertions, 178 deletions
diff --git a/linden/indra/llcommon/llapr.cpp b/linden/indra/llcommon/llapr.cpp
index 669afc5..7e3a26c 100644
--- a/linden/indra/llcommon/llapr.cpp
+++ b/linden/indra/llcommon/llapr.cpp
@@ -36,7 +36,6 @@
36#include "llapr.h" 36#include "llapr.h"
37 37
38apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool 38apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
39LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
40apr_thread_mutex_t *gLogMutexp = NULL; 39apr_thread_mutex_t *gLogMutexp = NULL;
41apr_thread_mutex_t *gCallStacksLogMutexp = NULL; 40apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
42 41
@@ -53,11 +52,9 @@ void ll_init_apr()
53 // Initialize the logging mutex 52 // Initialize the logging mutex
54 apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp); 53 apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
55 apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp); 54 apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
56 }
57 55
58 if(!LLAPRFile::sAPRFilePoolp) 56 // Initialize thread-local APR pool support.
59 { 57 LLVolatileAPRPool::initLocalAPRFilePool();
60 LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool() ;
61 } 58 }
62} 59}
63 60
@@ -87,11 +84,6 @@ void ll_cleanup_apr()
87 apr_pool_destroy(gAPRPoolp); 84 apr_pool_destroy(gAPRPoolp);
88 gAPRPoolp = NULL; 85 gAPRPoolp = NULL;
89 } 86 }
90 if (LLAPRFile::sAPRFilePoolp)
91 {
92 delete LLAPRFile::sAPRFilePoolp ;
93 LLAPRFile::sAPRFilePoolp = NULL ;
94 }
95 apr_terminate(); 87 apr_terminate();
96} 88}
97 89
@@ -207,6 +199,56 @@ BOOL LLVolatileAPRPool::isFull()
207{ 199{
208 return mNumTotalRef > FULL_VOLATILE_APR_POOL ; 200 return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
209} 201}
202
203#ifdef SHOW_ASSERT
204// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
205static void* gIsMainThread;
206bool is_main_thread() { return gIsMainThread == LLVolatileAPRPool::getLocalAPRFilePool(); }
207#endif
208
209// The thread private handle to access the LocalAPRFilePool.
210apr_threadkey_t* LLVolatileAPRPool::sLocalAPRFilePoolKey;
211
212// This should be called exactly once, before the first call to createLocalAPRFilePool.
213// static
214void LLVolatileAPRPool::initLocalAPRFilePool()
215{
216 apr_status_t status = apr_threadkey_private_create(&sLocalAPRFilePoolKey, &destroyLocalAPRFilePool, gAPRPoolp);
217 ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the
218 // total number of keys per process {PTHREAD_KEYS_MAX}
219 // has been exceeded.
220 // Create the thread-local pool for the main thread (this function is called by the main thread).
221 createLocalAPRFilePool();
222#ifdef SHOW_ASSERT
223 gIsMainThread = getLocalAPRFilePool();
224#endif
225}
226
227// This should be called once for every thread, before it uses getLocalAPRFilePool.
228// static
229void LLVolatileAPRPool::createLocalAPRFilePool()
230{
231 void* thread_local_data = new LLVolatileAPRPool;
232 apr_status_t status = apr_threadkey_private_set(thread_local_data, sLocalAPRFilePoolKey);
233 llassert_always(status == APR_SUCCESS);
234}
235
236// This is called once for every thread when the thread is destructed.
237// static
238void LLVolatileAPRPool::destroyLocalAPRFilePool(void* thread_local_data)
239{
240 delete reinterpret_cast<LLVolatileAPRPool*>(thread_local_data);
241}
242
243// static
244LLVolatileAPRPool* LLVolatileAPRPool::getLocalAPRFilePool()
245{
246 void* thread_local_data;
247 apr_status_t status = apr_threadkey_private_get(&thread_local_data, sLocalAPRFilePoolKey);
248 llassert_always(status == APR_SUCCESS);
249 return reinterpret_cast<LLVolatileAPRPool*>(thread_local_data);
250}
251
210//--------------------------------------------------------------------- 252//---------------------------------------------------------------------
211// 253//
212// LLScopedLock 254// LLScopedLock
@@ -251,10 +293,9 @@ void LLScopedLock::unlock()
251bool ll_apr_warn_status(apr_status_t status) 293bool ll_apr_warn_status(apr_status_t status)
252{ 294{
253 if(APR_SUCCESS == status) return false; 295 if(APR_SUCCESS == status) return false;
254#ifndef LL_WINDOWS
255 char buf[MAX_STRING]; /* Flawfinder: ignore */ 296 char buf[MAX_STRING]; /* Flawfinder: ignore */
256 LL_WARNS_ONCE("APR") << "APR: " << apr_strerror(status, buf, MAX_STRING) << LL_ENDL; 297 apr_strerror(status, buf, MAX_STRING);
257#endif 298 LL_WARNS("APR") << "APR: " << buf << LL_ENDL;
258 return true; 299 return true;
259} 300}
260 301
@@ -268,10 +309,18 @@ void ll_apr_assert_status(apr_status_t status)
268// LLAPRFile functions 309// LLAPRFile functions
269// 310//
270LLAPRFile::LLAPRFile() 311LLAPRFile::LLAPRFile()
312 : mFile(NULL),
313 mCurrentFilePoolp(NULL)
271{ 314{
272 mFile = NULL ;
273 mCurrentFilePoolp = NULL ;
274} 315}
316
317LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type)
318 : mFile(NULL),
319 mCurrentFilePoolp(NULL)
320{
321 open(filename, flags, access_type);
322}
323
275LLAPRFile::~LLAPRFile() 324LLAPRFile::~LLAPRFile()
276{ 325{
277 close() ; 326 close() ;
@@ -295,32 +344,27 @@ apr_status_t LLAPRFile::close()
295 return ret ; 344 return ret ;
296} 345}
297 346
298apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep) 347apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep)
299{ 348{
300 apr_status_t s ; 349 llassert_always(!mFile);
301 s = open(filename, flags, pool ? pool->getVolatileAPRPool() : NULL, sizep) ; 350 llassert_always(!mCurrentFilePoolp);
302
303 if(!mCurrentFilePoolp)
304 {
305 mCurrentFilePoolp = pool ;
306 351
307 if(!mFile) 352 // Access the pool and increment it's reference count.
308 { 353 // The reference count of LLVolatileAPRPool objects will be decremented
309 close() ; 354 // again in LLAPRFile::close by calling mCurrentFilePoolp->clearVolatileAPRPool().
310 } 355 apr_pool_t* pool;
356 if (access_type == local)
357 {
358 // Use a "volatile" thread-local pool.
359 mCurrentFilePoolp = LLVolatileAPRPool::getLocalAPRFilePool();
360 pool = mCurrentFilePoolp->getVolatileAPRPool();
311 } 361 }
312 362 else
313 return s ; 363 {
314} 364 llassert(is_main_thread());
315apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool, S32* sizep) 365 pool = gAPRPoolp;
316{ 366 }
317 apr_status_t s; 367 apr_status_t s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, pool);
318
319 //check if already open some file
320 llassert_always(!mFile) ;
321 llassert_always(!mCurrentFilePoolp) ;
322
323 s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(pool));
324 if (s != APR_SUCCESS || !mFile) 368 if (s != APR_SUCCESS || !mFile)
325 { 369 {
326 mFile = NULL ; 370 mFile = NULL ;
@@ -349,17 +393,6 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, apr
349 return s; 393 return s;
350} 394}
351 395
352apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool)
353{
354 if(!pool)
355 {
356 mCurrentFilePoolp = sAPRFilePoolp ;
357 return mCurrentFilePoolp->getVolatileAPRPool() ;
358 }
359
360 return pool ;
361}
362
363// File I/O 396// File I/O
364S32 LLAPRFile::read(void *buf, S32 nbytes) 397S32 LLAPRFile::read(void *buf, S32 nbytes)
365{ 398{
@@ -369,6 +402,7 @@ S32 LLAPRFile::read(void *buf, S32 nbytes)
369 apr_status_t s = apr_file_read(mFile, buf, &sz); 402 apr_status_t s = apr_file_read(mFile, buf, &sz);
370 if (s != APR_SUCCESS) 403 if (s != APR_SUCCESS)
371 { 404 {
405 ll_apr_warn_status(s);
372 return 0; 406 return 0;
373 } 407 }
374 else 408 else
@@ -386,6 +420,7 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes)
386 apr_status_t s = apr_file_write(mFile, buf, &sz); 420 apr_status_t s = apr_file_write(mFile, buf, &sz);
387 if (s != APR_SUCCESS) 421 if (s != APR_SUCCESS)
388 { 422 {
423 ll_apr_warn_status(s);
389 return 0; 424 return 0;
390 } 425 }
391 else 426 else
@@ -405,42 +440,16 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
405//static components of LLAPRFile 440//static components of LLAPRFile
406// 441//
407 442
408//static 443// Used in the static functions below.
409apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool) 444class LLScopedVolatileAPRFilePool {
410{ 445private:
411 apr_status_t ret = APR_SUCCESS ; 446 LLVolatileAPRPool* mPool;
412 if(file_handle) 447 apr_pool_t* apr_pool;
413 { 448public:
414 ret = apr_file_close(file_handle); 449 LLScopedVolatileAPRFilePool() : mPool(LLVolatileAPRPool::getLocalAPRFilePool()), apr_pool(mPool->getVolatileAPRPool()) { }
415 file_handle = NULL ; 450 ~LLScopedVolatileAPRFilePool() { mPool->clearVolatileAPRPool(); }
416 } 451 operator apr_pool_t*() const { return apr_pool; }
417 452};
418 if(pool)
419 {
420 pool->clearVolatileAPRPool() ;
421 }
422
423 return ret ;
424}
425
426//static
427apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
428{
429 apr_status_t s;
430 apr_file_t* file_handle ;
431
432 pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
433
434 s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
435 if (s != APR_SUCCESS || !file_handle)
436 {
437 file_handle = NULL ;
438 close(file_handle, pool) ;
439 return NULL;
440 }
441
442 return file_handle ;
443}
444 453
445//static 454//static
446S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) 455S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
@@ -464,6 +473,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
464 } 473 }
465 if (s != APR_SUCCESS) 474 if (s != APR_SUCCESS)
466 { 475 {
476 ll_apr_warn_status(s);
467 return -1; 477 return -1;
468 } 478 }
469 else 479 else
@@ -474,13 +484,15 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
474} 484}
475 485
476//static 486//static
477S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) 487S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
478{ 488{
479 //***************************************** 489 apr_file_t* file_handle;
480 apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY); 490 LLScopedVolatileAPRFilePool pool;
481 //***************************************** 491 apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool);
482 if (!file_handle) 492 if (s != APR_SUCCESS || !file_handle)
483 { 493 {
494 ll_apr_warn_status(s);
495 LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL;
484 return 0; 496 return 0;
485 } 497 }
486 498
@@ -501,6 +513,8 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
501 apr_status_t s = apr_file_read(file_handle, buf, &bytes_read); 513 apr_status_t s = apr_file_read(file_handle, buf, &bytes_read);
502 if (s != APR_SUCCESS) 514 if (s != APR_SUCCESS)
503 { 515 {
516 LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL;
517 ll_apr_warn_status(s);
504 bytes_read = 0; 518 bytes_read = 0;
505 } 519 }
506 else 520 else
@@ -509,14 +523,13 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
509 } 523 }
510 } 524 }
511 525
512 //***************************************** 526 apr_file_close(file_handle);
513 close(file_handle, pool) ; 527
514 //*****************************************
515 return (S32)bytes_read; 528 return (S32)bytes_read;
516} 529}
517 530
518//static 531//static
519S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) 532S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
520{ 533{
521 apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; 534 apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
522 if (offset < 0) 535 if (offset < 0)
@@ -525,11 +538,13 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
525 offset = 0; 538 offset = 0;
526 } 539 }
527 540
528 //***************************************** 541 apr_file_t* file_handle;
529 apr_file_t* file_handle = open(filename, pool, flags); 542 LLScopedVolatileAPRFilePool pool;
530 //***************************************** 543 apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
531 if (!file_handle) 544 if (s != APR_SUCCESS || !file_handle)
532 { 545 {
546 ll_apr_warn_status(s);
547 LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL;
533 return 0; 548 return 0;
534 } 549 }
535 550
@@ -549,6 +564,8 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
549 apr_status_t s = apr_file_write(file_handle, buf, &bytes_written); 564 apr_status_t s = apr_file_write(file_handle, buf, &bytes_written);
550 if (s != APR_SUCCESS) 565 if (s != APR_SUCCESS)
551 { 566 {
567 LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL;
568 ll_apr_warn_status(s);
552 bytes_written = 0; 569 bytes_written = 0;
553 } 570 }
554 else 571 else
@@ -557,93 +574,84 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
557 } 574 }
558 } 575 }
559 576
560 //***************************************** 577 apr_file_close(file_handle);
561 LLAPRFile::close(file_handle, pool);
562 //*****************************************
563 578
564 return (S32)bytes_written; 579 return (S32)bytes_written;
565} 580}
566 581
567//static 582//static
568bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool) 583bool LLAPRFile::remove(const std::string& filename)
569{ 584{
570 apr_status_t s; 585 apr_status_t s;
571 586
572 pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; 587 LLScopedVolatileAPRFilePool pool;
573 s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool()); 588 s = apr_file_remove(filename.c_str(), pool);
574 pool->clearVolatileAPRPool() ;
575 589
576 if (s != APR_SUCCESS) 590 if (s != APR_SUCCESS)
577 { 591 {
578 LL_DEBUGS("APR") << "LLAPRFile::remove failed on file: " << filename << LL_ENDL;
579 ll_apr_warn_status(s); 592 ll_apr_warn_status(s);
593 LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL;
580 return false; 594 return false;
581 } 595 }
582 return true; 596 return true;
583} 597}
584 598
585//static 599//static
586bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool) 600bool LLAPRFile::rename(const std::string& filename, const std::string& newname)
587{ 601{
588 apr_status_t s; 602 apr_status_t s;
589 603
590 pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; 604 LLScopedVolatileAPRFilePool pool;
591 s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool()); 605 s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
592 pool->clearVolatileAPRPool() ;
593 606
594 if (s != APR_SUCCESS) 607 if (s != APR_SUCCESS)
595 { 608 {
596 LL_DEBUGS("APR") << "LLAPRFile::rename failed on file: " << filename << LL_ENDL;
597 ll_apr_warn_status(s); 609 ll_apr_warn_status(s);
610 LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL;
598 return false; 611 return false;
599 } 612 }
600 return true; 613 return true;
601} 614}
602 615
603//static 616//static
604bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags) 617bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags)
605{ 618{
606 apr_file_t* apr_file; 619 apr_file_t* file_handle;
607 apr_status_t s; 620 apr_status_t s;
608 621
609 pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; 622 LLScopedVolatileAPRFilePool pool;
610 s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool()); 623 s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
611 624
612 if (s != APR_SUCCESS || !apr_file) 625 if (s != APR_SUCCESS || !file_handle)
613 { 626 {
614 pool->clearVolatileAPRPool() ;
615 return false; 627 return false;
616 } 628 }
617 else 629 else
618 { 630 {
619 apr_file_close(apr_file) ; 631 apr_file_close(file_handle);
620 pool->clearVolatileAPRPool() ;
621 return true; 632 return true;
622 } 633 }
623} 634}
624 635
625//static 636//static
626S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool) 637S32 LLAPRFile::size(const std::string& filename)
627{ 638{
628 apr_file_t* apr_file; 639 apr_file_t* file_handle;
629 apr_finfo_t info; 640 apr_finfo_t info;
630 apr_status_t s; 641 apr_status_t s;
631 642
632 pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; 643 LLScopedVolatileAPRFilePool pool;
633 s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool()); 644 s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
634 645
635 if (s != APR_SUCCESS || !apr_file) 646 if (s != APR_SUCCESS || !file_handle)
636 { 647 {
637 pool->clearVolatileAPRPool() ;
638
639 return 0; 648 return 0;
640 } 649 }
641 else 650 else
642 { 651 {
643 apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file); 652 apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, file_handle);
644 653
645 apr_file_close(apr_file) ; 654 apr_file_close(file_handle) ;
646 pool->clearVolatileAPRPool() ;
647 655
648 if (s == APR_SUCCESS) 656 if (s == APR_SUCCESS)
649 { 657 {
@@ -657,36 +665,34 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
657} 665}
658 666
659//static 667//static
660bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool) 668bool LLAPRFile::makeDir(const std::string& dirname)
661{ 669{
662 apr_status_t s; 670 apr_status_t s;
663 671
664 pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; 672 LLScopedVolatileAPRFilePool pool;
665 s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool()); 673 s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
666 pool->clearVolatileAPRPool() ;
667 674
668 if (s != APR_SUCCESS) 675 if (s != APR_SUCCESS)
669 { 676 {
670 LL_DEBUGS("APR") << "LLAPRFile::makeDir failed on file: " << dirname << LL_ENDL;
671 ll_apr_warn_status(s); 677 ll_apr_warn_status(s);
678 LL_WARNS("APR") << " while attempting to make directory: " << dirname << LL_ENDL;
672 return false; 679 return false;
673 } 680 }
674 return true; 681 return true;
675} 682}
676 683
677//static 684//static
678bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool) 685bool LLAPRFile::removeDir(const std::string& dirname)
679{ 686{
680 apr_status_t s; 687 apr_status_t s;
681 688
682 pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; 689 LLScopedVolatileAPRFilePool pool;
683 s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool()); 690 s = apr_file_remove(dirname.c_str(), pool);
684 pool->clearVolatileAPRPool() ;
685 691
686 if (s != APR_SUCCESS) 692 if (s != APR_SUCCESS)
687 { 693 {
688 LL_DEBUGS("APR") << "LLAPRFile::removeDir failed on file: " << dirname << LL_ENDL;
689 ll_apr_warn_status(s); 694 ll_apr_warn_status(s);
695 LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL;
690 return false; 696 return false;
691 } 697 }
692 return true; 698 return true;
diff --git a/linden/indra/llcommon/llapr.h b/linden/indra/llcommon/llapr.h
index 63130a8..7f770b0 100644
--- a/linden/indra/llcommon/llapr.h
+++ b/linden/indra/llcommon/llapr.h
@@ -92,7 +92,7 @@ protected:
92//which clears memory automatically. 92//which clears memory automatically.
93//so it can not hold static data or data after memory is cleared 93//so it can not hold static data or data after memory is cleared
94// 94//
95class LLVolatileAPRPool : public LLAPRPool 95class LLVolatileAPRPool : protected LLAPRPool
96{ 96{
97public: 97public:
98 LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE); 98 LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
@@ -104,9 +104,17 @@ public:
104 104
105 BOOL isFull() ; 105 BOOL isFull() ;
106 BOOL isEmpty() {return !mNumActiveRef ;} 106 BOOL isEmpty() {return !mNumActiveRef ;}
107
108 static void initLocalAPRFilePool();
109 static void createLocalAPRFilePool();
110 static void destroyLocalAPRFilePool(void* thread_local_data);
111 static LLVolatileAPRPool* getLocalAPRFilePool();
112
107private: 113private:
108 S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool. 114 S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
109 S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating. 115 S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
116
117 static apr_threadkey_t* sLocalAPRFilePoolKey;
110} ; 118} ;
111 119
112/** 120/**
@@ -192,18 +200,25 @@ typedef LLAtomic32<S32> LLAtomicS32;
192// 1, a temperary pool passed to an APRFile function, which is used within this function and only once. 200// 1, a temperary pool passed to an APRFile function, which is used within this function and only once.
193// 2, a global pool. 201// 2, a global pool.
194// 202//
195class LLAPRFile 203
204class LLAPRFile : boost::noncopyable
196{ 205{
206 // make this non copyable since a copy closes the file
197private: 207private:
198 apr_file_t* mFile ; 208 apr_file_t* mFile ;
199 LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. 209 LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool.
200 210
201public: 211public:
212 enum access_t {
213 global, // Use a global pool for long-lived file accesses. This should really only happen from the main thread.
214 local // Use a thread-local volatile pool for short file accesses.
215 };
216
202 LLAPRFile() ; 217 LLAPRFile() ;
218 LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type);
203 ~LLAPRFile() ; 219 ~LLAPRFile() ;
204 220
205 apr_status_t open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep = NULL); 221 apr_status_t open(const std::string& filename, apr_int32_t flags, access_t access_type, S32* sizep = NULL);
206 apr_status_t open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool = NULL, S32* sizep = NULL);
207 apr_status_t close() ; 222 apr_status_t close() ;
208 223
209 // Returns actual offset, -1 if seek fails 224 // Returns actual offset, -1 if seek fails
@@ -216,32 +231,24 @@ public:
216 231
217 apr_file_t* getFileHandle() {return mFile;} 232 apr_file_t* getFileHandle() {return mFile;}
218 233
219private:
220 apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
221
222// 234//
223//******************************************************************************************************************************* 235//*******************************************************************************************************************************
224//static components 236//static components
225// 237//
226public:
227 static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
228
229private: 238private:
230 static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
231 static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
232 static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset); 239 static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
233public: 240public:
234 // returns false if failure: 241 // returns false if failure:
235 static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL); 242 static bool remove(const std::string& filename);
236 static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL); 243 static bool rename(const std::string& filename, const std::string& newname);
237 static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ); 244 static bool isExist(const std::string& filename, apr_int32_t flags = APR_READ);
238 static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL); 245 static S32 size(const std::string& filename);
239 static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL); 246 static bool makeDir(const std::string& dirname);
240 static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL); 247 static bool removeDir(const std::string& dirname);
241 248
242 // Returns bytes read/written, 0 if read/write fails: 249 // Returns bytes read/written, 0 if read/write fails:
243 static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); 250 static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes);
244 static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); 251 static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes);
245//******************************************************************************************************************************* 252//*******************************************************************************************************************************
246}; 253};
247 254
diff --git a/linden/indra/llcommon/llthread.cpp b/linden/indra/llcommon/llthread.cpp
index 37b03a4..b39ffb6 100644
--- a/linden/indra/llcommon/llthread.cpp
+++ b/linden/indra/llcommon/llthread.cpp
@@ -72,6 +72,9 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
72 // Set thread state to running 72 // Set thread state to running
73 threadp->mStatus = RUNNING; 73 threadp->mStatus = RUNNING;
74 74
75 // Create a thread local APRFile pool.
76 LLVolatileAPRPool::createLocalAPRFilePool();
77
75 // Run the user supplied function 78 // Run the user supplied function
76 threadp->run(); 79 threadp->run();
77 80
@@ -102,20 +105,12 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
102 apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread 105 apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
103 } 106 }
104 mRunCondition = new LLCondition(mAPRPoolp); 107 mRunCondition = new LLCondition(mAPRPoolp);
105
106 mLocalAPRFilePoolp = NULL ;
107} 108}
108 109
109 110
110LLThread::~LLThread() 111LLThread::~LLThread()
111{ 112{
112 shutdown(); 113 shutdown();
113
114 if(mLocalAPRFilePoolp)
115 {
116 delete mLocalAPRFilePoolp ;
117 mLocalAPRFilePoolp = NULL ;
118 }
119} 114}
120 115
121void LLThread::shutdown() 116void LLThread::shutdown()
diff --git a/linden/indra/llcommon/llthread.h b/linden/indra/llcommon/llthread.h
index 457f45b..721b6e7 100644
--- a/linden/indra/llcommon/llthread.h
+++ b/linden/indra/llcommon/llthread.h
@@ -83,7 +83,6 @@ public:
83 void start(void); 83 void start(void);
84 84
85 apr_pool_t *getAPRPool() { return mAPRPoolp; } 85 apr_pool_t *getAPRPool() { return mAPRPoolp; }
86 LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
87 86
88private: 87private:
89 bool mPaused; 88 bool mPaused;
@@ -100,11 +99,6 @@ protected:
100 bool mIsLocalPool; 99 bool mIsLocalPool;
101 EThreadStatus mStatus; 100 EThreadStatus mStatus;
102 101
103 //a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
104 //Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
105 // otherwise it will cause severe memory leaking!!! --bao
106 LLVolatileAPRPool *mLocalAPRFilePoolp ;
107
108 void setQuitting(); 102 void setQuitting();
109 103
110 // virtual function overridden by subclass -- this will be called when the thread runs 104 // virtual function overridden by subclass -- this will be called when the thread runs
diff --git a/linden/indra/llcommon/llworkerthread.cpp b/linden/indra/llcommon/llworkerthread.cpp
index 5dda600..68d32db 100644
--- a/linden/indra/llcommon/llworkerthread.cpp
+++ b/linden/indra/llcommon/llworkerthread.cpp
@@ -44,11 +44,6 @@ LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) :
44 LLQueuedThread(name, threaded) 44 LLQueuedThread(name, threaded)
45{ 45{
46 mDeleteMutex = new LLMutex(NULL); 46 mDeleteMutex = new LLMutex(NULL);
47
48 if(!mLocalAPRFilePoolp)
49 {
50 mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
51 }
52} 47}
53 48
54LLWorkerThread::~LLWorkerThread() 49LLWorkerThread::~LLWorkerThread()