aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview
diff options
context:
space:
mode:
authorMcCabe Maxsted2010-09-03 14:39:47 -0700
committerMcCabe Maxsted2010-09-03 14:39:47 -0700
commitb88d3f2a93f4cb479fc139844fe8ef3e8524277a (patch)
treebbb628c000ad0522e6b12c4315989b687497c77d /linden/indra/newview
parentAdded some subgroups to the SL dic (these commits should really be squashed o... (diff)
downloadmeta-impy-b88d3f2a93f4cb479fc139844fe8ef3e8524277a.zip
meta-impy-b88d3f2a93f4cb479fc139844fe8ef3e8524277a.tar.gz
meta-impy-b88d3f2a93f4cb479fc139844fe8ef3e8524277a.tar.bz2
meta-impy-b88d3f2a93f4cb479fc139844fe8ef3e8524277a.tar.xz
Revert "Updated lltexturecache to the latest in viewer-development (see #425)" since it was causing issues with local assets and object backup
This reverts commit 4ca4594ec264f390be981568ef5ff3ff0f2f77e6.
Diffstat (limited to 'linden/indra/newview')
-rw-r--r--linden/indra/newview/lltexturecache.cpp679
-rw-r--r--linden/indra/newview/lltexturecache.h37
-rw-r--r--linden/indra/newview/lltexturefetch.cpp2
3 files changed, 229 insertions, 489 deletions
diff --git a/linden/indra/newview/lltexturecache.cpp b/linden/indra/newview/lltexturecache.cpp
index 0a76742..46c125f 100644
--- a/linden/indra/newview/lltexturecache.cpp
+++ b/linden/indra/newview/lltexturecache.cpp
@@ -48,11 +48,11 @@
48// Unordered array of Entry structs 48// Unordered array of Entry structs
49// cache/texture.cache 49// cache/texture.cache
50// First TEXTURE_CACHE_ENTRY_SIZE bytes of each texture in texture.entries in same order 50// First TEXTURE_CACHE_ENTRY_SIZE bytes of each texture in texture.entries in same order
51// Entry size same as header packet, so we're not 0-padding unless whole image is contained in header.
51// cache/textures/[0-F]/UUID.texture 52// cache/textures/[0-F]/UUID.texture
52// Actual texture body files 53// Actual texture body files
53 54
54//note: there is no good to define 1024 for TEXTURE_CACHE_ENTRY_SIZE while FIRST_PACKET_SIZE is 600 on sim side. 55const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE;
55const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE;//1024;
56const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit 56const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit
57const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate) 57const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
58 58
@@ -390,7 +390,6 @@ bool LLTextureCacheRemoteWorker::doRead()
390 } 390 }
391 else 391 else
392 { 392 {
393 //llinfos << "texture " << mID.asString() << " found in local_assets" << llendl;
394 mImageSize = local_size; 393 mImageSize = local_size;
395 mImageLocal = TRUE; 394 mImageLocal = TRUE;
396 } 395 }
@@ -401,8 +400,7 @@ bool LLTextureCacheRemoteWorker::doRead()
401 // Second state / stage : identify the cache or not... 400 // Second state / stage : identify the cache or not...
402 if (!done && (mState == CACHE)) 401 if (!done && (mState == CACHE))
403 { 402 {
404 LLTextureCache::Entry entry ; 403 idx = mCache->getHeaderCacheEntry(mID, mImageSize);
405 idx = mCache->getHeaderCacheEntry(mID, entry);
406 if (idx < 0) 404 if (idx < 0)
407 { 405 {
408 // The texture is *not* cached. We're done here... 406 // The texture is *not* cached. We're done here...
@@ -411,7 +409,6 @@ bool LLTextureCacheRemoteWorker::doRead()
411 } 409 }
412 else 410 else
413 { 411 {
414 mImageSize = entry.mImageSize ;
415 // If the read offset is bigger than the header cache, we read directly from the body 412 // If the read offset is bigger than the header cache, we read directly from the body
416 // Note that currently, we *never* read with offset from the cache, so the result is *always* HEADER 413 // Note that currently, we *never* read with offset from the cache, so the result is *always* HEADER
417 mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; 414 mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
@@ -539,7 +536,6 @@ bool LLTextureCacheRemoteWorker::doWrite()
539 { 536 {
540 llassert_always(mOffset == 0); // We currently do not support write offsets 537 llassert_always(mOffset == 0); // We currently do not support write offsets
541 llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative... 538 llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative...
542 llassert_always(mImageSize >= mDataSize);
543 mState = CACHE; 539 mState = CACHE;
544 } 540 }
545 541
@@ -549,19 +545,14 @@ bool LLTextureCacheRemoteWorker::doWrite()
549 if (!done && (mState == CACHE)) 545 if (!done && (mState == CACHE))
550 { 546 {
551 bool alreadyCached = false; 547 bool alreadyCached = false;
552 LLTextureCache::Entry entry ; 548 S32 cur_imagesize = 0;
553
554 // Checks if this image is already in the entry list 549 // Checks if this image is already in the entry list
555 idx = mCache->getHeaderCacheEntry(mID, entry); 550 idx = mCache->getHeaderCacheEntry(mID, cur_imagesize);
556 if(idx < 0) 551 if (idx >= 0 && (cur_imagesize >= 0))
557 {
558 idx = mCache->setHeaderCacheEntry(mID, entry, mImageSize, mDataSize); // create the new entry.
559 }
560 else
561 { 552 {
562 alreadyCached = mCache->updateEntry(idx, entry, mImageSize, mDataSize); // update the existing entry. 553 alreadyCached = true; // already there and non empty
563 } 554 }
564 555 idx = mCache->setHeaderCacheEntry(mID, mImageSize); // create or touch the entry
565 if (idx < 0) 556 if (idx < 0)
566 { 557 {
567 llwarns << "LLTextureCacheWorker: " << mID 558 llwarns << "LLTextureCacheWorker: " << mID
@@ -571,6 +562,10 @@ bool LLTextureCacheRemoteWorker::doWrite()
571 } 562 }
572 else 563 else
573 { 564 {
565 if (cur_imagesize > 0 && (mImageSize != cur_imagesize))
566 {
567 alreadyCached = false; // re-write the header if the size changed in all cases
568 }
574 if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)) 569 if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE))
575 { 570 {
576 // Small texture already cached case: we're done with writing 571 // Small texture already cached case: we're done with writing
@@ -633,7 +628,7 @@ bool LLTextureCacheRemoteWorker::doWrite()
633 { 628 {
634 llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE); // wouldn't make sense to be here otherwise... 629 llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE); // wouldn't make sense to be here otherwise...
635 S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; 630 S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE;
636 631 if ((file_size > 0) && mCache->updateTextureEntryList(mID, file_size))
637 { 632 {
638 // build the cache file name from the UUID 633 // build the cache file name from the UUID
639 std::string filename = mCache->getTextureFileName(mID); 634 std::string filename = mCache->getTextureFileName(mID);
@@ -650,7 +645,10 @@ bool LLTextureCacheRemoteWorker::doWrite()
650 done = true; 645 done = true;
651 } 646 }
652 } 647 }
653 648 else
649 {
650 mDataSize = 0; // no data written
651 }
654 // Nothing else to do at that point... 652 // Nothing else to do at that point...
655 done = true; 653 done = true;
656 } 654 }
@@ -741,7 +739,7 @@ LLTextureCache::LLTextureCache(bool threaded)
741 mHeaderMutex(NULL), 739 mHeaderMutex(NULL),
742 mListMutex(NULL), 740 mListMutex(NULL),
743 mHeaderAPRFile(NULL), 741 mHeaderAPRFile(NULL),
744 mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called. 742 mReadOnly(FALSE),
745 mTexturesSizeTotal(0), 743 mTexturesSizeTotal(0),
746 mDoPurge(FALSE) 744 mDoPurge(FALSE)
747{ 745{
@@ -749,8 +747,6 @@ LLTextureCache::LLTextureCache(bool threaded)
749 747
750LLTextureCache::~LLTextureCache() 748LLTextureCache::~LLTextureCache()
751{ 749{
752 clearDeleteList() ;
753 writeUpdatedEntries() ;
754} 750}
755 751
756////////////////////////////////////////////////////////////////////////////// 752//////////////////////////////////////////////////////////////////////////////
@@ -758,9 +754,6 @@ LLTextureCache::~LLTextureCache()
758//virtual 754//virtual
759S32 LLTextureCache::update(U32 max_time_ms) 755S32 LLTextureCache::update(U32 max_time_ms)
760{ 756{
761 static LLFrameTimer timer ;
762 static const F32 MAX_TIME_INTERVAL = 300.f ; //seconds.
763
764 S32 res; 757 S32 res;
765 res = LLWorkerThread::update(max_time_ms); 758 res = LLWorkerThread::update(max_time_ms);
766 759
@@ -796,12 +789,6 @@ S32 LLTextureCache::update(U32 max_time_ms)
796 responder->completed(success); 789 responder->completed(success);
797 } 790 }
798 791
799 if(!res && timer.getElapsedTimeF32() > MAX_TIME_INTERVAL)
800 {
801 timer.reset() ;
802 writeUpdatedEntries() ;
803 }
804
805 return res; 792 return res;
806} 793}
807 794
@@ -824,54 +811,58 @@ std::string LLTextureCache::getTextureFileName(const LLUUID& id)
824 return filename; 811 return filename;
825} 812}
826 813
827//debug 814bool LLTextureCache::updateTextureEntryList(const LLUUID& id, S32 bodysize)
828BOOL LLTextureCache::isInCache(const LLUUID& id)
829{ 815{
830 LLMutexLock lock(&mHeaderMutex); 816 bool res = false;
831 id_map_t::const_iterator iter = mHeaderIDMap.find(id); 817 bool purge = false;
832
833 return (iter != mHeaderIDMap.end()) ;
834}
835
836//debug
837BOOL LLTextureCache::isInLocal(const LLUUID& id)
838{
839 S32 local_size = 0;
840 std::string local_filename;
841
842 std::string filename = getLocalFileName(id);
843 // Is it a JPEG2000 file?
844 {
845 local_filename = filename + ".j2c";
846 local_size = LLAPRFile::size(local_filename);
847 if (local_size > 0)
848 {
849 return TRUE ;
850 }
851 }
852
853 // If not, is it a jpeg file?
854 { 818 {
855 local_filename = filename + ".jpg"; 819 mHeaderMutex.lock();
856 local_size = LLAPRFile::size(local_filename); 820 size_map_t::iterator iter1 = mTexturesSizeMap.find(id);
857 if (local_size > 0) 821 if (iter1 == mTexturesSizeMap.end() || iter1->second < bodysize)
858 { 822 {
859 return TRUE ; 823 llassert_always(bodysize > 0);
824
825 S32 oldbodysize = 0;
826 if (iter1 != mTexturesSizeMap.end())
827 {
828 oldbodysize = iter1->second;
829 }
830
831 Entry entry;
832 S32 idx = openAndReadEntry(id, entry, false);
833 if (idx < 0)
834 {
835 llwarns << "Failed to open entry: " << id << llendl;
836 mHeaderMutex.unlock();
837 removeFromCache(id);
838 return false;
839 }
840 else if (oldbodysize != entry.mBodySize)
841 {
842 llwarns << "Entry mismatch in mTextureSizeMap / mHeaderIDMap"
843 << " idx=" << idx << " oldsize=" << oldbodysize << " entrysize=" << entry.mBodySize << llendl;
844 }
845 entry.mBodySize = bodysize;
846 writeEntryAndClose(idx, entry);
847
848 mTexturesSizeTotal -= oldbodysize;
849 mTexturesSizeTotal += bodysize;
850
851 if (mTexturesSizeTotal > sCacheMaxTexturesSize)
852 {
853 purge = true;
854 }
855 res = true;
860 } 856 }
861 } 857 }
862 858 if (purge)
863 // Hmm... What about a targa file? (used for UI texture mostly)
864 { 859 {
865 local_filename = filename + ".tga"; 860 mDoPurge = TRUE;
866 local_size = LLAPRFile::size(local_filename);
867 if (local_size > 0)
868 {
869 return TRUE ;
870 }
871 } 861 }
872 862 mHeaderMutex.unlock();
873 return FALSE ; 863 return res;
874} 864}
865
875////////////////////////////////////////////////////////////////////////////// 866//////////////////////////////////////////////////////////////////////////////
876 867
877//static 868//static
@@ -902,21 +893,13 @@ void LLTextureCache::purgeCache(ELLPath location)
902 LLAPRFile::remove(mHeaderEntriesFileName); 893 LLAPRFile::remove(mHeaderEntriesFileName);
903 LLAPRFile::remove(mHeaderDataFileName); 894 LLAPRFile::remove(mHeaderDataFileName);
904 } 895 }
905 //remove the current texture cache.
906 purgeAllTextures(true); 896 purgeAllTextures(true);
907} 897}
908 898
909//is called in the main thread before initCache(...) is called. 899S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only)
910void LLTextureCache::setReadOnly(BOOL read_only)
911{ 900{
912 mReadOnly = read_only; 901 mReadOnly = read_only;
913} 902
914
915//called in the main thread.
916S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL disable_texture_cache)
917{
918 llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized.
919
920 S64 header_size = (max_size * 2) / 10; 903 S64 header_size = (max_size * 2) / 10;
921 S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE; 904 S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE;
922 sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries)); 905 sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries));
@@ -928,15 +911,6 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL disable_textu
928 sCacheMaxTexturesSize = max_size; 911 sCacheMaxTexturesSize = max_size;
929 max_size -= sCacheMaxTexturesSize; 912 max_size -= sCacheMaxTexturesSize;
930 913
931 if(disable_texture_cache) //the texture cache is disabled
932 {
933 llinfos << "The texture cache is disabled!" << llendl ;
934 setReadOnly(TRUE) ;
935 purgeAllTextures(true);
936
937 return max_size ;
938 }
939
940 LL_INFOS("TextureCache") << "Headers: " << sCacheMaxEntries 914 LL_INFOS("TextureCache") << "Headers: " << sCacheMaxEntries
941 << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << LL_ENDL; 915 << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << LL_ENDL;
942 916
@@ -945,7 +919,6 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL disable_textu
945 if (!mReadOnly) 919 if (!mReadOnly)
946 { 920 {
947 LLFile::mkdir(mTexturesDirName); 921 LLFile::mkdir(mTexturesDirName);
948
949 const char* subdirs = "0123456789abcdef"; 922 const char* subdirs = "0123456789abcdef";
950 for (S32 i=0; i<16; i++) 923 for (S32 i=0; i<16; i++)
951 { 924 {
@@ -956,8 +929,6 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL disable_textu
956 readHeaderCache(); 929 readHeaderCache();
957 purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it 930 purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it
958 931
959 llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized.
960
961 return max_size; // unused cache space 932 return max_size; // unused cache space
962} 933}
963 934
@@ -969,20 +940,13 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset)
969 llassert_always(mHeaderAPRFile == NULL); 940 llassert_always(mHeaderAPRFile == NULL);
970 apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY; 941 apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY;
971 mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, LLAPRFile::local); 942 mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, LLAPRFile::local);
972 if(offset > 0) 943 mHeaderAPRFile->seek(APR_SET, offset);
973 {
974 mHeaderAPRFile->seek(APR_SET, offset);
975 }
976 return mHeaderAPRFile; 944 return mHeaderAPRFile;
977} 945}
978 946
979void LLTextureCache::closeHeaderEntriesFile() 947void LLTextureCache::closeHeaderEntriesFile()
980{ 948{
981 if(!mHeaderAPRFile) 949 llassert_always(mHeaderAPRFile != NULL);
982 {
983 return ;
984 }
985
986 delete mHeaderAPRFile; 950 delete mHeaderAPRFile;
987 mHeaderAPRFile = NULL; 951 mHeaderAPRFile = NULL;
988} 952}
@@ -995,12 +959,6 @@ void LLTextureCache::readEntriesHeader()
995 { 959 {
996 LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); 960 LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
997 } 961 }
998 else //create an empty entries header.
999 {
1000 mHeaderEntriesInfo.mVersion = sHeaderCacheVersion ;
1001 mHeaderEntriesInfo.mEntries = 0 ;
1002 writeEntriesHeader() ;
1003 }
1004} 962}
1005 963
1006void LLTextureCache::writeEntriesHeader() 964void LLTextureCache::writeEntriesHeader()
@@ -1012,7 +970,8 @@ void LLTextureCache::writeEntriesHeader()
1012 } 970 }
1013} 971}
1014 972
1015//mHeaderMutex is locked before calling this. 973static S32 mHeaderEntriesMaxWriteIdx = 0;
974
1016S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create) 975S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create)
1017{ 976{
1018 S32 idx = -1; 977 S32 idx = -1;
@@ -1052,7 +1011,8 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create
1052 if (iter3 != mHeaderIDMap.end() && iter3->second >= 0) 1011 if (iter3 != mHeaderIDMap.end() && iter3->second >= 0)
1053 { 1012 {
1054 idx = iter3->second; 1013 idx = iter3->second;
1055 removeCachedTexture(oldid) ;//remove the existing cached texture to release the entry index. 1014 mHeaderIDMap.erase(oldid);
1015 mTexturesSizeMap.erase(oldid);
1056 break; 1016 break;
1057 } 1017 }
1058 } 1018 }
@@ -1062,9 +1022,20 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create
1062 } 1022 }
1063 if (idx >= 0) 1023 if (idx >= 0)
1064 { 1024 {
1065 entry.mID = id ; 1025 // Set the header index
1066 entry.mImageSize = -1 ; //mark it is a brand-new entry. 1026 mHeaderIDMap[id] = idx;
1067 entry.mBodySize = 0 ; 1027 llassert_always(mTexturesSizeMap.erase(id) == 0);
1028 // Initialize the entry (will get written later)
1029 entry.init(id, time(NULL));
1030 // Update Header
1031 writeEntriesHeader();
1032 // Write Entry
1033 S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
1034 LLAPRFile* aprfile = openHeaderEntriesFile(false, offset);
1035 S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry));
1036 llassert_always(bytes_written == sizeof(Entry));
1037 mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx);
1038 closeHeaderEntriesFile();
1068 } 1039 }
1069 } 1040 }
1070 } 1041 }
@@ -1073,153 +1044,44 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create
1073 // Remove this entry from the LRU if it exists 1044 // Remove this entry from the LRU if it exists
1074 mLRU.erase(id); 1045 mLRU.erase(id);
1075 // Read the entry 1046 // Read the entry
1076 idx_entry_map_t::iterator iter = mUpdatedEntryMap.find(idx) ; 1047 S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
1077 if(iter != mUpdatedEntryMap.end()) 1048 LLAPRFile* aprfile = openHeaderEntriesFile(true, offset);
1078 { 1049 S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry));
1079 entry = iter->second ; 1050 llassert_always(bytes_read == sizeof(Entry));
1080 } 1051 llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize);
1081 else 1052 closeHeaderEntriesFile();
1082 {
1083 readEntryFromHeaderImmediately(idx, entry) ;
1084 }
1085 if(entry.mImageSize <= entry.mBodySize)//it happens on 64-bit systems, do not know why
1086 {
1087 llwarns << "corrupted entry: " << id << " entry image size: " << entry.mImageSize << " entry body size: " << entry.mBodySize << llendl ;
1088
1089 //erase this entry and the cached texture from the cache.
1090 std::string tex_filename = getTextureFileName(id);
1091 removeEntry(idx, entry, tex_filename) ;
1092 mUpdatedEntryMap.erase(idx) ;
1093 idx = -1 ;
1094 }
1095 } 1053 }
1096 return idx; 1054 return idx;
1097} 1055}
1098 1056
1099//mHeaderMutex is locked before calling this. 1057void LLTextureCache::writeEntryAndClose(S32 idx, Entry& entry)
1100void LLTextureCache::writeEntryToHeaderImmediately(S32& idx, Entry& entry, bool write_header)
1101{
1102 LLAPRFile* aprfile ;
1103 S32 bytes_written ;
1104 S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
1105 if(write_header)
1106 {
1107 aprfile = openHeaderEntriesFile(false, 0);
1108 bytes_written = aprfile->write((U8*)&mHeaderEntriesInfo, sizeof(EntriesInfo)) ;
1109 if(bytes_written != sizeof(EntriesInfo))
1110 {
1111 clearCorruptedCache() ; //clear the cache.
1112 idx = -1 ;//mark the idx invalid.
1113 return ;
1114 }
1115
1116 mHeaderAPRFile->seek(APR_SET, offset);
1117 }
1118 else
1119 {
1120 aprfile = openHeaderEntriesFile(false, offset);
1121 }
1122 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry));
1123 if(bytes_written != sizeof(Entry))
1124 {
1125 clearCorruptedCache() ; //clear the cache.
1126 idx = -1 ;//mark the idx invalid.
1127
1128 return ;
1129 }
1130
1131 closeHeaderEntriesFile();
1132 mUpdatedEntryMap.erase(idx) ;
1133}
1134
1135//mHeaderMutex is locked before calling this.
1136void LLTextureCache::readEntryFromHeaderImmediately(S32& idx, Entry& entry)
1137{
1138 S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
1139 LLAPRFile* aprfile = openHeaderEntriesFile(true, offset);
1140 S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry));
1141 closeHeaderEntriesFile();
1142
1143 if(bytes_read != sizeof(Entry))
1144 {
1145 clearCorruptedCache() ; //clear the cache.
1146 idx = -1 ;//mark the idx invalid.
1147 }
1148}
1149
1150//mHeaderMutex is locked before calling this.
1151//update an existing entry time stamp, delay writing.
1152void LLTextureCache::updateEntryTimeStamp(S32 idx, Entry& entry)
1153{ 1058{
1154 static const U32 MAX_ENTRIES_WITHOUT_TIME_STAMP = (U32)(LLTextureCache::sCacheMaxEntries * 0.75f) ;
1155
1156 if(mHeaderEntriesInfo.mEntries < MAX_ENTRIES_WITHOUT_TIME_STAMP)
1157 {
1158 return ; //there are enough empty entry index space, no need to stamp time.
1159 }
1160
1161 if (idx >= 0) 1059 if (idx >= 0)
1162 { 1060 {
1163 if (!mReadOnly) 1061 if (!mReadOnly)
1164 { 1062 {
1165 entry.mTime = time(NULL); 1063 entry.mTime = time(NULL);
1166 mUpdatedEntryMap[idx] = entry ; 1064 if(entry.mImageSize < entry.mBodySize)
1167 } 1065 {
1168 } 1066 // Just say no, due to my messing around to cache discards other than 0 we can end up here
1169} 1067 // after recalling an image from cache at a lower discard than cached. RC
1170 1068 return;
1171//update an existing entry, write to header file immediately. 1069 }
1172bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 new_data_size)
1173{
1174 S32 new_body_size = llmax(0, new_data_size - TEXTURE_CACHE_ENTRY_SIZE) ;
1175
1176 if(new_image_size == entry.mImageSize && new_body_size == entry.mBodySize)
1177 {
1178 return true ; //nothing changed.
1179 }
1180 else
1181 {
1182 bool purge = false ;
1183
1184 lockHeaders() ;
1185
1186 bool update_header = false ;
1187 if(entry.mImageSize < 0) //is a brand-new entry
1188 {
1189 mHeaderIDMap[entry.mID] = idx;
1190 mTexturesSizeMap[entry.mID] = new_body_size ;
1191 mTexturesSizeTotal += new_body_size ;
1192
1193 // Update Header
1194 update_header = true ;
1195 }
1196 else if (entry.mBodySize != new_body_size)
1197 {
1198 //already in mHeaderIDMap.
1199 mTexturesSizeMap[entry.mID] = new_body_size ;
1200 mTexturesSizeTotal -= entry.mBodySize ;
1201 mTexturesSizeTotal += new_body_size ;
1202 }
1203 entry.mTime = time(NULL);
1204 entry.mImageSize = new_image_size ;
1205 entry.mBodySize = new_body_size ;
1206
1207 writeEntryToHeaderImmediately(idx, entry, update_header) ;
1208
1209 if (mTexturesSizeTotal > sCacheMaxTexturesSize)
1210 {
1211 purge = true;
1212 }
1213
1214 unlockHeaders() ;
1215 1070
1216 if (purge) 1071 llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize);
1217 { 1072 if (entry.mBodySize > 0)
1218 mDoPurge = TRUE; 1073 {
1074 mTexturesSizeMap[entry.mID] = entry.mBodySize;
1075 }
1076// llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl;
1077 S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
1078 LLAPRFile* aprfile = openHeaderEntriesFile(false, offset);
1079 S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry));
1080 llassert_always(bytes_written == sizeof(Entry));
1081 mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx);
1082 closeHeaderEntriesFile();
1219 } 1083 }
1220 } 1084 }
1221
1222 return false ;
1223} 1085}
1224 1086
1225U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) 1087U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries)
@@ -1231,21 +1093,7 @@ U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries)
1231 mFreeList.clear(); 1093 mFreeList.clear();
1232 mTexturesSizeTotal = 0; 1094 mTexturesSizeTotal = 0;
1233 1095
1234 LLAPRFile* aprfile = NULL; 1096 LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo));
1235 if(mUpdatedEntryMap.empty())
1236 {
1237 aprfile = openHeaderEntriesFile(true, (S32)sizeof(EntriesInfo));
1238 }
1239 else //update the header file first.
1240 {
1241 aprfile = openHeaderEntriesFile(false, 0);
1242 updatedHeaderEntriesFile() ;
1243 if(!aprfile)
1244 {
1245 return 0;
1246 }
1247 aprfile->seek(APR_SET, (S32)sizeof(EntriesInfo));
1248 }
1249 for (U32 idx=0; idx<num_entries; idx++) 1097 for (U32 idx=0; idx<num_entries; idx++)
1250 { 1098 {
1251 Entry entry; 1099 Entry entry;
@@ -1259,15 +1107,19 @@ U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries)
1259 } 1107 }
1260 entries.push_back(entry); 1108 entries.push_back(entry);
1261// llinfos << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << llendl; 1109// llinfos << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << llendl;
1262 if(entry.mImageSize > entry.mBodySize) 1110 if (entry.mImageSize < 0)
1263 { 1111 {
1264 mHeaderIDMap[entry.mID] = idx; 1112 mFreeList.insert(idx);
1265 mTexturesSizeMap[entry.mID] = entry.mBodySize;
1266 mTexturesSizeTotal += entry.mBodySize;
1267 } 1113 }
1268 else 1114 else
1269 { 1115 {
1270 mFreeList.insert(idx); 1116 mHeaderIDMap[entry.mID] = idx;
1117 if (entry.mBodySize > 0)
1118 {
1119 mTexturesSizeMap[entry.mID] = entry.mBodySize;
1120 mTexturesSizeTotal += entry.mBodySize;
1121 }
1122 llassert_always(entry.mImageSize == 0 || entry.mImageSize > entry.mBodySize);
1271 } 1123 }
1272 } 1124 }
1273 closeHeaderEntriesFile(); 1125 closeHeaderEntriesFile();
@@ -1285,65 +1137,13 @@ void LLTextureCache::writeEntriesAndClose(const std::vector<Entry>& entries)
1285 for (S32 idx=0; idx<num_entries; idx++) 1137 for (S32 idx=0; idx<num_entries; idx++)
1286 { 1138 {
1287 S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry)); 1139 S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry));
1288 if(bytes_written != sizeof(Entry)) 1140 llassert_always(bytes_written == sizeof(Entry));
1289 {
1290 clearCorruptedCache() ; //clear the cache.
1291 return ;
1292 }
1293 } 1141 }
1142 mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, num_entries-1);
1294 closeHeaderEntriesFile(); 1143 closeHeaderEntriesFile();
1295 } 1144 }
1296} 1145}
1297 1146
1298void LLTextureCache::writeUpdatedEntries()
1299{
1300 lockHeaders() ;
1301 if (!mReadOnly && !mUpdatedEntryMap.empty())
1302 {
1303 openHeaderEntriesFile(false, 0);
1304 updatedHeaderEntriesFile() ;
1305 closeHeaderEntriesFile();
1306 }
1307 unlockHeaders() ;
1308}
1309
1310//mHeaderMutex is locked and mHeaderAPRFile is created before calling this.
1311void LLTextureCache::updatedHeaderEntriesFile()
1312{
1313 if (!mReadOnly && !mUpdatedEntryMap.empty() && mHeaderAPRFile)
1314 {
1315 //entriesInfo
1316 mHeaderAPRFile->seek(APR_SET, 0);
1317 S32 bytes_written = mHeaderAPRFile->write((U8*)&mHeaderEntriesInfo, sizeof(EntriesInfo)) ;
1318 if(bytes_written != sizeof(EntriesInfo))
1319 {
1320 clearCorruptedCache() ; //clear the cache.
1321 return ;
1322 }
1323
1324 //write each updated entry
1325 S32 entry_size = (S32)sizeof(Entry) ;
1326 S32 prev_idx = -1 ;
1327 S32 delta_idx ;
1328 for (idx_entry_map_t::iterator iter = mUpdatedEntryMap.begin(); iter != mUpdatedEntryMap.end(); ++iter)
1329 {
1330 delta_idx = iter->first - prev_idx - 1;
1331 prev_idx = iter->first ;
1332 if(delta_idx)
1333 {
1334 mHeaderAPRFile->seek(APR_CUR, delta_idx * entry_size);
1335 }
1336
1337 bytes_written = mHeaderAPRFile->write((void*)(&iter->second), entry_size);
1338 if(bytes_written != entry_size)
1339 {
1340 clearCorruptedCache() ; //clear the cache.
1341 return ;
1342 }
1343 }
1344 mUpdatedEntryMap.clear() ;
1345 }
1346}
1347//---------------------------------------------------------------------------- 1147//----------------------------------------------------------------------------
1348 1148
1349// Called from either the main thread or the worker thread 1149// Called from either the main thread or the worker thread
@@ -1369,27 +1169,28 @@ void LLTextureCache::readHeaderCache()
1369 if (num_entries) 1169 if (num_entries)
1370 { 1170 {
1371 U32 empty_entries = 0; 1171 U32 empty_entries = 0;
1372 typedef std::pair<U32, S32> lru_data_t; 1172 typedef std::pair<U32, LLUUID> lru_data_t;
1373 std::set<lru_data_t> lru; 1173 std::set<lru_data_t> lru;
1374 std::set<U32> purge_list; 1174 std::vector<LLUUID> purge_list;
1375 for (U32 i=0; i<num_entries; i++) 1175 for (U32 i=0; i<num_entries; i++)
1376 { 1176 {
1377 Entry& entry = entries[i]; 1177 Entry& entry = entries[i];
1378 if (entry.mImageSize <= 0) 1178 const LLUUID& id = entry.mID;
1179 if (entry.mImageSize < 0)
1379 { 1180 {
1380 // This will be in the Free List, don't put it in the LRU 1181 // This will be in the Free List, don't put it in the LRU
1381 ++empty_entries; 1182 ++empty_entries;
1382 } 1183 }
1383 else 1184 else
1384 { 1185 {
1385 lru.insert(std::make_pair(entry.mTime, i)); 1186 lru.insert(std::make_pair(entry.mTime, id));
1386 if (entry.mBodySize > 0) 1187 if (entry.mBodySize > 0)
1387 { 1188 {
1388 if (entry.mBodySize > entry.mImageSize) 1189 if (entry.mBodySize > entry.mImageSize)
1389 { 1190 {
1390 // Shouldn't happen, failsafe only 1191 // Shouldn't happen, failsafe only
1391 llwarns << "Bad entry: " << i << ": " << entry.mID << ": BodySize: " << entry.mBodySize << llendl; 1192 llwarns << "Bad entry: " << i << ": " << id << ": BodySize: " << entry.mBodySize << llendl;
1392 purge_list.insert(i); 1193 purge_list.push_back(id);
1393 } 1194 }
1394 } 1195 }
1395 } 1196 }
@@ -1399,24 +1200,22 @@ void LLTextureCache::readHeaderCache()
1399 // Special case: cache size was reduced, need to remove entries 1200 // Special case: cache size was reduced, need to remove entries
1400 // Note: After we prune entries, we will call this again and create the LRU 1201 // Note: After we prune entries, we will call this again and create the LRU
1401 U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries; 1202 U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries;
1402 llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl;
1403 if (entries_to_purge > 0) 1203 if (entries_to_purge > 0)
1404 { 1204 {
1405 for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) 1205 for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter)
1406 { 1206 {
1407 purge_list.insert(iter->second); 1207 purge_list.push_back(iter->second);
1408 if (purge_list.size() >= entries_to_purge) 1208 if (--entries_to_purge <= 0)
1409 break; 1209 break;
1410 } 1210 }
1411 } 1211 }
1412 llassert_always(purge_list.size() >= entries_to_purge);
1413 } 1212 }
1414 else 1213 else
1415 { 1214 {
1416 S32 lru_entries = (S32)((F32)sCacheMaxEntries * TEXTURE_CACHE_LRU_SIZE); 1215 S32 lru_entries = (S32)((F32)sCacheMaxEntries * TEXTURE_CACHE_LRU_SIZE);
1417 for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) 1216 for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter)
1418 { 1217 {
1419 mLRU.insert(entries[iter->second].mID); 1218 mLRU.insert(iter->second);
1420// llinfos << "LRU: " << iter->first << " : " << iter->second << llendl; 1219// llinfos << "LRU: " << iter->first << " : " << iter->second << llendl;
1421 if (--lru_entries <= 0) 1220 if (--lru_entries <= 0)
1422 break; 1221 break;
@@ -1425,10 +1224,11 @@ void LLTextureCache::readHeaderCache()
1425 1224
1426 if (purge_list.size() > 0) 1225 if (purge_list.size() > 0)
1427 { 1226 {
1428 for (std::set<U32>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) 1227 for (std::vector<LLUUID>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter)
1429 { 1228 {
1430 std::string tex_filename = getTextureFileName(entries[*iter].mID); 1229 mHeaderMutex.unlock();
1431 removeEntry((S32)*iter, entries[*iter], tex_filename); 1230 removeFromCache(*iter);
1231 mHeaderMutex.lock();
1432 } 1232 }
1433 // If we removed any entries, we need to rebuild the entries list, 1233 // If we removed any entries, we need to rebuild the entries list,
1434 // write the header, and call this again 1234 // write the header, and call this again
@@ -1436,14 +1236,13 @@ void LLTextureCache::readHeaderCache()
1436 for (U32 i=0; i<num_entries; i++) 1236 for (U32 i=0; i<num_entries; i++)
1437 { 1237 {
1438 const Entry& entry = entries[i]; 1238 const Entry& entry = entries[i];
1439 if (entry.mImageSize > 0) 1239 if (entry.mImageSize >=0)
1440 { 1240 {
1441 new_entries.push_back(entry); 1241 new_entries.push_back(entry);
1442 } 1242 }
1443 } 1243 }
1444 llassert_always(new_entries.size() <= sCacheMaxEntries); 1244 llassert_always(new_entries.size() <= sCacheMaxEntries);
1445 mHeaderEntriesInfo.mEntries = new_entries.size(); 1245 mHeaderEntriesInfo.mEntries = new_entries.size();
1446 writeEntriesHeader();
1447 writeEntriesAndClose(new_entries); 1246 writeEntriesAndClose(new_entries);
1448 mHeaderMutex.unlock(); // unlock the mutex before calling again 1247 mHeaderMutex.unlock(); // unlock the mutex before calling again
1449 readHeaderCache(); // repeat with new entries file 1248 readHeaderCache(); // repeat with new entries file
@@ -1451,7 +1250,7 @@ void LLTextureCache::readHeaderCache()
1451 } 1250 }
1452 else 1251 else
1453 { 1252 {
1454 //entries are not changed, nothing here. 1253 writeEntriesAndClose(entries);
1455 } 1254 }
1456 } 1255 }
1457 } 1256 }
@@ -1460,29 +1259,6 @@ void LLTextureCache::readHeaderCache()
1460 1259
1461////////////////////////////////////////////////////////////////////////////// 1260//////////////////////////////////////////////////////////////////////////////
1462 1261
1463//the header mutex is locked before calling this.
1464void LLTextureCache::clearCorruptedCache()
1465{
1466 llwarns << "the texture cache is corrupted, need to be cleared." << llendl ;
1467
1468 closeHeaderEntriesFile();//close possible file handler
1469 purgeAllTextures(false) ; //clear the cache.
1470
1471 if (!mReadOnly) //regenerate the directory tree if not exists.
1472 {
1473 LLFile::mkdir(mTexturesDirName);
1474
1475 const char* subdirs = "0123456789abcdef";
1476 for (S32 i=0; i<16; i++)
1477 {
1478 std::string dirname = mTexturesDirName + gDirUtilp->getDirDelimiter() + subdirs[i];
1479 LLFile::mkdir(dirname);
1480 }
1481 }
1482
1483 return ;
1484}
1485
1486void LLTextureCache::purgeAllTextures(bool purge_directories) 1262void LLTextureCache::purgeAllTextures(bool purge_directories)
1487{ 1263{
1488 if (!mReadOnly) 1264 if (!mReadOnly)
@@ -1493,7 +1269,6 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
1493 for (S32 i=0; i<16; i++) 1269 for (S32 i=0; i<16; i++)
1494 { 1270 {
1495 std::string dirname = mTexturesDirName + delem + subdirs[i]; 1271 std::string dirname = mTexturesDirName + delem + subdirs[i];
1496 llinfos << "Deleting files in directory: " << dirname << llendl;
1497 gDirUtilp->deleteFilesInDir(dirname,mask); 1272 gDirUtilp->deleteFilesInDir(dirname,mask);
1498 if (purge_directories) 1273 if (purge_directories)
1499 { 1274 {
@@ -1502,23 +1277,19 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
1502 } 1277 }
1503 if (purge_directories) 1278 if (purge_directories)
1504 { 1279 {
1505 gDirUtilp->deleteFilesInDir(mTexturesDirName, mask);
1506 LLFile::rmdir(mTexturesDirName); 1280 LLFile::rmdir(mTexturesDirName);
1507 } 1281 }
1508 } 1282 }
1509 mHeaderIDMap.clear(); 1283 mHeaderIDMap.clear();
1510 mTexturesSizeMap.clear(); 1284 mTexturesSizeMap.clear();
1511 mTexturesSizeTotal = 0; 1285 mTexturesSizeTotal = 0;
1512 mFreeList.clear(); 1286 mFreeList.clear();
1513 mTexturesSizeTotal = 0; 1287 mTexturesSizeTotal = 0;
1514 mUpdatedEntryMap.clear();
1515 1288
1516 // Info with 0 entries 1289 // Info with 0 entries
1517 mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; 1290 mHeaderEntriesInfo.mVersion = sHeaderCacheVersion;
1518 mHeaderEntriesInfo.mEntries = 0; 1291 mHeaderEntriesInfo.mEntries = 0;
1519 writeEntriesHeader(); 1292 writeEntriesHeader();
1520
1521 llinfos << "The entire texture cache is cleared." << llendl ;
1522} 1293}
1523 1294
1524void LLTextureCache::purgeTextures(bool validate) 1295void LLTextureCache::purgeTextures(bool validate)
@@ -1543,6 +1314,7 @@ void LLTextureCache::purgeTextures(bool validate)
1543 U32 num_entries = openAndReadEntries(entries); 1314 U32 num_entries = openAndReadEntries(entries);
1544 if (!num_entries) 1315 if (!num_entries)
1545 { 1316 {
1317 writeEntriesAndClose(entries);
1546 return; // nothing to purge 1318 return; // nothing to purge
1547 } 1319 }
1548 1320
@@ -1561,10 +1333,6 @@ void LLTextureCache::purgeTextures(bool validate)
1561 time_idx_set.insert(std::make_pair(entries[idx].mTime, idx)); 1333 time_idx_set.insert(std::make_pair(entries[idx].mTime, idx));
1562// llinfos << "TIME: " << entries[idx].mTime << " TEX: " << entries[idx].mID << " IDX: " << idx << " Size: " << entries[idx].mImageSize << llendl; 1334// llinfos << "TIME: " << entries[idx].mTime << " TEX: " << entries[idx].mID << " IDX: " << idx << " Size: " << entries[idx].mImageSize << llendl;
1563 } 1335 }
1564 else
1565 {
1566 llerrs << "mTexturesSizeMap / mHeaderIDMap corrupted." << llendl ;
1567 }
1568 } 1336 }
1569 } 1337 }
1570 1338
@@ -1616,8 +1384,11 @@ void LLTextureCache::purgeTextures(bool validate)
1616 { 1384 {
1617 purge_count++; 1385 purge_count++;
1618 LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; 1386 LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL;
1619 removeEntry(idx, entries[idx], filename) ; 1387 LLAPRFile::remove(filename);
1620 cache_size -= entries[idx].mBodySize; 1388 cache_size -= entries[idx].mBodySize;
1389 mTexturesSizeTotal -= entries[idx].mBodySize;
1390 entries[idx].mBodySize = 0;
1391 mTexturesSizeMap.erase(entries[idx].mID);
1621 } 1392 }
1622 } 1393 }
1623 1394
@@ -1625,8 +1396,11 @@ void LLTextureCache::purgeTextures(bool validate)
1625 1396
1626 writeEntriesAndClose(entries); 1397 writeEntriesAndClose(entries);
1627 1398
1628 // *FIX:Mani - watchdog back on. 1399 if (!mThreaded)
1629 LLAppViewer::instance()->resumeMainloopTimeout(); 1400 {
1401 // *FIX:Mani - watchdog back on.
1402 LLAppViewer::instance()->resumeMainloopTimeout();
1403 }
1630 1404
1631 LL_INFOS("TextureCache") << "TEXTURE CACHE:" 1405 LL_INFOS("TextureCache") << "TEXTURE CACHE:"
1632 << " PURGED: " << purge_count 1406 << " PURGED: " << purge_count
@@ -1664,38 +1438,40 @@ LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)
1664// Called from work thread 1438// Called from work thread
1665 1439
1666// Reads imagesize from the header, updates timestamp 1440// Reads imagesize from the header, updates timestamp
1667S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, Entry& entry) 1441S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, S32& imagesize)
1668{ 1442{
1669 LLMutexLock lock(&mHeaderMutex); 1443 LLMutexLock lock(&mHeaderMutex);
1444 Entry entry;
1670 S32 idx = openAndReadEntry(id, entry, false); 1445 S32 idx = openAndReadEntry(id, entry, false);
1671 if (idx >= 0) 1446 if (idx >= 0)
1672 { 1447 {
1673 updateEntryTimeStamp(idx, entry); // updates time 1448 imagesize = entry.mImageSize;
1449 writeEntryAndClose(idx, entry); // updates time
1674 } 1450 }
1675 return idx; 1451 return idx;
1676} 1452}
1677 1453
1678// Writes imagesize to the header, updates timestamp 1454// Writes imagesize to the header, updates timestamp
1679S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imagesize, S32 datasize) 1455S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, S32 imagesize)
1680{ 1456{
1681 mHeaderMutex.lock(); 1457 mHeaderMutex.lock();
1458 llassert_always(imagesize >= 0);
1459 Entry entry;
1682 S32 idx = openAndReadEntry(id, entry, true); 1460 S32 idx = openAndReadEntry(id, entry, true);
1683 mHeaderMutex.unlock();
1684
1685 if (idx >= 0) 1461 if (idx >= 0)
1686 { 1462 {
1687 updateEntry(idx, entry, imagesize, datasize); 1463 entry.mImageSize = imagesize;
1464 writeEntryAndClose(idx, entry);
1465 mHeaderMutex.unlock();
1688 } 1466 }
1689 1467 else // retry
1690 if(idx < 0) // retry
1691 { 1468 {
1469 mHeaderMutex.unlock();
1692 readHeaderCache(); // We couldn't write an entry, so refresh the LRU 1470 readHeaderCache(); // We couldn't write an entry, so refresh the LRU
1693
1694 mHeaderMutex.lock(); 1471 mHeaderMutex.lock();
1695 llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries); 1472 llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries);
1696 mHeaderMutex.unlock(); 1473 mHeaderMutex.unlock();
1697 1474 idx = setHeaderCacheEntry(id, imagesize); // assert above ensures no inf. recursion
1698 idx = setHeaderCacheEntry(id, entry, imagesize, datasize); // assert above ensures no inf. recursion
1699 } 1475 }
1700 return idx; 1476 return idx;
1701} 1477}
@@ -1732,34 +1508,39 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri
1732 return handle; 1508 return handle;
1733} 1509}
1734 1510
1735 1511// Return true if the handle is not valid, which is the case
1512// when the worker was already deleted or is scheduled for deletion.
1513//
1514// If the handle exists and a call to worker->complete() returns
1515// true or abort is true, then the handle is removed and the worker
1516// scheduled for deletion.
1736bool LLTextureCache::readComplete(handle_t handle, bool abort) 1517bool LLTextureCache::readComplete(handle_t handle, bool abort)
1737{ 1518{
1738 lockWorkers(); 1519 lockWorkers(); // Needed for access to mReaders.
1520
1739 handle_map_t::iterator iter = mReaders.find(handle); 1521 handle_map_t::iterator iter = mReaders.find(handle);
1522 bool handle_is_valid = iter != mReaders.end();
1523 llassert_always(handle_is_valid || abort);
1740 LLTextureCacheWorker* worker = NULL; 1524 LLTextureCacheWorker* worker = NULL;
1741 bool complete = false; 1525 bool delete_worker = false;
1742 if (iter != mReaders.end()) 1526
1527 if (handle_is_valid)
1743 { 1528 {
1744 worker = iter->second; 1529 worker = iter->second;
1745 complete = worker->complete(); 1530 delete_worker = worker->complete() || abort;
1746 1531 if (delete_worker)
1747 if(!complete && abort)
1748 { 1532 {
1749 abortRequest(handle, true) ; 1533 mReaders.erase(handle);
1534 handle_is_valid = false;
1750 } 1535 }
1751 } 1536 }
1752 if (worker && (complete || abort)) 1537
1753 { 1538 unlockWorkers();
1754 mReaders.erase(iter); 1539
1755 unlockWorkers(); 1540 if (delete_worker) worker->scheduleDelete();
1756 worker->scheduleDelete(); 1541
1757 } 1542 // Return false if the handle is (still) valid.
1758 else 1543 return !handle_is_valid;
1759 {
1760 unlockWorkers();
1761 }
1762 return (complete || abort);
1763} 1544}
1764 1545
1765LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority, 1546LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority,
@@ -1792,20 +1573,20 @@ bool LLTextureCache::writeComplete(handle_t handle, bool abort)
1792{ 1573{
1793 lockWorkers(); 1574 lockWorkers();
1794 handle_map_t::iterator iter = mWriters.find(handle); 1575 handle_map_t::iterator iter = mWriters.find(handle);
1795 llassert(iter != mWriters.end()); 1576 llassert_always(iter != mWriters.end());
1796 if (iter != mWriters.end()) 1577 LLTextureCacheWorker* worker = iter->second;
1578 if (worker->complete() || abort)
1797 { 1579 {
1798 LLTextureCacheWorker* worker = iter->second; 1580 mWriters.erase(handle);
1799 if (worker->complete() || abort) 1581 unlockWorkers();
1800 { 1582 worker->scheduleDelete();
1801 mWriters.erase(handle); 1583 return true;
1802 unlockWorkers(); 1584 }
1803 worker->scheduleDelete(); 1585 else
1804 return true; 1586 {
1805 } 1587 unlockWorkers();
1588 return false;
1806 } 1589 }
1807 unlockWorkers();
1808 return false;
1809} 1590}
1810 1591
1811void LLTextureCache::prioritizeWrite(handle_t handle) 1592void LLTextureCache::prioritizeWrite(handle_t handle)
@@ -1824,56 +1605,38 @@ void LLTextureCache::addCompleted(Responder* responder, bool success)
1824 1605
1825////////////////////////////////////////////////////////////////////////////// 1606//////////////////////////////////////////////////////////////////////////////
1826 1607
1827//called after mHeaderMutex is locked. 1608// Called from MAIN thread (endWork())
1828void LLTextureCache::removeCachedTexture(const LLUUID& id)
1829{
1830 if(mTexturesSizeMap.find(id) != mTexturesSizeMap.end())
1831 {
1832 mTexturesSizeTotal -= mTexturesSizeMap[id] ;
1833 mTexturesSizeMap.erase(id);
1834 }
1835 mHeaderIDMap.erase(id);
1836 LLAPRFile::remove(getTextureFileName(id));
1837}
1838 1609
1839//called after mHeaderMutex is locked. 1610bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id)
1840void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
1841{ 1611{
1842 if(idx >= 0) //valid entry 1612 if (!mReadOnly)
1843 { 1613 {
1844 entry.mImageSize = -1; 1614 LLMutexLock lock(&mHeaderMutex);
1845 entry.mBodySize = 0; 1615 Entry entry;
1846 mHeaderIDMap.erase(entry.mID); 1616 S32 idx = openAndReadEntry(id, entry, false);
1847 mTexturesSizeMap.erase(entry.mID); 1617 if (idx >= 0)
1848 1618 {
1849 mTexturesSizeTotal -= entry.mBodySize; 1619 entry.mImageSize = -1;
1850 mFreeList.insert(idx); 1620 entry.mBodySize = 0;
1621 writeEntryAndClose(idx, entry);
1622 mFreeList.insert(idx);
1623 mHeaderIDMap.erase(id);
1624 mTexturesSizeMap.erase(id);
1625 return true;
1626 }
1851 } 1627 }
1852 1628 return false;
1853 LLAPRFile::remove(filename);
1854} 1629}
1855 1630
1856bool LLTextureCache::removeFromCache(const LLUUID& id) 1631void LLTextureCache::removeFromCache(const LLUUID& id)
1857{ 1632{
1858 //llwarns << "Removing texture from cache: " << id << llendl; 1633 //llwarns << "Removing texture from cache: " << id << llendl;
1859 bool ret = false ;
1860 if (!mReadOnly) 1634 if (!mReadOnly)
1861 { 1635 {
1862 lockHeaders() ; 1636 removeHeaderCacheEntry(id);
1863 1637 LLMutexLock lock(&mHeaderMutex);
1864 Entry entry; 1638 LLAPRFile::remove(getTextureFileName(id));
1865 S32 idx = openAndReadEntry(id, entry, false);
1866 std::string tex_filename = getTextureFileName(id);
1867 removeEntry(idx, entry, tex_filename) ;
1868 if (idx >= 0)
1869 {
1870 writeEntryToHeaderImmediately(idx, entry);
1871 ret = true;
1872 }
1873
1874 unlockHeaders() ;
1875 } 1639 }
1876 return ret ;
1877} 1640}
1878 1641
1879////////////////////////////////////////////////////////////////////////////// 1642//////////////////////////////////////////////////////////////////////////////
diff --git a/linden/indra/newview/lltexturecache.h b/linden/indra/newview/lltexturecache.h
index f80be00..45804c2 100644
--- a/linden/indra/newview/lltexturecache.h
+++ b/linden/indra/newview/lltexturecache.h
@@ -40,7 +40,6 @@
40 40
41#include "llworkerthread.h" 41#include "llworkerthread.h"
42 42
43class LLImageFormatted;
44class LLTextureCacheWorker; 43class LLTextureCacheWorker;
45 44
46class LLTextureCache : public LLWorkerThread 45class LLTextureCache : public LLWorkerThread
@@ -59,16 +58,10 @@ private:
59 }; 58 };
60 struct Entry 59 struct Entry
61 { 60 {
62 Entry() : 61 Entry() {}
63 mBodySize(0),
64 mImageSize(0),
65 mTime(0)
66 {
67 }
68 Entry(const LLUUID& id, S32 imagesize, S32 bodysize, U32 time) : 62 Entry(const LLUUID& id, S32 imagesize, S32 bodysize, U32 time) :
69 mID(id), mImageSize(imagesize), mBodySize(bodysize), mTime(time) {} 63 mID(id), mImageSize(imagesize), mBodySize(bodysize), mTime(time) {}
70 void init(const LLUUID& id, U32 time) { mID = id, mImageSize = 0; mBodySize = 0; mTime = time; } 64 void init(const LLUUID& id, U32 time) { mID = id, mImageSize = 0; mBodySize = 0; mTime = time; }
71 Entry& operator=(const Entry& entry) {mID = entry.mID, mImageSize = entry.mImageSize; mBodySize = entry.mBodySize; mTime = entry.mTime; return *this;}
72 LLUUID mID; // 16 bytes 65 LLUUID mID; // 16 bytes
73 S32 mImageSize; // total size of image if known 66 S32 mImageSize; // total size of image if known
74 S32 mBodySize; // size of body file in body cache 67 S32 mBodySize; // size of body file in body cache
@@ -110,8 +103,7 @@ public:
110 /*virtual*/ S32 update(U32 max_time_ms); 103 /*virtual*/ S32 update(U32 max_time_ms);
111 104
112 void purgeCache(ELLPath location); 105 void purgeCache(ELLPath location);
113 void setReadOnly(BOOL read_only) ; 106 S64 initCache(ELLPath location, S64 maxsize, BOOL read_only);
114 S64 initCache(ELLPath location, S64 maxsize, BOOL disable_texture_cache);
115 107
116 handle_t readFromCache(const std::string& local_filename, const LLUUID& id, U32 priority, S32 offset, S32 size, 108 handle_t readFromCache(const std::string& local_filename, const LLUUID& id, U32 priority, S32 offset, S32 size,
117 ReadResponder* responder); 109 ReadResponder* responder);
@@ -124,7 +116,7 @@ public:
124 bool writeComplete(handle_t handle, bool abort = false); 116 bool writeComplete(handle_t handle, bool abort = false);
125 void prioritizeWrite(handle_t handle); 117 void prioritizeWrite(handle_t handle);
126 118
127 bool removeFromCache(const LLUUID& id); 119 void removeFromCache(const LLUUID& id);
128 120
129 // For LLTextureCacheWorker::Responder 121 // For LLTextureCacheWorker::Responder
130 LLTextureCacheWorker* getReader(handle_t handle); 122 LLTextureCacheWorker* getReader(handle_t handle);
@@ -139,11 +131,10 @@ public:
139 S64 getMaxUsage() { return sCacheMaxTexturesSize; } 131 S64 getMaxUsage() { return sCacheMaxTexturesSize; }
140 U32 getEntries() { return mHeaderEntriesInfo.mEntries; } 132 U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
141 U32 getMaxEntries() { return sCacheMaxEntries; }; 133 U32 getMaxEntries() { return sCacheMaxEntries; };
142 BOOL isInCache(const LLUUID& id) ;
143 BOOL isInLocal(const LLUUID& id) ;
144 134
145protected: 135protected:
146 // Accessed by LLTextureCacheWorker 136 // Accessed by LLTextureCacheWorker
137 bool updateTextureEntryList(const LLUUID& id, S32 size);
147 std::string getLocalFileName(const LLUUID& id); 138 std::string getLocalFileName(const LLUUID& id);
148 std::string getTextureFileName(const LLUUID& id); 139 std::string getTextureFileName(const LLUUID& id);
149 void addCompleted(Responder* responder, bool success); 140 void addCompleted(Responder* responder, bool success);
@@ -154,7 +145,6 @@ protected:
154private: 145private:
155 void setDirNames(ELLPath location); 146 void setDirNames(ELLPath location);
156 void readHeaderCache(); 147 void readHeaderCache();
157 void clearCorruptedCache();
158 void purgeAllTextures(bool purge_directories); 148 void purgeAllTextures(bool purge_directories);
159 void purgeTextures(bool validate); 149 void purgeTextures(bool validate);
160 LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset); 150 LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset);
@@ -162,20 +152,12 @@ private:
162 void readEntriesHeader(); 152 void readEntriesHeader();
163 void writeEntriesHeader(); 153 void writeEntriesHeader();
164 S32 openAndReadEntry(const LLUUID& id, Entry& entry, bool create); 154 S32 openAndReadEntry(const LLUUID& id, Entry& entry, bool create);
165 bool updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 new_body_size); 155 void writeEntryAndClose(S32 idx, Entry& entry);
166 void updateEntryTimeStamp(S32 idx, Entry& entry) ;
167 U32 openAndReadEntries(std::vector<Entry>& entries); 156 U32 openAndReadEntries(std::vector<Entry>& entries);
168 void writeEntriesAndClose(const std::vector<Entry>& entries); 157 void writeEntriesAndClose(const std::vector<Entry>& entries);
169 void readEntryFromHeaderImmediately(S32& idx, Entry& entry) ; 158 S32 getHeaderCacheEntry(const LLUUID& id, S32& imagesize);
170 void writeEntryToHeaderImmediately(S32& idx, Entry& entry, bool write_header = false) ; 159 S32 setHeaderCacheEntry(const LLUUID& id, S32 imagesize);
171 void removeEntry(S32 idx, Entry& entry, std::string& filename); 160 bool removeHeaderCacheEntry(const LLUUID& id);
172 void removeCachedTexture(const LLUUID& id) ;
173 S32 getHeaderCacheEntry(const LLUUID& id, Entry& entry);
174 S32 setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imagesize, S32 datasize);
175 void writeUpdatedEntries() ;
176 void updatedHeaderEntriesFile() ;
177 void lockHeaders() { mHeaderMutex.lock(); }
178 void unlockHeaders() { mHeaderMutex.unlock(); }
179 161
180private: 162private:
181 // Internal 163 // Internal
@@ -212,9 +194,6 @@ private:
212 S64 mTexturesSizeTotal; 194 S64 mTexturesSizeTotal;
213 LLAtomic32<BOOL> mDoPurge; 195 LLAtomic32<BOOL> mDoPurge;
214 196
215 typedef std::map<S32, Entry> idx_entry_map_t;
216 idx_entry_map_t mUpdatedEntryMap;
217
218 // Statics 197 // Statics
219 static F32 sHeaderCacheVersion; 198 static F32 sHeaderCacheVersion;
220 static U32 sCacheMaxEntries; 199 static U32 sCacheMaxEntries;
diff --git a/linden/indra/newview/lltexturefetch.cpp b/linden/indra/newview/lltexturefetch.cpp
index 427e55a..2184478 100644
--- a/linden/indra/newview/lltexturefetch.cpp
+++ b/linden/indra/newview/lltexturefetch.cpp
@@ -1500,8 +1500,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
1500 1500
1501LLTextureFetch::~LLTextureFetch() 1501LLTextureFetch::~LLTextureFetch()
1502{ 1502{
1503 clearDeleteList() ;
1504
1505 // ~LLQueuedThread() called here 1503 // ~LLQueuedThread() called here
1506} 1504}
1507 1505