void LLTextureCache::writeEntryAndClose(S32 idx, Entry& entry) { if (idx >= 0) { if (!mReadOnly) { entry.mTime = time(NULL); if(entry.mImageSize < entry.mBodySize) { // Just say no, due to my messing around to cache discards other than 0 we can end up here // after recalling an image from cache at a lower discard than cached. RC return; } llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); if (entry.mBodySize > 0) { mTexturesSizeMap[entry.mID] = entry.mBodySize; } // llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl; 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(); } } }
void LLTextureCache::writeEntriesAndClose(const std::vector<Entry>& entries) { S32 num_entries = entries.size(); llassert_always(num_entries == mHeaderEntriesInfo.mEntries); if (!mReadOnly) { LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); for (S32 idx=0; idx<num_entries; idx++) { S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry)); llassert_always(bytes_written == sizeof(Entry)); } mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, num_entries-1); closeHeaderEntriesFile(); } }
U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) { U32 num_entries = mHeaderEntriesInfo.mEntries; mHeaderIDMap.clear(); mTexturesSizeMap.clear(); mFreeList.clear(); mTexturesSizeTotal = 0; LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); for (U32 idx=0; idx<num_entries; idx++) { Entry entry; S32 bytes_read = aprfile->read((void*)(&entry), (S32)sizeof(Entry)); if (bytes_read < sizeof(Entry)) { llwarns << "Corrupted header entries, failed at " << idx << " / " << num_entries << llendl; closeHeaderEntriesFile(); purgeAllTextures(false); return 0; } entries.push_back(entry); // llinfos << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << llendl; if (entry.mImageSize < 0) { mFreeList.insert(idx); } 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); } } closeHeaderEntriesFile(); return num_entries; }
void LLTextureCache::writeEntryAndClose(S32 idx, Entry& entry) { 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; } // llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl; 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(); } } }
S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create) { S32 idx = -1; id_map_t::iterator iter1 = mHeaderIDMap.find(id); if (iter1 != mHeaderIDMap.end()) { idx = iter1->second; } if (idx < 0) { if (create && !mReadOnly) { if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries) { // Add an entry to the end of the list idx = mHeaderEntriesInfo.mEntries++; } else if (!mFreeList.empty()) { idx = *(mFreeList.begin()); mFreeList.erase(mFreeList.begin()); } else { // Look for a still valid entry in the LRU for (std::set<LLUUID>::iterator iter2 = mLRU.begin(); iter2 != mLRU.end();) { std::set<LLUUID>::iterator curiter2 = iter2++; LLUUID oldid = *curiter2; // Erase entry from LRU regardless mLRU.erase(curiter2); // Look up entry and use it if it is valid id_map_t::iterator iter3 = mHeaderIDMap.find(oldid); if (iter3 != mHeaderIDMap.end() && iter3->second >= 0) { idx = iter3->second; mHeaderIDMap.erase(oldid); mTexturesSizeMap.erase(oldid); break; } } // if (idx < 0) at this point, we will rebuild the LRU // and retry if called from setHeaderCacheEntry(), // otherwise this shouldn't happen and will trigger an error } 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(); // 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(); } } } else { // Remove this entry from the LRU if it exists mLRU.erase(id); // Read the 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)); llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); closeHeaderEntriesFile(); } return idx; }