diff options
Diffstat (limited to 'indra/newview/lltexturecache.cpp')
-rw-r--r-- | indra/newview/lltexturecache.cpp | 458 |
1 files changed, 269 insertions, 189 deletions
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 49770030c6..9ad2322765 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -401,7 +401,8 @@ bool LLTextureCacheRemoteWorker::doRead() // Second state / stage : identify the cache or not... if (!done && (mState == CACHE)) { - idx = mCache->getHeaderCacheEntry(mID, mImageSize); + LLTextureCache::Entry entry ; + idx = mCache->getHeaderCacheEntry(mID, entry); if (idx < 0) { // The texture is *not* cached. We're done here... @@ -410,6 +411,7 @@ bool LLTextureCacheRemoteWorker::doRead() } else { + mImageSize = entry.mImageSize ; // If the read offset is bigger than the header cache, we read directly from the body // Note that currently, we *never* read with offset from the cache, so the result is *always* HEADER mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; @@ -531,13 +533,14 @@ bool LLTextureCacheRemoteWorker::doRead() bool LLTextureCacheRemoteWorker::doWrite() { bool done = false; - S32 idx = -1; + S32 idx = -1; // First state / stage : check that what we're trying to cache is in an OK shape if (mState == INIT) { llassert_always(mOffset == 0); // We currently do not support write offsets llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative... + llassert_always(mImageSize >= mDataSize); mState = CACHE; } @@ -547,14 +550,19 @@ bool LLTextureCacheRemoteWorker::doWrite() if (!done && (mState == CACHE)) { bool alreadyCached = false; - S32 cur_imagesize = 0; + LLTextureCache::Entry entry ; + // Checks if this image is already in the entry list - idx = mCache->getHeaderCacheEntry(mID, cur_imagesize); - if (idx >= 0 && (cur_imagesize >= 0)) + idx = mCache->getHeaderCacheEntry(mID, entry); + if(idx < 0) + { + idx = mCache->setHeaderCacheEntry(mID, entry, mImageSize, mDataSize); // create the new entry. + } + else { - alreadyCached = true; // already there and non empty + alreadyCached = mCache->updateEntry(idx, entry, mImageSize, mDataSize); // update the existing entry. } - idx = mCache->setHeaderCacheEntry(mID, mImageSize); // create or touch the entry + if (idx < 0) { llwarns << "LLTextureCacheWorker: " << mID @@ -564,10 +572,6 @@ bool LLTextureCacheRemoteWorker::doWrite() } else { - if (cur_imagesize > 0 && (mImageSize != cur_imagesize)) - { - alreadyCached = false; // re-write the header if the size changed in all cases - } if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)) { // Small texture already cached case: we're done with writing @@ -630,7 +634,7 @@ bool LLTextureCacheRemoteWorker::doWrite() { llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE); // wouldn't make sense to be here otherwise... S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; - if ((file_size > 0) && mCache->updateTextureEntryList(mID, file_size)) + { // build the cache file name from the UUID std::string filename = mCache->getTextureFileName(mID); @@ -648,10 +652,7 @@ bool LLTextureCacheRemoteWorker::doWrite() done = true; } } - else - { - mDataSize = 0; // no data written - } + // Nothing else to do at that point... done = true; } @@ -742,7 +743,7 @@ LLTextureCache::LLTextureCache(bool threaded) mHeaderMutex(NULL), mListMutex(NULL), mHeaderAPRFile(NULL), - mReadOnly(FALSE), + mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called. mTexturesSizeTotal(0), mDoPurge(FALSE) { @@ -825,58 +826,6 @@ std::string LLTextureCache::getTextureFileName(const LLUUID& id) return filename; } -bool LLTextureCache::updateTextureEntryList(const LLUUID& id, S32 bodysize) -{ - bool res = false; - bool purge = false; - { - LLMutexLock lock(&mHeaderMutex); - size_map_t::iterator iter1 = mTexturesSizeMap.find(id); - if (iter1 == mTexturesSizeMap.end() || iter1->second < bodysize) - { - llassert_always(bodysize > 0); - - S32 oldbodysize = 0; - if (iter1 != mTexturesSizeMap.end()) - { - oldbodysize = iter1->second; - } - - Entry entry; - S32 idx = openAndReadEntry(id, entry, false); - if (idx < 0) - { - llwarns << "Failed to open entry: " << id << llendl; - removeHeaderCacheEntry(id); - LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); - return false; - } - else if (oldbodysize != entry.mBodySize) - { - // TODO: change to llwarns - llerrs << "Entry mismatch in mTextureSizeMap / mHeaderIDMap" - << " idx=" << idx << " oldsize=" << oldbodysize << " entrysize=" << entry.mBodySize << llendl; - } - entry.mBodySize = bodysize; - writeEntryAndClose(idx, entry); - - mTexturesSizeTotal -= oldbodysize; - mTexturesSizeTotal += bodysize; - - if (mTexturesSizeTotal > sCacheMaxTexturesSize) - { - purge = true; - } - res = true; - } - } - if (purge) - { - mDoPurge = TRUE; - } - return res; -} - //debug BOOL LLTextureCache::isInCache(const LLUUID& id) { @@ -934,13 +883,16 @@ U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit const char* entries_filename = "texture.entries"; const char* cache_filename = "texture.cache"; -const char* textures_dirname = "textures"; +const char* old_textures_dirname = "textures"; +//change the location of the texture cache to prevent from being deleted by old version viewers. +const char* textures_dirname = "texturecache"; void LLTextureCache::setDirNames(ELLPath location) { std::string delem = gDirUtilp->getDirDelimiter(); - mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename); - mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename); + + mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, entries_filename); + mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, cache_filename); mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname); } @@ -952,16 +904,38 @@ void LLTextureCache::purgeCache(ELLPath location) { setDirNames(location); llassert_always(mHeaderAPRFile == NULL); - LLAPRFile::remove(mHeaderEntriesFileName, getLocalAPRFilePool()); - LLAPRFile::remove(mHeaderDataFileName, getLocalAPRFilePool()); + + //remove the legacy cache if exists + std::string texture_dir = mTexturesDirName ; + mTexturesDirName = gDirUtilp->getExpandedFilename(location, old_textures_dirname); + if(LLFile::isdir(mTexturesDirName)) + { + std::string file_name = gDirUtilp->getExpandedFilename(location, entries_filename); + LLAPRFile::remove(file_name, getLocalAPRFilePool()); + + file_name = gDirUtilp->getExpandedFilename(location, cache_filename); + LLAPRFile::remove(file_name, getLocalAPRFilePool()); + + purgeAllTextures(true); + } + mTexturesDirName = texture_dir ; } + + //remove the current texture cache. purgeAllTextures(true); } -S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only) +//is called in the main thread before initCache(...) is called. +void LLTextureCache::setReadOnly(BOOL read_only) { - mReadOnly = read_only; - + mReadOnly = read_only ; +} + +//called in the main thread. +S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL disable_texture_cache) +{ + llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized. + S64 header_size = (max_size * 2) / 10; S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE; sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries)); @@ -973,6 +947,15 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only) sCacheMaxTexturesSize = max_size; max_size -= sCacheMaxTexturesSize; + if(disable_texture_cache) //the texture cache is disabled + { + llinfos << "The texture cache is disabled!" << llendl ; + setReadOnly(TRUE) ; + purgeAllTextures(true); + + return max_size ; + } + LL_INFOS("TextureCache") << "Headers: " << sCacheMaxEntries << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << LL_ENDL; @@ -981,6 +964,7 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only) if (!mReadOnly) { LLFile::mkdir(mTexturesDirName); + const char* subdirs = "0123456789abcdef"; for (S32 i=0; i<16; i++) { @@ -991,6 +975,8 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only) readHeaderCache(); purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it + llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized. + return max_size; // unused cache space } @@ -1002,7 +988,10 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset) llassert_always(mHeaderAPRFile == NULL); apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY; mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, getLocalAPRFilePool()); - mHeaderAPRFile->seek(APR_SET, offset); + if(offset > 0) + { + mHeaderAPRFile->seek(APR_SET, offset); + } return mHeaderAPRFile; } @@ -1022,6 +1011,12 @@ void LLTextureCache::readEntriesHeader() LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), getLocalAPRFilePool()); } + else //create an empty entries header. + { + mHeaderEntriesInfo.mVersion = sHeaderCacheVersion ; + mHeaderEntriesInfo.mEntries = 0 ; + writeEntriesHeader() ; + } } void LLTextureCache::writeEntriesHeader() @@ -1034,8 +1029,7 @@ void LLTextureCache::writeEntriesHeader() } } -static S32 mHeaderEntriesMaxWriteIdx = 0; - +//mHeaderMutex is locked before calling this. S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create) { S32 idx = -1; @@ -1075,8 +1069,7 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create if (iter3 != mHeaderIDMap.end() && iter3->second >= 0) { idx = iter3->second; - mHeaderIDMap.erase(oldid); - mTexturesSizeMap.erase(oldid); + removeCachedTexture(oldid) ;//remove the existing cached texture to release the entry index. break; } } @@ -1086,22 +1079,9 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create } if (idx >= 0) { - // Set the header index - mHeaderIDMap[id] = idx; - llassert_always(mTexturesSizeMap.erase(id) == 0); - // Initialize the entry (will get written later) - entry.init(id, time(NULL)); - // Update Header - writeEntriesHeader(); - - //the new entry, write immediately. - // Write Entry - S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - LLAPRFile* aprfile = openHeaderEntriesFile(false, offset); - S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); - llassert_always(bytes_written == sizeof(Entry)); - mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx); - closeHeaderEntriesFile(); + entry.mID = id ; + entry.mImageSize = -1 ; //mark it is a brand-new entry. + entry.mBodySize = 0 ; } } } @@ -1117,40 +1097,130 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create } else { - S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - LLAPRFile* aprfile = openHeaderEntriesFile(true, offset); - S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry)); - llassert_always(bytes_read == sizeof(Entry)); - closeHeaderEntriesFile(); + readEntryFromHeaderImmediately(idx, entry) ; + } + if(entry.mImageSize <= entry.mBodySize)//it happens on 64-bit systems, do not know why + { + llwarns << "corrupted entry: " << id << " entry image size: " << entry.mImageSize << " entry body size: " << entry.mBodySize << llendl ; + + //erase this entry and the cached texture from the cache. + std::string tex_filename = getTextureFileName(id); + removeEntry(idx, entry, tex_filename) ; + mUpdatedEntryMap.erase(idx) ; + idx = -1 ; } - llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); } return idx; } -void LLTextureCache::writeEntryAndClose(S32 idx, Entry& entry) +//mHeaderMutex is locked before calling this. +void LLTextureCache::writeEntryToHeaderImmediately(S32 idx, Entry& entry, bool write_header) +{ + LLAPRFile* aprfile ; + S32 bytes_written ; + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + if(write_header) + { + aprfile = openHeaderEntriesFile(false, 0); + bytes_written = aprfile->write((U8*)&mHeaderEntriesInfo, sizeof(EntriesInfo)) ; + llassert_always(bytes_written == sizeof(EntriesInfo)); + mHeaderAPRFile->seek(APR_SET, offset); + } + else + { + aprfile = openHeaderEntriesFile(false, offset); + } + bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); + llassert_always(bytes_written == sizeof(Entry)); + closeHeaderEntriesFile(); + mUpdatedEntryMap.erase(idx) ; +} + +//mHeaderMutex is locked before calling this. +void LLTextureCache::readEntryFromHeaderImmediately(S32 idx, Entry& entry) +{ + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + LLAPRFile* aprfile = openHeaderEntriesFile(true, offset); + S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry)); + llassert_always(bytes_read == sizeof(Entry)); + closeHeaderEntriesFile(); +} + +//mHeaderMutex is locked before calling this. +//update an existing entry time stamp, delay writing. +void LLTextureCache::updateEntryTimeStamp(S32 idx, Entry& entry) { + static const U32 MAX_ENTRIES_WITHOUT_TIME_STAMP = (U32)(LLTextureCache::sCacheMaxEntries * 0.75f) ; + + if(mHeaderEntriesInfo.mEntries < MAX_ENTRIES_WITHOUT_TIME_STAMP) + { + return ; //there are enough empty entry index space, no need to stamp time. + } + if (idx >= 0) { if (!mReadOnly) { - entry.mTime = time(NULL); - llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); - if (entry.mBodySize > 0) - { - mTexturesSizeMap[entry.mID] = entry.mBodySize; - } - else if(mTexturesSizeMap.find(entry.mID) != mTexturesSizeMap.end() && mTexturesSizeMap[entry.mID] > 0) - { - llerrs << "mTexturesSizeMap / mHeaderIDMap corrupted." << llendl ; - } -// llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl; - mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx); + entry.mTime = time(NULL); mUpdatedEntryMap[idx] = entry ; } } } +//update an existing entry, write to header file immediately. +bool LLTextureCache::updateEntry(S32 idx, Entry& entry, S32 new_image_size, S32 new_data_size) +{ + S32 new_body_size = llmax(0, new_data_size - TEXTURE_CACHE_ENTRY_SIZE) ; + + if(new_image_size == entry.mImageSize && new_body_size == entry.mBodySize) + { + return true ; //nothing changed. + } + else + { + bool purge = false ; + + lockHeaders() ; + + bool update_header = false ; + if(entry.mImageSize < 0) //is a brand-new entry + { + mHeaderIDMap[entry.mID] = idx; + mTexturesSizeMap[entry.mID] = new_body_size ; + mTexturesSizeTotal += new_body_size ; + + // Update Header + update_header = true ; + } + else if (entry.mBodySize != new_body_size) + { + //already in mHeaderIDMap. + mTexturesSizeMap[entry.mID] = new_body_size ; + mTexturesSizeTotal -= entry.mBodySize ; + mTexturesSizeTotal += new_body_size ; + } + entry.mTime = time(NULL); + entry.mImageSize = new_image_size ; + entry.mBodySize = new_body_size ; + + writeEntryToHeaderImmediately(idx, entry, update_header) ; + + if (mTexturesSizeTotal > sCacheMaxTexturesSize) + { + purge = true; + } + + unlockHeaders() ; + + if (purge) + { + mDoPurge = TRUE; + } + } + + return false ; +} + U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) { U32 num_entries = mHeaderEntriesInfo.mEntries; @@ -1160,8 +1230,17 @@ U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) mFreeList.clear(); mTexturesSizeTotal = 0; - LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); - updatedHeaderEntriesFile() ; + LLAPRFile* aprfile = NULL; + if(mUpdatedEntryMap.empty()) + { + aprfile = openHeaderEntriesFile(true, (S32)sizeof(EntriesInfo)); + } + else //update the header file first. + { + aprfile = openHeaderEntriesFile(false, 0); + updatedHeaderEntriesFile() ; + aprfile->seek(APR_SET, (S32)sizeof(EntriesInfo)); + } for (U32 idx=0; idx<num_entries; idx++) { Entry entry; @@ -1175,19 +1254,15 @@ U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) } entries.push_back(entry); // llinfos << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << llendl; - if (entry.mImageSize < 0) + if(entry.mImageSize > entry.mBodySize) { - mFreeList.insert(idx); + mHeaderIDMap[entry.mID] = idx; + mTexturesSizeMap[entry.mID] = entry.mBodySize; + mTexturesSizeTotal += entry.mBodySize; } else { - mHeaderIDMap[entry.mID] = idx; - if (entry.mBodySize > 0) - { - mTexturesSizeMap[entry.mID] = entry.mBodySize; - mTexturesSizeTotal += entry.mBodySize; - } - llassert_always(entry.mImageSize == 0 || entry.mImageSize > entry.mBodySize); + mFreeList.insert(idx); } } closeHeaderEntriesFile(); @@ -1207,7 +1282,6 @@ void LLTextureCache::writeEntriesAndClose(const std::vector<Entry>& entries) S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry)); llassert_always(bytes_written == sizeof(Entry)); } - mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, num_entries-1); closeHeaderEntriesFile(); } } @@ -1280,12 +1354,11 @@ void LLTextureCache::readHeaderCache() U32 empty_entries = 0; typedef std::pair<U32, S32> lru_data_t; std::set<lru_data_t> lru; - std::set<LLUUID> purge_list; + std::set<U32> purge_list; for (U32 i=0; i<num_entries; i++) { Entry& entry = entries[i]; - const LLUUID& id = entry.mID; - if (entry.mImageSize < 0) + if (entry.mImageSize <= 0) { // This will be in the Free List, don't put it in the LRU ++empty_entries; @@ -1298,9 +1371,8 @@ void LLTextureCache::readHeaderCache() if (entry.mBodySize > entry.mImageSize) { // Shouldn't happen, failsafe only - llwarns << "Bad entry: " << i << ": " << id << ": BodySize: " << entry.mBodySize << llendl; - purge_list.insert(entry.mID); - entry.mImageSize = -1; // empty/available + llwarns << "Bad entry: " << i << ": " << entry.mID << ": BodySize: " << entry.mBodySize << llendl; + purge_list.insert(i); } } } @@ -1315,14 +1387,9 @@ void LLTextureCache::readHeaderCache() { for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) { - S32 idx = iter->second; - if (entries[idx].mImageSize >= 0) - { - purge_list.insert(entries[idx].mID); - entries[idx].mImageSize = -1; - if (purge_list.size() >= entries_to_purge) - break; - } + purge_list.insert(iter->second); + if (purge_list.size() >= entries_to_purge) + break; } } llassert_always(purge_list.size() >= entries_to_purge); @@ -1332,9 +1399,7 @@ void LLTextureCache::readHeaderCache() S32 lru_entries = (S32)((F32)sCacheMaxEntries * TEXTURE_CACHE_LRU_SIZE); for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) { - S32 idx = iter->second; - const LLUUID& id = entries[idx].mID; - mLRU.insert(id); + mLRU.insert(entries[iter->second].mID); // llinfos << "LRU: " << iter->first << " : " << iter->second << llendl; if (--lru_entries <= 0) break; @@ -1343,12 +1408,10 @@ void LLTextureCache::readHeaderCache() if (purge_list.size() > 0) { - for (std::set<LLUUID>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) + for (std::set<U32>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) { - const LLUUID& id = *iter; - bool res = removeHeaderCacheEntry(id); // sets entry size on disk to -1 - llassert_always(res); - LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); + std::string tex_filename = getTextureFileName(entries[*iter].mID); + removeEntry((S32)*iter, entries[*iter], tex_filename); } // If we removed any entries, we need to rebuild the entries list, // write the header, and call this again @@ -1356,13 +1419,14 @@ void LLTextureCache::readHeaderCache() for (U32 i=0; i<num_entries; i++) { const Entry& entry = entries[i]; - if (entry.mImageSize >=0) + if (entry.mImageSize > 0) { new_entries.push_back(entry); } } llassert_always(new_entries.size() <= sCacheMaxEntries); mHeaderEntriesInfo.mEntries = new_entries.size(); + writeEntriesHeader(); writeEntriesAndClose(new_entries); mHeaderMutex.unlock(); // unlock the mutex before calling again readHeaderCache(); // repeat with new entries file @@ -1370,7 +1434,7 @@ void LLTextureCache::readHeaderCache() } else { - writeEntriesAndClose(entries); + //entries are not changed, nothing here. } } } @@ -1398,8 +1462,9 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) } if (purge_directories) { + gDirUtilp->deleteFilesInDir(mTexturesDirName, mask); LLFile::rmdir(mTexturesDirName); - } + } } mHeaderIDMap.clear(); mTexturesSizeMap.clear(); @@ -1435,7 +1500,6 @@ void LLTextureCache::purgeTextures(bool validate) U32 num_entries = openAndReadEntries(entries); if (!num_entries) { - writeEntriesAndClose(entries); return; // nothing to purge } @@ -1509,11 +1573,8 @@ void LLTextureCache::purgeTextures(bool validate) { purge_count++; LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; - LLAPRFile::remove(filename, getLocalAPRFilePool()); + removeEntry(idx, entries[idx], filename) ; cache_size -= entries[idx].mBodySize; - mTexturesSizeTotal -= entries[idx].mBodySize; - entries[idx].mBodySize = 0; - mTexturesSizeMap.erase(entries[idx].mID); } } @@ -1560,40 +1621,37 @@ LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle) // Called from work thread // Reads imagesize from the header, updates timestamp -S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, S32& imagesize) +S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, Entry& entry) { - LLMutexLock lock(&mHeaderMutex); - Entry entry; + LLMutexLock lock(&mHeaderMutex); S32 idx = openAndReadEntry(id, entry, false); if (idx >= 0) - { - imagesize = entry.mImageSize; - writeEntryAndClose(idx, entry); // updates time + { + updateEntryTimeStamp(idx, entry); // updates time } return idx; } // Writes imagesize to the header, updates timestamp -S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, S32 imagesize) +S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imagesize, S32 datasize) { mHeaderMutex.lock(); - llassert_always(imagesize >= 0); - Entry entry; S32 idx = openAndReadEntry(id, entry, true); + mHeaderMutex.unlock(); + if (idx >= 0) { - entry.mImageSize = imagesize; - writeEntryAndClose(idx, entry); - mHeaderMutex.unlock(); + updateEntry(idx, entry, imagesize, datasize); } else // retry { - mHeaderMutex.unlock(); readHeaderCache(); // We couldn't write an entry, so refresh the LRU + mHeaderMutex.lock(); llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries); mHeaderMutex.unlock(); - idx = setHeaderCacheEntry(id, imagesize); // assert above ensures no inf. recursion + + idx = setHeaderCacheEntry(id, entry, imagesize, datasize); // assert above ensures no inf. recursion } return idx; } @@ -1722,34 +1780,56 @@ void LLTextureCache::addCompleted(Responder* responder, bool success) ////////////////////////////////////////////////////////////////////////////// -// Called from MAIN thread (endWork()) -// Ensure that mHeaderMutex is locked first! -bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) +//called after mHeaderMutex is locked. +void LLTextureCache::removeCachedTexture(const LLUUID& id) { - Entry entry; - S32 idx = openAndReadEntry(id, entry, false); - if (idx >= 0) + if(mTexturesSizeMap.find(id) != mTexturesSizeMap.end()) + { + mTexturesSizeTotal -= mTexturesSizeMap[id] ; + mTexturesSizeMap.erase(id); + } + mHeaderIDMap.erase(id); + LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); +} + +//called after mHeaderMutex is locked. +void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename) +{ + if(idx >= 0) //valid entry { entry.mImageSize = -1; entry.mBodySize = 0; - writeEntryAndClose(idx, entry); - mFreeList.insert(idx); - mHeaderIDMap.erase(id); - mTexturesSizeMap.erase(id); - return true; + mHeaderIDMap.erase(entry.mID); + mTexturesSizeMap.erase(entry.mID); + + mTexturesSizeTotal -= entry.mBodySize; + mFreeList.insert(idx); } - return false; + + LLAPRFile::remove(filename, getLocalAPRFilePool()); } -void LLTextureCache::removeFromCache(const LLUUID& id) +bool LLTextureCache::removeFromCache(const LLUUID& id) { //llwarns << "Removing texture from cache: " << id << llendl; + bool ret = false ; if (!mReadOnly) { - LLMutexLock lock(&mHeaderMutex); - removeHeaderCacheEntry(id); - LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); + lockHeaders() ; + + Entry entry; + S32 idx = openAndReadEntry(id, entry, false); + std::string tex_filename = getTextureFileName(id); + removeEntry(idx, entry, tex_filename) ; + if (idx >= 0) + { + writeEntryToHeaderImmediately(idx, entry); + ret = true; + } + + unlockHeaders() ; } + return ret ; } ////////////////////////////////////////////////////////////////////////////// |