/** * @file llvocache.cpp * @brief Cache of objects on the viewer. * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llvocache.h" #include "llerror.h" //--------------------------------------------------------------------------- // LLVOCacheEntry //--------------------------------------------------------------------------- LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp) { mLocalID = local_id; mCRC = crc; mHitCount = 0; mDupeCount = 0; mCRCChangeCount = 0; mBuffer = new U8[dp.getBufferSize()]; mDP.assignBuffer(mBuffer, dp.getBufferSize()); mDP = dp; } LLVOCacheEntry::LLVOCacheEntry() { mLocalID = 0; mCRC = 0; mHitCount = 0; mDupeCount = 0; mCRCChangeCount = 0; mBuffer = NULL; mDP.assignBuffer(mBuffer, 0); } static inline void checkedRead(LLFILE *fp, void *data, size_t nbytes) { if (fread(data, 1, nbytes, fp) != nbytes) { llwarns << "Short read" << llendl; memset(data, 0, nbytes); } } LLVOCacheEntry::LLVOCacheEntry(LLFILE *fp) { S32 size; checkedRead(fp, &mLocalID, sizeof(U32)); checkedRead(fp, &mCRC, sizeof(U32)); checkedRead(fp, &mHitCount, sizeof(S32)); checkedRead(fp, &mDupeCount, sizeof(S32)); checkedRead(fp, &mCRCChangeCount, sizeof(S32)); checkedRead(fp, &size, sizeof(S32)); // Corruption in the cache entries if ((size > 10000) || (size < 1)) { // We've got a bogus size, skip reading it. // We won't bother seeking, because the rest of this file // is likely bogus, and will be tossed anyway. llwarns << "Bogus cache entry, size " << size << ", aborting!" << llendl; mLocalID = 0; mCRC = 0; mBuffer = NULL; return; } mBuffer = new U8[size]; checkedRead(fp, mBuffer, size); mDP.assignBuffer(mBuffer, size); } LLVOCacheEntry::~LLVOCacheEntry() { delete [] mBuffer; } // New CRC means the object has changed. void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp) { if ( (mCRC != crc) ||(mDP.getBufferSize() == 0)) { mCRC = crc; mHitCount = 0; mCRCChangeCount++; mDP.freeBuffer(); mBuffer = new U8[dp.getBufferSize()]; mDP.assignBuffer(mBuffer, dp.getBufferSize()); mDP = dp; } } LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc) { if ( (mCRC != crc) ||(mDP.getBufferSize() == 0)) { //llinfos << "Not getting cache entry, invalid!" << llendl; return NULL; } mHitCount++; return &mDP; } void LLVOCacheEntry::recordHit() { mHitCount++; } void LLVOCacheEntry::dump() const { llinfos << "local " << mLocalID << " crc " << mCRC << " hits " << mHitCount << " dupes " << mDupeCount << " change " << mCRCChangeCount << llendl; } static inline void checkedWrite(LLFILE *fp, const void *data, size_t nbytes) { if (fwrite(data, 1, nbytes, fp) != nbytes) { llwarns << "Short write" << llendl; } } void LLVOCacheEntry::writeToFile(LLFILE *fp) const { checkedWrite(fp, &mLocalID, sizeof(U32)); checkedWrite(fp, &mCRC, sizeof(U32)); checkedWrite(fp, &mHitCount, sizeof(S32)); checkedWrite(fp, &mDupeCount, sizeof(S32)); checkedWrite(fp, &mCRCChangeCount, sizeof(S32)); S32 size = mDP.getBufferSize(); checkedWrite(fp, &size, sizeof(S32)); checkedWrite(fp, mBuffer, size); }