From 3e1f2083abe31d54b4b57ac7e8479b79461f6062 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 14 Dec 2010 23:56:35 -0800 Subject: First pass at fix for ER-401: Fix object cache header on the viewer --- indra/newview/llvocache.cpp | 162 +++++++++++++++++++++++++++----------------- 1 file changed, 101 insertions(+), 61 deletions(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 145ee31260..6ea88abab8 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -40,6 +40,7 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) return apr_file->write(src, n_bytes) == n_bytes ; } + //--------------------------------------------------------------------------- // LLVOCacheEntry //--------------------------------------------------------------------------- @@ -212,8 +213,8 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const if(success) { success = check_write(apr_file, (void*)mBuffer, size); + } } -} return success ; } @@ -224,7 +225,7 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const // Format string used to construct filename for the object cache static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; -const U32 NUM_ENTRIES_TO_PURGE = 16 ; +const U32 NUM_ENTRIES_TO_PURGE = 50; const char* object_cache_dirname = "objectcache"; const char* header_filename = "object.cache"; @@ -259,7 +260,6 @@ void LLVOCache::destroyClass() LLVOCache::LLVOCache(): mInitialized(FALSE), mReadOnly(TRUE), - mNumEntries(0), mCacheSize(1) { mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); @@ -286,8 +286,15 @@ void LLVOCache::setDirNames(ELLPath location) void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) { - if(mInitialized || !mEnabled) + if(!mEnabled) + { + llwarns << "Not initializing cache: Cache is currently disabled." << llendl; + return ; + } + + if(mInitialized) { + llwarns << "Cache already initialized." << llendl; return ; } @@ -321,6 +328,7 @@ void LLVOCache::removeCache(ELLPath location) { if(mReadOnly) { + llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl; return ; } @@ -339,6 +347,7 @@ void LLVOCache::removeCache() llassert_always(mInitialized) ; if(mReadOnly) { + llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl; return ; } @@ -352,16 +361,8 @@ void LLVOCache::removeCache() void LLVOCache::clearCacheInMemory() { - if(!mHeaderEntryQueue.empty()) - { - for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin(); iter != mHeaderEntryQueue.end(); ++iter) - { - delete *iter ; - } - mHeaderEntryQueue.clear(); - mHandleEntryMap.clear(); - mNumEntries = 0 ; - } + std::for_each(mHandleEntryMap.begin(), mHandleEntryMap.end(), DeletePairedPointer()); + mHandleEntryMap.clear(); } void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename) @@ -379,6 +380,7 @@ void LLVOCache::removeFromCache(U64 handle) { if(mReadOnly) { + llwarns << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << llendl; return ; } @@ -391,7 +393,6 @@ BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes) { if(!check_read(apr_file, src, n_bytes)) { - delete apr_file ; removeCache() ; return FALSE ; } @@ -403,7 +404,6 @@ BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) { if(!check_write(apr_file, src, n_bytes)) { - delete apr_file ; removeCache() ; return FALSE ; } @@ -415,7 +415,8 @@ void LLVOCache::readCacheHeader() { if(!mEnabled) { - return ; + llwarns << "Not reading cache header: Cache is currently disabled." << llendl; + return; } //clear stale info. @@ -428,28 +429,29 @@ void LLVOCache::readCacheHeader() //read the meta element if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) { - return ; + llwarns << "Error reading meta information from cache header." << llendl; + delete apr_file; + return; } HeaderEntryInfo* entry ; - mNumEntries = 0 ; - while(mNumEntries < mCacheSize) + for(U32 entry_index = 0; entry_index < mCacheSize; ++entry_index) { entry = new HeaderEntryInfo() ; if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo))) { + llwarns << "Error reading cache header entry. (entry_index=" << entry_index << ")" << llendl; delete entry ; - return ; + break; } else if(!entry->mTime) //end of the cache. { delete entry ; - return ; + break; } - entry->mIndex = mNumEntries++ ; - mHeaderEntryQueue.insert(entry) ; - mHandleEntryMap[entry->mHandle] = entry ; + entry->mIndex = entry_index; + mHandleEntryMap[entry->mHandle] = entry; } delete apr_file ; @@ -462,40 +464,57 @@ void LLVOCache::readCacheHeader() void LLVOCache::writeCacheHeader() { - if(mReadOnly || !mEnabled) + if (!mEnabled) { - return ; - } + llwarns << "Not writing cache header: Cache is currently disabled." << llendl; + return; + } + + if(mReadOnly) + { + llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl; + return; + } LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); //write the meta element if(!checkWrite(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) { - return ; + llwarns << "Error writing meta information to cache header." << llendl; + delete apr_file; + return; } - mNumEntries = 0 ; - for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; iter != mHeaderEntryQueue.end(); ++iter) + U32 entry_index = 0; + handle_entry_map_t::iterator iter_end = mHandleEntryMap.end(); + for(handle_entry_map_t::iterator iter = mHandleEntryMap.begin(); + iter != iter_end; + ++iter) { - (*iter)->mIndex = mNumEntries++ ; - if(!checkWrite(apr_file, (void*)*iter, sizeof(HeaderEntryInfo))) + HeaderEntryInfo* entry = iter->second; + entry->mIndex = entry_index++; + if(!checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo))) { - return ; + llwarns << "Failed to write cache header for entry " << entry->mHandle << " (entry_index = " << entry_index << ")" << llendl; + delete apr_file; + return; } } - mNumEntries = mHeaderEntryQueue.size() ; - if(mNumEntries < mCacheSize) + // Why do we need to fill the cache header with default entries? DK 2010-12-14 + // It looks like we currently rely on the file being pre-allocated so we can seek during updateEntry(). + if(entry_index < mCacheSize) { HeaderEntryInfo* entry = new HeaderEntryInfo() ; - for(U32 i = mNumEntries ; i < mCacheSize; i++) + for(; entry_index < mCacheSize; ++entry_index) { //fill the cache with the default entry. if(!checkWrite(apr_file, entry, sizeof(HeaderEntryInfo))) { + llwarns << "Failed to fill cache header with default entries (entry_index = " << entry_index << "). Switching to read-only mode." << llendl; mReadOnly = TRUE ; //disable the cache. - return ; + break; } } delete entry ; @@ -508,13 +527,16 @@ BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); apr_file->seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; - return checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; + BOOL result = checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; + delete apr_file; + return result; } void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) { if(!mEnabled) { + llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl; return ; } llassert_always(mInitialized); @@ -522,6 +544,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; if(iter == mHandleEntryMap.end()) //no cache { + llwarns << "No handle map entry for " << handle << llendl; return ; } @@ -532,12 +555,13 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca LLUUID cache_id ; if(!checkRead(apr_file, cache_id.mData, UUID_BYTES)) { + llwarns << "Error reading cache_id from " << filename << llendl; + delete apr_file; return ; } if(cache_id != id) { - llinfos << "Cache ID doesn't match for this region, discarding"<< llendl; - + llwarns << "Cache ID (" << cache_id << ") doesn't match id for this region (" << id << "), discarding. handle = " << handle << llendl; delete apr_file ; return ; } @@ -545,6 +569,8 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca S32 num_entries; if(!checkRead(apr_file, &num_entries, sizeof(S32))) { + llwarns << "Error reading num_entries from " << filename << llendl; + delete apr_file; return ; } @@ -553,13 +579,12 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca LLVOCacheEntry* entry = new LLVOCacheEntry(apr_file); if (!entry->getLocalID()) { - llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; + llwarns << "Aborting cache file load for " << filename << ", cache file corruption! (entry number = " << i << ")" << llendl; delete entry ; break; } cache_entry_map[entry->getLocalID()] = entry; } - num_entries = cache_entry_map.size() ; delete apr_file ; return ; @@ -568,40 +593,53 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca void LLVOCache::purgeEntries() { U32 limit = mCacheSize - NUM_ENTRIES_TO_PURGE ; - while(mHeaderEntryQueue.size() > limit) + // Construct a vector of entries out of the map so we can sort by time. + std::vector header_vector; + handle_entry_map_t::iterator iter_end = mHandleEntryMap.end(); + for (handle_entry_map_t::iterator iter = mHandleEntryMap.begin(); + iter != iter_end; + ++iter) + { + header_vector.push_back(iter->second); + } + // Sort by time, oldest first. + std::sort(header_vector.begin(), header_vector.end(), header_entry_less()); + while(header_vector.size() > limit) { - header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; - HeaderEntryInfo* entry = *iter ; + HeaderEntryInfo* entry = header_vector.front(); - removeFromCache(entry->mHandle) ; - mHandleEntryMap.erase(entry->mHandle) ; - mHeaderEntryQueue.erase(iter) ; - delete entry ; + removeFromCache(entry->mHandle); + mHandleEntryMap.erase(entry->mHandle); + header_vector.erase(header_vector.begin()); + delete entry; } writeCacheHeader() ; + // *TODO: Verify that we can avoid re-reading the cache header. DK 2010-12-14 readCacheHeader() ; - mNumEntries = mHandleEntryMap.size() ; } void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) { if(!mEnabled) { + llwarns << "Not writing cache for handle " << handle << "): Cache is currently disabled." << llendl; return ; } llassert_always(mInitialized); if(mReadOnly) { + llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl; return ; } HeaderEntryInfo* entry; handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; + U32 num_handle_entries = mHandleEntryMap.size(); if(iter == mHandleEntryMap.end()) //new entry - { - if(mNumEntries >= mCacheSize) + { + if(num_handle_entries >= mCacheSize) { purgeEntries() ; } @@ -609,28 +647,26 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: entry = new HeaderEntryInfo(); entry->mHandle = handle ; entry->mTime = time(NULL) ; - entry->mIndex = mNumEntries++ ; - mHeaderEntryQueue.insert(entry) ; + entry->mIndex = num_handle_entries++; mHandleEntryMap[handle] = entry ; } else { + // Update access time. entry = iter->second ; entry->mTime = time(NULL) ; - - //resort - mHeaderEntryQueue.erase(entry) ; - mHeaderEntryQueue.insert(entry) ; } //update cache header if(!updateEntry(entry)) { + llwarns << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << llendl; return ; //update failed. } if(!dirty_cache) { + llwarns << "Skipping write to cache for handle " << handle << ": cache not dirty" << llendl; return ; //nothing changed, no need to update. } @@ -641,12 +677,16 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: if(!checkWrite(apr_file, (void*)id.mData, UUID_BYTES)) { + llwarns << "Error writing id to " << filename << llendl; + delete apr_file; return ; } S32 num_entries = cache_entry_map.size() ; if(!checkWrite(apr_file, &num_entries, sizeof(S32))) { + llwarns << "Error writing num_entries to " << filename << llendl; + delete apr_file; return ; } @@ -654,10 +694,10 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: { if(!iter->second->writeToFile(apr_file)) { + llwarns << "Aborting cache file write for " << filename << ", error writing to file!" << llendl; //failed - delete apr_file ; removeCache() ; - return ; + break; } } -- cgit v1.2.3 From 2192316803564b41a28d56481985597eb5d94fad Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Wed, 15 Dec 2010 15:56:15 -0800 Subject: Modified cache purge entry threshold (part of ER-401) --- indra/newview/llvocache.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 6ea88abab8..10744991f4 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -225,7 +225,8 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const // Format string used to construct filename for the object cache static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; -const U32 NUM_ENTRIES_TO_PURGE = 50; +// Throw out 1/20 (5%) of our cache entries if we run out of room. +const U32 ENTRIES_PURGE_FACTOR = 20; const char* object_cache_dirname = "objectcache"; const char* header_filename = "object.cache"; @@ -592,7 +593,8 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca void LLVOCache::purgeEntries() { - U32 limit = mCacheSize - NUM_ENTRIES_TO_PURGE ; + U32 limit = mCacheSize / ENTRIES_PURGE_FACTOR; + limit = llclamp(limit, 1, mCacheSize); // Construct a vector of entries out of the map so we can sort by time. std::vector header_vector; handle_entry_map_t::iterator iter_end = mHandleEntryMap.end(); -- cgit v1.2.3 From 57065fe5a9521158b79b7a313d6476b8dcaa13a5 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 15 Dec 2010 17:20:58 -0700 Subject: fix for SH-367: mesh viewer lock up: Problem removing object.cache - errorcode: 13 --- indra/newview/llvocache.cpp | 274 ++++++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 125 deletions(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 1cb3962daa..bbe637d161 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -325,6 +325,8 @@ void LLVOCache::removeCache(ELLPath location) return ; } + llinfos << "about to remove the object cache due to settings." << llendl ; + std::string delem = gDirUtilp->getDirDelimiter(); std::string mask = delem + "*"; std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname); @@ -343,6 +345,8 @@ void LLVOCache::removeCache() return ; } + llinfos << "about to remove the object cache due to some error." << llendl ; + std::string delem = gDirUtilp->getDirDelimiter(); std::string mask = delem + "*"; gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); @@ -351,6 +355,43 @@ void LLVOCache::removeCache() writeCacheHeader(); } +void LLVOCache::removeEntry(HeaderEntryInfo* entry) +{ + llassert_always(mInitialized) ; + if(mReadOnly) + { + return ; + } + if(!entry) + { + return ; + } + + header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry) ; + if(iter != mHeaderEntryQueue.end()) + { + removeFromCache(entry->mHandle) ; + mHandleEntryMap.erase(entry->mHandle) ; + mHeaderEntryQueue.erase(iter) ; + delete entry ; + + writeCacheHeader() ; + readCacheHeader() ; + mNumEntries = mHandleEntryMap.size() ; + } +} + +void LLVOCache::removeEntry(U64 handle) +{ + handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; + if(iter == mHandleEntryMap.end()) //no cache + { + return ; + } + HeaderEntryInfo* entry = iter->second ; + removeEntry(entry) ; +} + void LLVOCache::clearCacheInMemory() { if(!mHeaderEntryQueue.empty()) @@ -388,30 +429,6 @@ void LLVOCache::removeFromCache(U64 handle) LLAPRFile::remove(filename, mLocalAPRFilePoolp); } -BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes) -{ - if(!check_read(apr_file, src, n_bytes)) - { - delete apr_file ; - removeCache() ; - return FALSE ; - } - - return TRUE ; -} - -BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) -{ - if(!check_write(apr_file, src, n_bytes)) - { - delete apr_file ; - removeCache() ; - return FALSE ; - } - - return TRUE ; -} - void LLVOCache::readCacheHeader() { if(!mEnabled) @@ -422,43 +439,45 @@ void LLVOCache::readCacheHeader() //clear stale info. clearCacheInMemory(); + bool success = true ; if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) { - LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp); + LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp); //read the meta element - if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) - { - return ; - } - - HeaderEntryInfo* entry ; - mNumEntries = 0 ; - while(mNumEntries < MAX_NUM_OBJECT_ENTRIES) + success = check_read(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; + + if(success) { - entry = new HeaderEntryInfo() ; - if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo))) - { - delete entry ; - return ; - } - else if(!entry->mTime) //end of the cache. + HeaderEntryInfo* entry ; + mNumEntries = 0 ; + while(mNumEntries < MAX_NUM_OBJECT_ENTRIES) { - delete entry ; - return ; + entry = new HeaderEntryInfo() ; + success = check_read(&apr_file, entry, sizeof(HeaderEntryInfo)); + + if(!success || !entry->mTime) //failed or end of the cache + { + delete entry ; + break ; + } + + entry->mIndex = mNumEntries++ ; + mHeaderEntryQueue.insert(entry) ; + mHandleEntryMap[entry->mHandle] = entry ; } - - entry->mIndex = mNumEntries++ ; - mHeaderEntryQueue.insert(entry) ; - mHandleEntryMap[entry->mHandle] = entry ; } - - delete apr_file ; } else { writeCacheHeader() ; } + + if(!success) + { + removeCache() ; //failed to read header, clear the cache + } + return ; } void LLVOCache::writeCacheHeader() @@ -468,48 +487,47 @@ void LLVOCache::writeCacheHeader() return ; } - LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - - //write the meta element - if(!checkWrite(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) + bool success = true ; { - return ; - } + LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - mNumEntries = 0 ; - for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; iter != mHeaderEntryQueue.end(); ++iter) - { - (*iter)->mIndex = mNumEntries++ ; - if(!checkWrite(apr_file, (void*)*iter, sizeof(HeaderEntryInfo))) + //write the meta element + success = check_write(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; + + mNumEntries = 0 ; + for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) { - return ; + (*iter)->mIndex = mNumEntries++ ; + success = check_write(&apr_file, (void*)*iter, sizeof(HeaderEntryInfo)); } - } - - mNumEntries = mHeaderEntryQueue.size() ; - if(mNumEntries < MAX_NUM_OBJECT_ENTRIES) - { - HeaderEntryInfo* entry = new HeaderEntryInfo() ; - for(S32 i = mNumEntries ; i < MAX_NUM_OBJECT_ENTRIES ; i++) + + mNumEntries = mHeaderEntryQueue.size() ; + if(success && mNumEntries < MAX_NUM_OBJECT_ENTRIES) { - //fill the cache with the default entry. - if(!checkWrite(apr_file, entry, sizeof(HeaderEntryInfo))) + HeaderEntryInfo* entry = new HeaderEntryInfo() ; + for(S32 i = mNumEntries ; success && i < MAX_NUM_OBJECT_ENTRIES ; i++) { - mReadOnly = TRUE ; //disable the cache. - return ; + //fill the cache with the default entry. + success = check_write(&apr_file, entry, sizeof(HeaderEntryInfo)) ; } + delete entry ; } - delete entry ; } - delete apr_file ; + + if(!success) + { + clearCacheInMemory() ; + mReadOnly = TRUE ; //disable the cache. + } + return ; } BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) { - LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - apr_file->seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; + LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + apr_file.seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; - return checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; + return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; } void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) @@ -526,43 +544,51 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca return ; } - std::string filename; - getObjectCacheFilename(handle, filename); - LLAPRFile* apr_file = new LLAPRFile(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); - - LLUUID cache_id ; - if(!checkRead(apr_file, cache_id.mData, UUID_BYTES)) - { - return ; - } - if(cache_id != id) + bool success = true ; { - llinfos << "Cache ID doesn't match for this region, discarding"<< llendl; - - delete apr_file ; - return ; - } + std::string filename; + getObjectCacheFilename(handle, filename); + LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); + + LLUUID cache_id ; + success = check_read(&apr_file, cache_id.mData, UUID_BYTES) ; + + if(success) + { + if(cache_id != id) + { + llinfos << "Cache ID doesn't match for this region, discarding"<< llendl; + success = false ; + } - S32 num_entries; - if(!checkRead(apr_file, &num_entries, sizeof(S32))) - { - return ; + if(success) + { + S32 num_entries; + success = check_read(&apr_file, &num_entries, sizeof(S32)) ; + + for (S32 i = 0; success && i < num_entries; i++) + { + LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file); + if (!entry->getLocalID()) + { + llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; + delete entry ; + success = false ; + } + cache_entry_map[entry->getLocalID()] = entry; + } + } + } } - for (S32 i = 0; i < num_entries; i++) + if(!success) { - LLVOCacheEntry* entry = new LLVOCacheEntry(apr_file); - if (!entry->getLocalID()) + if(cache_entry_map.empty()) { - llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; - delete entry ; - break; + removeEntry(iter->second) ; } - cache_entry_map[entry->getLocalID()] = entry; } - num_entries = cache_entry_map.size() ; - delete apr_file ; return ; } @@ -636,33 +662,31 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: } //write to cache file - std::string filename; - getObjectCacheFilename(handle, filename); - LLAPRFile* apr_file = new LLAPRFile(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - - if(!checkWrite(apr_file, (void*)id.mData, UUID_BYTES)) - { - return ; - } - - S32 num_entries = cache_entry_map.size() ; - if(!checkWrite(apr_file, &num_entries, sizeof(S32))) + bool success = true ; { - return ; + std::string filename; + getObjectCacheFilename(handle, filename); + LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + + success = check_write(&apr_file, (void*)id.mData, UUID_BYTES) ; + + if(success) + { + S32 num_entries = cache_entry_map.size() ; + success = check_write(&apr_file, &num_entries, sizeof(S32)); + + for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter) + { + success = iter->second->writeToFile(&apr_file) ; + } + } } - for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); iter != cache_entry_map.end(); ++iter) + if(!success) { - if(!iter->second->writeToFile(apr_file)) - { - //failed - delete apr_file ; - removeCache() ; - return ; - } + removeEntry(entry) ; } - delete apr_file ; return ; } -- cgit v1.2.3 From ac71884a446170a32ec557d5e9f85d0a73e8fa23 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 15 Dec 2010 17:34:18 -0700 Subject: fix for SH-446: viewer crashed after clearing cache and relogging --- indra/newview/llvocache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index bbe637d161..cb48d1db73 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -291,6 +291,7 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) { return ; } + mInitialized = TRUE ; setDirNames(location); if (!mReadOnly) @@ -301,8 +302,7 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) MAX_NUM_OBJECT_ENTRIES, NUM_ENTRIES_TO_PURGE); mMetaInfo.mVersion = cache_version; - readCacheHeader(); - mInitialized = TRUE ; + readCacheHeader(); if(mMetaInfo.mVersion != cache_version) { -- cgit v1.2.3 From b87397938345b7dce30c3f10a4e54d9e0434b217 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 16 Dec 2010 02:06:39 -0800 Subject: Fix for compile issue --- indra/newview/llvocache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 10744991f4..040139f3ab 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -594,7 +594,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca void LLVOCache::purgeEntries() { U32 limit = mCacheSize / ENTRIES_PURGE_FACTOR; - limit = llclamp(limit, 1, mCacheSize); + limit = llclamp(limit, (U32)1, mCacheSize); // Construct a vector of entries out of the map so we can sort by time. std::vector header_vector; handle_entry_map_t::iterator iter_end = mHandleEntryMap.end(); -- cgit v1.2.3 From f137dc0c2f928b81a90e59c58adefeb56f21393e Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 16 Dec 2010 17:13:07 -0700 Subject: fix for SH-445: debug settings -> "CacheNumberOfRegionsForObjects" does not limit the number of object cache files --- indra/newview/llvocache.cpp | 86 +++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 31 deletions(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index cb48d1db73..b53f5c7a20 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -225,7 +225,8 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; const U32 MAX_NUM_OBJECT_ENTRIES = 128 ; -const U32 NUM_ENTRIES_TO_PURGE = 16 ; +const U32 MIN_ENTRIES_TO_PURGE = 16 ; +const U32 INVALID_TIME = 0 ; const char* object_cache_dirname = "objectcache"; const char* header_filename = "object.cache"; @@ -298,8 +299,7 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) { LLFile::mkdir(mObjectCacheDirName); } - mCacheSize = llclamp(size, - MAX_NUM_OBJECT_ENTRIES, NUM_ENTRIES_TO_PURGE); + mCacheSize = llclamp(size, MIN_ENTRIES_TO_PURGE, MAX_NUM_OBJECT_ENTRIES); mMetaInfo.mVersion = cache_version; readCacheHeader(); @@ -369,14 +369,12 @@ void LLVOCache::removeEntry(HeaderEntryInfo* entry) header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry) ; if(iter != mHeaderEntryQueue.end()) - { - removeFromCache(entry->mHandle) ; + { mHandleEntryMap.erase(entry->mHandle) ; mHeaderEntryQueue.erase(iter) ; + removeFromCache(entry) ; delete entry ; - writeCacheHeader() ; - readCacheHeader() ; mNumEntries = mHandleEntryMap.size() ; } } @@ -417,7 +415,7 @@ void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename) return ; } -void LLVOCache::removeFromCache(U64 handle) +void LLVOCache::removeFromCache(HeaderEntryInfo* entry) { if(mReadOnly) { @@ -425,8 +423,11 @@ void LLVOCache::removeFromCache(U64 handle) } std::string filename; - getObjectCacheFilename(handle, filename); - LLAPRFile::remove(filename, mLocalAPRFilePoolp); + getObjectCacheFilename(entry->mHandle, filename); + LLAPRFile::remove(filename, mLocalAPRFilePoolp); + + entry->mTime = INVALID_TIME ; + updateEntry(entry) ; //update the head file. } void LLVOCache::readCacheHeader() @@ -449,24 +450,49 @@ void LLVOCache::readCacheHeader() if(success) { - HeaderEntryInfo* entry ; + HeaderEntryInfo* entry = NULL ; mNumEntries = 0 ; - while(mNumEntries < MAX_NUM_OBJECT_ENTRIES) + U32 num_read = 0 ; + while(num_read++ < MAX_NUM_OBJECT_ENTRIES) { - entry = new HeaderEntryInfo() ; + if(!entry) + { + entry = new HeaderEntryInfo() ; + } success = check_read(&apr_file, entry, sizeof(HeaderEntryInfo)); - - if(!success || !entry->mTime) //failed or end of the cache + + if(!success) //failed { - delete entry ; + delete entry ; + entry = NULL ; break ; - } + } + else if(entry->mTime == INVALID_TIME) + { + continue ; //an empty entry + } entry->mIndex = mNumEntries++ ; mHeaderEntryQueue.insert(entry) ; mHandleEntryMap[entry->mHandle] = entry ; + entry = NULL ; + } + if(entry) + { + delete entry ; } } + + //--------- + //debug code + //---------- + //std::string name ; + //for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) + //{ + // getObjectCacheFilename((*iter)->mHandle, name) ; + // llinfos << name << llendl ; + //} + //----------- } else { @@ -505,6 +531,7 @@ void LLVOCache::writeCacheHeader() if(success && mNumEntries < MAX_NUM_OBJECT_ENTRIES) { HeaderEntryInfo* entry = new HeaderEntryInfo() ; + entry->mTime = INVALID_TIME ; for(S32 i = mNumEntries ; success && i < MAX_NUM_OBJECT_ENTRIES ; i++) { //fill the cache with the default entry. @@ -594,20 +621,17 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca void LLVOCache::purgeEntries() { - U32 limit = mCacheSize - NUM_ENTRIES_TO_PURGE ; - while(mHeaderEntryQueue.size() > limit) + while(mHeaderEntryQueue.size() >= mCacheSize) { header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; HeaderEntryInfo* entry = *iter ; - - removeFromCache(entry->mHandle) ; + mHandleEntryMap.erase(entry->mHandle) ; mHeaderEntryQueue.erase(iter) ; + removeFromCache(entry) ; delete entry ; } - writeCacheHeader() ; - readCacheHeader() ; mNumEntries = mHandleEntryMap.size() ; } @@ -623,16 +647,15 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: { return ; } + if(mNumEntries >= mCacheSize) + { + purgeEntries() ; + } HeaderEntryInfo* entry; handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; if(iter == mHandleEntryMap.end()) //new entry - { - if(mNumEntries >= mCacheSize) - { - purgeEntries() ; - } - + { entry = new HeaderEntryInfo(); entry->mHandle = handle ; entry->mTime = time(NULL) ; @@ -642,11 +665,12 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: } else { - entry = iter->second ; - entry->mTime = time(NULL) ; + entry = iter->second ; //resort mHeaderEntryQueue.erase(entry) ; + + entry->mTime = time(NULL) ; mHeaderEntryQueue.insert(entry) ; } -- cgit v1.2.3 From 649dd6eb74023d48379ebaadd2ff000801306f17 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Wed, 22 Dec 2010 14:23:35 -0800 Subject: Cleanup from review with Andrew and Merov --- indra/newview/llvocache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 040139f3ab..d372fd0212 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -593,7 +593,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca void LLVOCache::purgeEntries() { - U32 limit = mCacheSize / ENTRIES_PURGE_FACTOR; + U32 limit = mCacheSize - (mCacheSize / ENTRIES_PURGE_FACTOR); limit = llclamp(limit, (U32)1, mCacheSize); // Construct a vector of entries out of the map so we can sort by time. std::vector header_vector; -- cgit v1.2.3 From a9bc51e6416dd637080c0307de99d5e09d06dcc4 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Fri, 7 Jan 2011 10:46:41 -0800 Subject: Fix for ER-425: Viewer object cache list gets corrupted when CacheNumberOfRegionsForObjects is exceeded --- indra/newview/llvocache.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index d372fd0212..22199be82d 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -425,7 +425,7 @@ void LLVOCache::readCacheHeader() if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) { - LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp); + LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_READ|APR_FOPEN_BINARY, mLocalAPRFilePoolp); //read the meta element if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) @@ -477,7 +477,7 @@ void LLVOCache::writeCacheHeader() return; } - LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BINARY|APR_FOPEN_TRUNCATE, mLocalAPRFilePoolp); //write the meta element if(!checkWrite(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) @@ -525,7 +525,7 @@ void LLVOCache::writeCacheHeader() BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) { - LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_WRITE|APR_FOPEN_BINARY, mLocalAPRFilePoolp); apr_file->seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; BOOL result = checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; @@ -551,7 +551,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca std::string filename; getObjectCacheFilename(handle, filename); - LLAPRFile* apr_file = new LLAPRFile(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); + LLAPRFile* apr_file = new LLAPRFile(filename, APR_FOPEN_READ|APR_FOPEN_BINARY, mLocalAPRFilePoolp); LLUUID cache_id ; if(!checkRead(apr_file, cache_id.mData, UUID_BYTES)) @@ -636,14 +636,16 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: return ; } + U32 num_handle_entries = mHandleEntryMap.size(); + HeaderEntryInfo* entry; handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; - U32 num_handle_entries = mHandleEntryMap.size(); if(iter == mHandleEntryMap.end()) //new entry { if(num_handle_entries >= mCacheSize) { purgeEntries() ; + num_handle_entries = mHandleEntryMap.size(); } entry = new HeaderEntryInfo(); @@ -675,7 +677,7 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: //write to cache file std::string filename; getObjectCacheFilename(handle, filename); - LLAPRFile* apr_file = new LLAPRFile(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + LLAPRFile* apr_file = new LLAPRFile(filename, APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BINARY|APR_FOPEN_TRUNCATE, mLocalAPRFilePoolp); if(!checkWrite(apr_file, (void*)id.mData, UUID_BYTES)) { -- cgit v1.2.3 From d8b4363c1d3f60741422419b386b79df23a6da6a Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Fri, 7 Jan 2011 14:36:59 -0800 Subject: Fix for viewer crash when making the object viewer cache larger --- indra/newview/llvocache.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 22199be82d..c26008d640 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -307,7 +307,6 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) mCacheSize = size; - mMetaInfo.mVersion = cache_version; readCacheHeader(); mInitialized = TRUE ; @@ -336,6 +335,7 @@ void LLVOCache::removeCache(ELLPath location) std::string delem = gDirUtilp->getDirDelimiter(); std::string mask = delem + "*"; std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname); + llinfos << "Removing cache at " << cache_dir << llendl; gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files LLFile::rmdir(cache_dir); @@ -354,6 +354,7 @@ void LLVOCache::removeCache() std::string delem = gDirUtilp->getDirDelimiter(); std::string mask = delem + "*"; + llinfos << "Removing cache at " << mObjectCacheDirName << llendl; gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); clearCacheInMemory() ; @@ -390,22 +391,28 @@ void LLVOCache::removeFromCache(U64 handle) LLAPRFile::remove(filename, mLocalAPRFilePoolp); } -BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes) +BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error) { if(!check_read(apr_file, src, n_bytes)) { - removeCache() ; + if (remove_cache_on_error) + { + removeCache() ; + } return FALSE ; } return TRUE ; } -BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) +BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error) { if(!check_write(apr_file, src, n_bytes)) { - removeCache() ; + if (remove_cache_on_error) + { + removeCache() ; + } return FALSE ; } @@ -428,7 +435,8 @@ void LLVOCache::readCacheHeader() LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_READ|APR_FOPEN_BINARY, mLocalAPRFilePoolp); //read the meta element - if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) + bool remove_cache_on_error = false; + if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo), remove_cache_on_error)) { llwarns << "Error reading meta information from cache header." << llendl; delete apr_file; @@ -439,7 +447,7 @@ void LLVOCache::readCacheHeader() for(U32 entry_index = 0; entry_index < mCacheSize; ++entry_index) { entry = new HeaderEntryInfo() ; - if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo))) + if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo), remove_cache_on_error)) { llwarns << "Error reading cache header entry. (entry_index=" << entry_index << ")" << llendl; delete entry ; -- cgit v1.2.3 From 2a14079563ce323452a8088cca994e4f5c0edcd4 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Mon, 24 Jan 2011 15:50:46 -0700 Subject: fix for SH-445: debug settings -> "CacheNumberOfRegionsForObjects" does not limit the number of object cache files --- indra/newview/llvocache.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'indra/newview/llvocache.cpp') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 1e2736f7d9..b3312db4a0 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -517,6 +517,11 @@ void LLVOCache::readCacheHeader() { removeCache() ; //failed to read header, clear the cache } + else if(mNumEntries >= mCacheSize) + { + purgeEntries(mCacheSize) ; + } + return ; } @@ -644,9 +649,9 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca return ; } -void LLVOCache::purgeEntries() +void LLVOCache::purgeEntries(U32 size) { - while(mHeaderEntryQueue.size() >= mCacheSize) + while(mHeaderEntryQueue.size() >= size) { header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; HeaderEntryInfo* entry = *iter ; @@ -671,16 +676,17 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: { llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl; return ; - } - if(mNumEntries >= mCacheSize) - { - purgeEntries() ; - } + } HeaderEntryInfo* entry; handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; if(iter == mHandleEntryMap.end()) //new entry { + if(mNumEntries >= mCacheSize - 1) + { + purgeEntries(mCacheSize - 1) ; + } + entry = new HeaderEntryInfo(); entry->mHandle = handle ; entry->mTime = time(NULL) ; -- cgit v1.2.3