Pull sync to viewer-development
commit
ce55885aa3
|
|
@ -92,6 +92,17 @@ LLFILE* LLFile::_fsopen(const std::string& filename, const char* mode, int shari
|
|||
#endif
|
||||
}
|
||||
|
||||
int LLFile::close(LLFILE * file)
|
||||
{
|
||||
int ret_value = 0;
|
||||
if (file)
|
||||
{
|
||||
ret_value = fclose(file);
|
||||
}
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
|
||||
int LLFile::remove(const std::string& filename)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ public:
|
|||
static LLFILE* fopen(const std::string& filename,const char* accessmode); /* Flawfinder: ignore */
|
||||
static LLFILE* _fsopen(const std::string& filename,const char* accessmode,int sharingFlag);
|
||||
|
||||
static int close(LLFILE * file);
|
||||
|
||||
// perms is a permissions mask like 0777 or 0700. In most cases it will
|
||||
// be overridden by the user's umask. It is ignored on Windows.
|
||||
static int mkdir(const std::string& filename, int perms = 0700);
|
||||
|
|
|
|||
|
|
@ -530,6 +530,7 @@ set(viewer_SOURCE_FILES
|
|||
llviewerregion.cpp
|
||||
llviewershadermgr.cpp
|
||||
llviewerstats.cpp
|
||||
llviewerstatsrecorder.cpp
|
||||
llviewertexteditor.cpp
|
||||
llviewertexture.cpp
|
||||
llviewertextureanim.cpp
|
||||
|
|
@ -1063,6 +1064,7 @@ set(viewer_HEADER_FILES
|
|||
llviewerregion.h
|
||||
llviewershadermgr.h
|
||||
llviewerstats.h
|
||||
llviewerstatsrecorder.h
|
||||
llviewertexteditor.h
|
||||
llviewertexture.h
|
||||
llviewertextureanim.h
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "llagentwearables.h"
|
||||
#include "llwindow.h"
|
||||
#include "llviewerstats.h"
|
||||
#include "llviewerstatsrecorder.h"
|
||||
#include "llmd5.h"
|
||||
#include "llpumpio.h"
|
||||
#include "llmimetypes.h"
|
||||
|
|
@ -667,6 +668,10 @@ bool LLAppViewer::init()
|
|||
|
||||
mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
|
||||
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::initClass();
|
||||
#endif
|
||||
|
||||
// *NOTE:Mani - LLCurl::initClass is not thread safe.
|
||||
// Called before threads are created.
|
||||
LLCurl::initClass();
|
||||
|
|
@ -990,6 +995,8 @@ bool LLAppViewer::init()
|
|||
|
||||
LLAgentLanguage::init();
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1710,6 +1717,10 @@ bool LLAppViewer::cleanup()
|
|||
}
|
||||
LLMetricPerformanceTesterBasic::cleanClass() ;
|
||||
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::cleanupClass();
|
||||
#endif
|
||||
|
||||
llinfos << "Cleaning up Media and Textures" << llendflush;
|
||||
|
||||
//Note:
|
||||
|
|
|
|||
|
|
@ -2578,6 +2578,49 @@ void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)
|
|||
gGL.end();
|
||||
}
|
||||
|
||||
void renderUpdateType(LLDrawable* drawablep)
|
||||
{
|
||||
LLViewerObject* vobj = drawablep->getVObj();
|
||||
if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType())
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
switch (vobj->getLastUpdateType())
|
||||
{
|
||||
case OUT_FULL:
|
||||
glColor4f(0,1,0,0.5f);
|
||||
break;
|
||||
case OUT_TERSE_IMPROVED:
|
||||
glColor4f(0,1,1,0.5f);
|
||||
break;
|
||||
case OUT_FULL_COMPRESSED:
|
||||
if (vobj->getLastUpdateCached())
|
||||
{
|
||||
glColor4f(1,0,0,0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4f(1,1,0,0.5f);
|
||||
}
|
||||
break;
|
||||
case OUT_FULL_CACHED:
|
||||
glColor4f(0,0,1,0.5f);
|
||||
break;
|
||||
default:
|
||||
llwarns << "Unknown update_type " << vobj->getLastUpdateType() << llendl;
|
||||
break;
|
||||
};
|
||||
S32 num_faces = drawablep->getNumFaces();
|
||||
if (num_faces)
|
||||
{
|
||||
for (S32 i = 0; i < num_faces; ++i)
|
||||
{
|
||||
pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
|
||||
{
|
||||
|
|
@ -3018,6 +3061,10 @@ public:
|
|||
{
|
||||
renderRaycast(drawable);
|
||||
}
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_UPDATE_TYPE))
|
||||
{
|
||||
renderUpdateType(drawable);
|
||||
}
|
||||
|
||||
LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get());
|
||||
|
||||
|
|
@ -3180,6 +3227,7 @@ void LLSpatialPartition::renderDebug()
|
|||
LLPipeline::RENDER_DEBUG_OCCLUSION |
|
||||
LLPipeline::RENDER_DEBUG_LIGHTS |
|
||||
LLPipeline::RENDER_DEBUG_BATCH_SIZE |
|
||||
LLPipeline::RENDER_DEBUG_UPDATE_TYPE |
|
||||
LLPipeline::RENDER_DEBUG_BBOXES |
|
||||
LLPipeline::RENDER_DEBUG_POINTS |
|
||||
LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
|
||||
|
|
|
|||
|
|
@ -906,6 +906,10 @@ U32 info_display_from_string(std::string info_display)
|
|||
{
|
||||
return LLPipeline::RENDER_DEBUG_BATCH_SIZE;
|
||||
}
|
||||
else if ("update type" == info_display)
|
||||
{
|
||||
return LLPipeline::RENDER_DEBUG_UPDATE_TYPE;
|
||||
}
|
||||
else if ("texture anim" == info_display)
|
||||
{
|
||||
return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM;
|
||||
|
|
|
|||
|
|
@ -234,7 +234,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
|
|||
mState(0),
|
||||
mMedia(NULL),
|
||||
mClickAction(0),
|
||||
mAttachmentItemID(LLUUID::null)
|
||||
mAttachmentItemID(LLUUID::null),
|
||||
mLastUpdateType(OUT_UNKNOWN),
|
||||
mLastUpdateCached(FALSE)
|
||||
{
|
||||
if (!is_global)
|
||||
{
|
||||
|
|
@ -5403,6 +5405,26 @@ void LLViewerObject::setAttachmentItemID(const LLUUID &id)
|
|||
mAttachmentItemID = id;
|
||||
}
|
||||
|
||||
EObjectUpdateType LLViewerObject::getLastUpdateType() const
|
||||
{
|
||||
return mLastUpdateType;
|
||||
}
|
||||
|
||||
void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type)
|
||||
{
|
||||
mLastUpdateType = last_update_type;
|
||||
}
|
||||
|
||||
BOOL LLViewerObject::getLastUpdateCached() const
|
||||
{
|
||||
return mLastUpdateCached;
|
||||
}
|
||||
|
||||
void LLViewerObject::setLastUpdateCached(BOOL last_update_cached)
|
||||
{
|
||||
mLastUpdateCached = last_update_cached;
|
||||
}
|
||||
|
||||
const LLUUID &LLViewerObject::extractAttachmentItemID()
|
||||
{
|
||||
LLUUID item_id = LLUUID::null;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ typedef enum e_object_update_type
|
|||
OUT_TERSE_IMPROVED,
|
||||
OUT_FULL_COMPRESSED,
|
||||
OUT_FULL_CACHED,
|
||||
OUT_UNKNOWN,
|
||||
} EObjectUpdateType;
|
||||
|
||||
|
||||
|
|
@ -693,8 +694,15 @@ public:
|
|||
const LLUUID &getAttachmentItemID() const;
|
||||
void setAttachmentItemID(const LLUUID &id);
|
||||
const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object
|
||||
EObjectUpdateType getLastUpdateType() const;
|
||||
void setLastUpdateType(EObjectUpdateType last_update_type);
|
||||
BOOL getLastUpdateCached() const;
|
||||
void setLastUpdateCached(BOOL last_update_cached);
|
||||
|
||||
private:
|
||||
LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
|
||||
EObjectUpdateType mLastUpdateType;
|
||||
BOOL mLastUpdateCached;
|
||||
};
|
||||
|
||||
///////////////////
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "llresmgr.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewerstats.h"
|
||||
#include "llviewerstatsrecorder.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "lltoolmgr.h"
|
||||
#include "lltoolpie.h"
|
||||
|
|
@ -302,8 +303,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
// have to transform to absolute coordinates.
|
||||
num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
|
||||
|
||||
// I don't think this case is ever hit. TODO* Test this.
|
||||
if (!cached && !compressed && update_type != OUT_FULL)
|
||||
{
|
||||
//llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl;
|
||||
gTerseObjectUpdates += num_objects;
|
||||
S32 size;
|
||||
if (mesgsys->getReceiveCompressedSize())
|
||||
|
|
@ -314,7 +317,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
{
|
||||
size = mesgsys->getReceiveSize();
|
||||
}
|
||||
// llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
|
||||
//llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -345,9 +348,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
U8 compressed_dpbuffer[2048];
|
||||
LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
|
||||
LLDataPacker *cached_dpp = NULL;
|
||||
|
||||
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(regionp);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < num_objects; i++)
|
||||
{
|
||||
// timer is unused?
|
||||
LLTimer update_timer;
|
||||
BOOL justCreated = FALSE;
|
||||
|
||||
|
|
@ -359,9 +367,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
|
||||
|
||||
// Lookup data packer and add this id to cache miss lists if necessary.
|
||||
cached_dpp = regionp->getDP(id, crc);
|
||||
U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
|
||||
cached_dpp = regionp->getDP(id, crc, cache_miss_type);
|
||||
if (cached_dpp)
|
||||
{
|
||||
// Cache Hit.
|
||||
cached_dpp->reset();
|
||||
cached_dpp->unpackUUID(fullid, "ID");
|
||||
cached_dpp->unpackU32(local_id, "LocalID");
|
||||
|
|
@ -369,6 +379,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
}
|
||||
else
|
||||
{
|
||||
// Cache Miss.
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->recordCacheMissEvent(id, update_type, cache_miss_type);
|
||||
#endif
|
||||
|
||||
continue; // no data packer, skip this object
|
||||
}
|
||||
}
|
||||
|
|
@ -380,13 +395,15 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
compressed_dp.reset();
|
||||
|
||||
U32 flags = 0;
|
||||
if (update_type != OUT_TERSE_IMPROVED)
|
||||
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
|
||||
{
|
||||
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
|
||||
}
|
||||
|
||||
// I don't think we ever use this flag from the server. DK 2010/12/09
|
||||
if (flags & FLAGS_ZLIB_COMPRESSED)
|
||||
{
|
||||
//llinfos << "TEST: flags & FLAGS_ZLIB_COMPRESSED" << llendl;
|
||||
compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
|
||||
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i);
|
||||
uncompressed_length = 2048;
|
||||
|
|
@ -402,7 +419,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
}
|
||||
|
||||
|
||||
if (update_type != OUT_TERSE_IMPROVED)
|
||||
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
|
||||
{
|
||||
compressed_dp.unpackUUID(fullid, "ID");
|
||||
compressed_dp.unpackU32(local_id, "LocalID");
|
||||
|
|
@ -422,7 +439,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (update_type != OUT_FULL)
|
||||
else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only?
|
||||
{
|
||||
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
|
||||
getUUIDFromLocal(fullid,
|
||||
|
|
@ -435,7 +452,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
mNumUnknownUpdates++;
|
||||
}
|
||||
}
|
||||
else
|
||||
else // OUT_FULL only?
|
||||
{
|
||||
mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
|
||||
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
|
||||
|
|
@ -467,12 +484,12 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
gMessageSystem->getSenderPort());
|
||||
|
||||
if (objectp->mLocalID != local_id)
|
||||
{ // Update local ID in object with the one sent from the region
|
||||
{ // Update local ID in object with the one sent from the region
|
||||
objectp->mLocalID = local_id;
|
||||
}
|
||||
|
||||
if (objectp->getRegion() != regionp)
|
||||
{ // Object changed region, so update it
|
||||
{ // Object changed region, so update it
|
||||
objectp->updateRegion(regionp); // for LLVOAvatar
|
||||
}
|
||||
}
|
||||
|
|
@ -483,18 +500,24 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
{
|
||||
if (update_type == OUT_TERSE_IMPROVED)
|
||||
{
|
||||
// llinfos << "terse update for an unknown object:" << fullid << llendl;
|
||||
// llinfos << "terse update for an unknown object (compressed):" << fullid << llendl;
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (cached)
|
||||
else if (cached) // Cache hit only?
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update_type != OUT_FULL)
|
||||
{
|
||||
// llinfos << "terse update for an unknown object:" << fullid << llendl;
|
||||
//llinfos << "terse update for an unknown object:" << fullid << llendl;
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -504,7 +527,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
if (mDeadObjects.find(fullid) != mDeadObjects.end())
|
||||
{
|
||||
mNumDeadObjectUpdates++;
|
||||
// llinfos << "update for a dead object:" << fullid << llendl;
|
||||
//llinfos << "update for a dead object:" << fullid << llendl;
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -512,6 +538,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());
|
||||
if (!objectp)
|
||||
{
|
||||
llinfos << "createObject failure for object: " << fullid << llendl;
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
justCreated = TRUE;
|
||||
|
|
@ -524,19 +554,26 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;
|
||||
}
|
||||
|
||||
bool bCached = false;
|
||||
if (compressed)
|
||||
{
|
||||
if (update_type != OUT_TERSE_IMPROVED)
|
||||
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
|
||||
{
|
||||
objectp->mLocalID = local_id;
|
||||
}
|
||||
processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated);
|
||||
if (update_type != OUT_TERSE_IMPROVED)
|
||||
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
|
||||
{
|
||||
bCached = true;
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
|
||||
LLViewerStatsRecorder::instance()->recordCacheFullUpdate(local_id, update_type, result, objectp);
|
||||
#else
|
||||
objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (cached)
|
||||
else if (cached) // Cache hit only?
|
||||
{
|
||||
objectp->mLocalID = local_id;
|
||||
processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated);
|
||||
|
|
@ -549,8 +586,17 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
|||
}
|
||||
processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);
|
||||
}
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->recordObjectUpdateEvent(local_id, update_type, objectp);
|
||||
#endif
|
||||
objectp->setLastUpdateType(update_type);
|
||||
objectp->setLastUpdateCached(bCached);
|
||||
}
|
||||
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->endObjectUpdateEvents();
|
||||
#endif
|
||||
|
||||
LLVOAvatar::cullAvatarsByPixelArea();
|
||||
}
|
||||
|
||||
|
|
@ -681,12 +727,12 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
|
|||
|
||||
// update global timer
|
||||
F32 last_time = gFrameTimeSeconds;
|
||||
U64 time = totalTime(); // this will become the new gFrameTime when the update is done
|
||||
U64 time = totalTime(); // this will become the new gFrameTime when the update is done
|
||||
// Time _can_ go backwards, for example if the user changes the system clock.
|
||||
// It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here.
|
||||
// llassert(time > gFrameTime);
|
||||
F64 time_diff = U64_to_F64(time - gFrameTime)/(F64)SEC_TO_MICROSEC;
|
||||
gFrameTime = time;
|
||||
gFrameTime = time;
|
||||
F64 time_since_start = U64_to_F64(gFrameTime - gStartTime)/(F64)SEC_TO_MICROSEC;
|
||||
gFrameTimeSeconds = (F32)time_since_start;
|
||||
|
||||
|
|
@ -788,7 +834,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
|
|||
{
|
||||
std::string id_str;
|
||||
objectp->mID.toString(id_str);
|
||||
std::string tmpstr = std::string("Par: ") + id_str;
|
||||
std::string tmpstr = std::string("Par: ") + id_str;
|
||||
addDebugBeacon(objectp->getPositionAgent(),
|
||||
tmpstr,
|
||||
LLColor4(1.f,0.f,0.f,1.f),
|
||||
|
|
@ -808,12 +854,12 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
|
|||
std::string tmpstr;
|
||||
if (objectp->getParent())
|
||||
{
|
||||
tmpstr = std::string("ChP: ") + id_str;
|
||||
tmpstr = std::string("ChP: ") + id_str;
|
||||
text_color = LLColor4(0.f, 1.f, 0.f, 1.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpstr = std::string("ChNoP: ") + id_str;
|
||||
tmpstr = std::string("ChNoP: ") + id_str;
|
||||
text_color = LLColor4(1.f, 0.f, 0.f, 1.f);
|
||||
}
|
||||
id = sIndexAndLocalIDToUUID[oi.mParentInfo];
|
||||
|
|
@ -1519,8 +1565,8 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
|
|||
llinfos << "Agent: " << objectp->getPositionAgent() << llendl;
|
||||
addDebugBeacon(objectp->getPositionAgent(),"");
|
||||
#endif
|
||||
gPipeline.markMoved(objectp->mDrawable);
|
||||
objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE);
|
||||
gPipeline.markMoved(objectp->mDrawable);
|
||||
objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE);
|
||||
|
||||
// Flag the object as no longer orphaned
|
||||
childp->mOrphaned = FALSE;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#include "llurldispatcher.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerparceloverlay.h"
|
||||
#include "llviewerstatsrecorder.h"
|
||||
#include "llvlmanager.h"
|
||||
#include "llvlcomposition.h"
|
||||
#include "llvocache.h"
|
||||
|
|
@ -1032,7 +1033,7 @@ void LLViewerRegion::getInfo(LLSD& info)
|
|||
info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
|
||||
}
|
||||
|
||||
void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
|
||||
LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
|
||||
{
|
||||
U32 local_id = objectp->getLocalID();
|
||||
U32 crc = objectp->getCRC();
|
||||
|
|
@ -1046,35 +1047,36 @@ void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinary
|
|||
{
|
||||
// Record a hit
|
||||
entry->recordDupe();
|
||||
return CACHE_UPDATE_DUPE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the cache entry
|
||||
mCacheMap.erase(local_id);
|
||||
delete entry;
|
||||
entry = new LLVOCacheEntry(local_id, crc, dp);
|
||||
mCacheMap[local_id] = entry;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we haven't seen this object before
|
||||
|
||||
// Create new entry and add to map
|
||||
if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
|
||||
{
|
||||
mCacheMap.erase(mCacheMap.begin());
|
||||
}
|
||||
// Update the cache entry
|
||||
mCacheMap.erase(local_id);
|
||||
delete entry;
|
||||
entry = new LLVOCacheEntry(local_id, crc, dp);
|
||||
|
||||
mCacheMap[local_id] = entry;
|
||||
return CACHE_UPDATE_CHANGED;
|
||||
}
|
||||
return ;
|
||||
|
||||
// we haven't seen this object before
|
||||
|
||||
// Create new entry and add to map
|
||||
eCacheUpdateResult result = CACHE_UPDATE_ADDED;
|
||||
if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
|
||||
{
|
||||
mCacheMap.erase(mCacheMap.begin());
|
||||
result = CACHE_UPDATE_REPLACED;
|
||||
|
||||
}
|
||||
entry = new LLVOCacheEntry(local_id, crc, dp);
|
||||
|
||||
mCacheMap[local_id] = entry;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get data packer for this object, if we have cached data
|
||||
// AND the CRC matches. JC
|
||||
LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc)
|
||||
LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type)
|
||||
{
|
||||
llassert(mCacheLoaded);
|
||||
|
||||
|
|
@ -1087,17 +1089,20 @@ LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc)
|
|||
{
|
||||
// Record a hit
|
||||
entry->recordHit();
|
||||
cache_miss_type = CACHE_MISS_TYPE_NONE;
|
||||
return entry->getDP(crc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// llinfos << "CRC miss for " << local_id << llendl;
|
||||
cache_miss_type = CACHE_MISS_TYPE_CRC;
|
||||
mCacheMissCRC.put(local_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// llinfos << "Cache miss for " << local_id << llendl;
|
||||
cache_miss_type = CACHE_MISS_TYPE_FULL;
|
||||
mCacheMissFull.put(local_id);
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -1119,9 +1124,6 @@ void LLViewerRegion::requestCacheMisses()
|
|||
S32 blocks = 0;
|
||||
S32 i;
|
||||
|
||||
const U8 CACHE_MISS_TYPE_FULL = 0;
|
||||
const U8 CACHE_MISS_TYPE_CRC = 1;
|
||||
|
||||
// Send full cache miss updates. For these, we KNOW we don't
|
||||
// have a viewer object.
|
||||
for (i = 0; i < full_count; i++)
|
||||
|
|
@ -1184,6 +1186,11 @@ void LLViewerRegion::requestCacheMisses()
|
|||
|
||||
mCacheDirty = TRUE ;
|
||||
// llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl;
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this);
|
||||
LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count);
|
||||
LLViewerStatsRecorder::instance()->endObjectUpdateEvents();
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLViewerRegion::dumpCache()
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
// Surface id's
|
||||
#define LAND 1
|
||||
#define WATER 2
|
||||
const U32 MAX_OBJECT_CACHE_ENTRIES = 10000;
|
||||
const U32 MAX_OBJECT_CACHE_ENTRIES = 50000;
|
||||
|
||||
|
||||
class LLEventPoll;
|
||||
|
|
@ -275,9 +275,24 @@ public:
|
|||
|
||||
void getInfo(LLSD& info);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CACHE_MISS_TYPE_FULL = 0,
|
||||
CACHE_MISS_TYPE_CRC,
|
||||
CACHE_MISS_TYPE_NONE
|
||||
} eCacheMissType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CACHE_UPDATE_DUPE = 0,
|
||||
CACHE_UPDATE_CHANGED,
|
||||
CACHE_UPDATE_ADDED,
|
||||
CACHE_UPDATE_REPLACED
|
||||
} eCacheUpdateResult;
|
||||
|
||||
// handle a full update message
|
||||
void cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp);
|
||||
LLDataPacker *getDP(U32 local_id, U32 crc);
|
||||
eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp);
|
||||
LLDataPacker *getDP(U32 local_id, U32 crc, U8 &cache_miss_type);
|
||||
void requestCacheMisses();
|
||||
void addCacheMissFull(const U32 local_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,258 @@
|
|||
/**
|
||||
* @file llviewerstatsrecorder.cpp
|
||||
* @brief record info about viewer events to a metrics log file
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&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 "llviewerstatsrecorder.h"
|
||||
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
|
||||
#include "llfile.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewerobject.h"
|
||||
|
||||
|
||||
// To do - something using region name or global position
|
||||
#if LL_WINDOWS
|
||||
static const std::string STATS_FILE_NAME("C:\\ViewerObjectCacheStats.csv");
|
||||
#else
|
||||
static const std::string STATS_FILE_NAME("/tmp/viewerstats.csv");
|
||||
#endif
|
||||
|
||||
LLViewerStatsRecorder* LLViewerStatsRecorder::sInstance = NULL;
|
||||
LLViewerStatsRecorder::LLViewerStatsRecorder() :
|
||||
mObjectCacheFile(NULL),
|
||||
mTimer(),
|
||||
mRegionp(NULL),
|
||||
mStartTime(0.f),
|
||||
mProcessingTime(0.f)
|
||||
{
|
||||
if (NULL != sInstance)
|
||||
{
|
||||
llerrs << "Attempted to create multiple instances of LLViewerStatsRecorder!" << llendl;
|
||||
}
|
||||
sInstance = this;
|
||||
clearStats();
|
||||
}
|
||||
|
||||
LLViewerStatsRecorder::~LLViewerStatsRecorder()
|
||||
{
|
||||
if (mObjectCacheFile != NULL)
|
||||
{
|
||||
LLFile::close(mObjectCacheFile);
|
||||
mObjectCacheFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLViewerStatsRecorder::initClass()
|
||||
{
|
||||
sInstance = new LLViewerStatsRecorder();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLViewerStatsRecorder::cleanupClass()
|
||||
{
|
||||
delete sInstance;
|
||||
sInstance = NULL;
|
||||
}
|
||||
|
||||
|
||||
void LLViewerStatsRecorder::initStatsRecorder(LLViewerRegion *regionp)
|
||||
{
|
||||
if (mObjectCacheFile == NULL)
|
||||
{
|
||||
mStartTime = LLTimer::getTotalTime();
|
||||
mObjectCacheFile = LLFile::fopen(STATS_FILE_NAME, "wb");
|
||||
if (mObjectCacheFile)
|
||||
{ // Write column headers
|
||||
std::ostringstream data_msg;
|
||||
data_msg << "EventTime, "
|
||||
<< "ProcessingTime, "
|
||||
<< "CacheHits, "
|
||||
<< "CacheFullMisses, "
|
||||
<< "CacheCrcMisses, "
|
||||
<< "FullUpdates, "
|
||||
<< "TerseUpdates, "
|
||||
<< "CacheMissRequests, "
|
||||
<< "CacheMissResponses, "
|
||||
<< "CacheUpdateDupes, "
|
||||
<< "CacheUpdateChanges, "
|
||||
<< "CacheUpdateAdds, "
|
||||
<< "CacheUpdateReplacements, "
|
||||
<< "UpdateFailures"
|
||||
<< "\n";
|
||||
|
||||
fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerStatsRecorder::beginObjectUpdateEvents(LLViewerRegion *regionp)
|
||||
{
|
||||
initStatsRecorder(regionp);
|
||||
mRegionp = regionp;
|
||||
mProcessingTime = LLTimer::getTotalTime();
|
||||
clearStats();
|
||||
}
|
||||
|
||||
void LLViewerStatsRecorder::clearStats()
|
||||
{
|
||||
mObjectCacheHitCount = 0;
|
||||
mObjectCacheMissFullCount = 0;
|
||||
mObjectCacheMissCrcCount = 0;
|
||||
mObjectFullUpdates = 0;
|
||||
mObjectTerseUpdates = 0;
|
||||
mObjectCacheMissRequests = 0;
|
||||
mObjectCacheMissResponses = 0;
|
||||
mObjectCacheUpdateDupes = 0;
|
||||
mObjectCacheUpdateChanges = 0;
|
||||
mObjectCacheUpdateAdds = 0;
|
||||
mObjectCacheUpdateReplacements = 0;
|
||||
mObjectUpdateFailures = 0;
|
||||
}
|
||||
|
||||
|
||||
void LLViewerStatsRecorder::recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type)
|
||||
{
|
||||
mObjectUpdateFailures++;
|
||||
}
|
||||
|
||||
void LLViewerStatsRecorder::recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type)
|
||||
{
|
||||
if (LLViewerRegion::CACHE_MISS_TYPE_FULL == cache_miss_type)
|
||||
{
|
||||
mObjectCacheMissFullCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mObjectCacheMissCrcCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp)
|
||||
{
|
||||
switch (update_type)
|
||||
{
|
||||
case OUT_FULL:
|
||||
mObjectFullUpdates++;
|
||||
break;
|
||||
case OUT_TERSE_IMPROVED:
|
||||
mObjectTerseUpdates++;
|
||||
break;
|
||||
case OUT_FULL_COMPRESSED:
|
||||
mObjectCacheMissResponses++;
|
||||
break;
|
||||
case OUT_FULL_CACHED:
|
||||
mObjectCacheHitCount++;
|
||||
break;
|
||||
default:
|
||||
llwarns << "Unknown update_type" << llendl;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp)
|
||||
{
|
||||
switch (update_result)
|
||||
{
|
||||
case LLViewerRegion::CACHE_UPDATE_DUPE:
|
||||
mObjectCacheUpdateDupes++;
|
||||
break;
|
||||
case LLViewerRegion::CACHE_UPDATE_CHANGED:
|
||||
mObjectCacheUpdateChanges++;
|
||||
break;
|
||||
case LLViewerRegion::CACHE_UPDATE_ADDED:
|
||||
mObjectCacheUpdateAdds++;
|
||||
break;
|
||||
case LLViewerRegion::CACHE_UPDATE_REPLACED:
|
||||
mObjectCacheUpdateReplacements++;
|
||||
break;
|
||||
default:
|
||||
llwarns << "Unknown update_result type" << llendl;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void LLViewerStatsRecorder::recordRequestCacheMissesEvent(S32 count)
|
||||
{
|
||||
mObjectCacheMissRequests += count;
|
||||
}
|
||||
|
||||
void LLViewerStatsRecorder::endObjectUpdateEvents()
|
||||
{
|
||||
llinfos << "ILX: "
|
||||
<< mObjectCacheHitCount << " hits, "
|
||||
<< mObjectCacheMissFullCount << " full misses, "
|
||||
<< mObjectCacheMissCrcCount << " crc misses, "
|
||||
<< mObjectFullUpdates << " full updates, "
|
||||
<< mObjectTerseUpdates << " terse updates, "
|
||||
<< mObjectCacheMissRequests << " cache miss requests, "
|
||||
<< mObjectCacheMissResponses << " cache miss responses, "
|
||||
<< mObjectCacheUpdateDupes << " cache update dupes, "
|
||||
<< mObjectCacheUpdateChanges << " cache update changes, "
|
||||
<< mObjectCacheUpdateAdds << " cache update adds, "
|
||||
<< mObjectCacheUpdateReplacements << " cache update replacements, "
|
||||
<< mObjectUpdateFailures << " update failures"
|
||||
<< llendl;
|
||||
|
||||
S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures;
|
||||
if (mObjectCacheFile != NULL &&
|
||||
total_objects > 0)
|
||||
{
|
||||
std::ostringstream data_msg;
|
||||
F32 processing32 = (F32) ((LLTimer::getTotalTime() - mProcessingTime) / 1000.0);
|
||||
|
||||
data_msg << getTimeSinceStart()
|
||||
<< ", " << processing32
|
||||
<< ", " << mObjectCacheHitCount
|
||||
<< ", " << mObjectCacheMissFullCount
|
||||
<< ", " << mObjectCacheMissCrcCount
|
||||
<< ", " << mObjectFullUpdates
|
||||
<< ", " << mObjectTerseUpdates
|
||||
<< ", " << mObjectCacheMissRequests
|
||||
<< ", " << mObjectCacheMissResponses
|
||||
<< ", " << mObjectCacheUpdateDupes
|
||||
<< ", " << mObjectCacheUpdateChanges
|
||||
<< ", " << mObjectCacheUpdateAdds
|
||||
<< ", " << mObjectCacheUpdateReplacements
|
||||
<< ", " << mObjectUpdateFailures
|
||||
<< "\n";
|
||||
|
||||
fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile );
|
||||
}
|
||||
|
||||
clearStats();
|
||||
}
|
||||
|
||||
F32 LLViewerStatsRecorder::getTimeSinceStart()
|
||||
{
|
||||
return (F32) ((LLTimer::getTotalTime() - mStartTime) / 1000.0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* @file llviewerstatsrecorder.h
|
||||
* @brief record info about viewer events to a metrics log file
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&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$
|
||||
*/
|
||||
|
||||
#ifndef LLVIEWERSTATSRECORDER_H
|
||||
#define LLVIEWERSTATSRECORDER_H
|
||||
|
||||
|
||||
// This is a diagnostic class used to record information from the viewer
|
||||
// for analysis.
|
||||
|
||||
// This is normally 0. Set to 1 to enable viewer stats recording
|
||||
#define LL_RECORD_VIEWER_STATS 0
|
||||
|
||||
|
||||
#if LL_RECORD_VIEWER_STATS
|
||||
#include "llframetimer.h"
|
||||
#include "llviewerobject.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
class LLMutex;
|
||||
class LLViewerRegion;
|
||||
class LLViewerObject;
|
||||
|
||||
class LLViewerStatsRecorder
|
||||
{
|
||||
public:
|
||||
LLViewerStatsRecorder();
|
||||
~LLViewerStatsRecorder();
|
||||
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
static LLViewerStatsRecorder* instance() {return sInstance; }
|
||||
|
||||
void initStatsRecorder(LLViewerRegion *regionp);
|
||||
|
||||
void beginObjectUpdateEvents(LLViewerRegion *regionp);
|
||||
void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type);
|
||||
void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type);
|
||||
void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp);
|
||||
void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp);
|
||||
void recordRequestCacheMissesEvent(S32 count);
|
||||
void endObjectUpdateEvents();
|
||||
|
||||
F32 getTimeSinceStart();
|
||||
|
||||
private:
|
||||
static LLViewerStatsRecorder* sInstance;
|
||||
|
||||
LLFILE * mObjectCacheFile; // File to write data into
|
||||
LLFrameTimer mTimer;
|
||||
LLViewerRegion* mRegionp;
|
||||
F64 mStartTime;
|
||||
F64 mProcessingTime;
|
||||
|
||||
S32 mObjectCacheHitCount;
|
||||
S32 mObjectCacheMissFullCount;
|
||||
S32 mObjectCacheMissCrcCount;
|
||||
S32 mObjectFullUpdates;
|
||||
S32 mObjectTerseUpdates;
|
||||
S32 mObjectCacheMissRequests;
|
||||
S32 mObjectCacheMissResponses;
|
||||
S32 mObjectCacheUpdateDupes;
|
||||
S32 mObjectCacheUpdateChanges;
|
||||
S32 mObjectCacheUpdateAdds;
|
||||
S32 mObjectCacheUpdateReplacements;
|
||||
S32 mObjectUpdateFailures;
|
||||
|
||||
|
||||
void clearStats();
|
||||
};
|
||||
#endif // LL_RECORD_VIEWER_STATS
|
||||
|
||||
#endif // LLVIEWERSTATSRECORDER_H
|
||||
|
||||
|
|
@ -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,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 = 16 ;
|
||||
// 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";
|
||||
|
||||
|
|
@ -259,7 +261,6 @@ void LLVOCache::destroyClass()
|
|||
LLVOCache::LLVOCache():
|
||||
mInitialized(FALSE),
|
||||
mReadOnly(TRUE),
|
||||
mNumEntries(0),
|
||||
mCacheSize(1)
|
||||
{
|
||||
mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled");
|
||||
|
|
@ -286,8 +287,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 ;
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +307,6 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)
|
|||
|
||||
mCacheSize = size;
|
||||
|
||||
mMetaInfo.mVersion = cache_version;
|
||||
readCacheHeader();
|
||||
mInitialized = TRUE ;
|
||||
|
||||
|
|
@ -321,12 +328,14 @@ void LLVOCache::removeCache(ELLPath location)
|
|||
{
|
||||
if(mReadOnly)
|
||||
{
|
||||
llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
@ -339,11 +348,13 @@ void LLVOCache::removeCache()
|
|||
llassert_always(mInitialized) ;
|
||||
if(mReadOnly)
|
||||
{
|
||||
llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
std::string delem = gDirUtilp->getDirDelimiter();
|
||||
std::string mask = delem + "*";
|
||||
llinfos << "Removing cache at " << mObjectCacheDirName << llendl;
|
||||
gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask);
|
||||
|
||||
clearCacheInMemory() ;
|
||||
|
|
@ -352,16 +363,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 +382,7 @@ void LLVOCache::removeFromCache(U64 handle)
|
|||
{
|
||||
if(mReadOnly)
|
||||
{
|
||||
llwarns << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
|
@ -387,24 +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))
|
||||
{
|
||||
delete apr_file ;
|
||||
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))
|
||||
{
|
||||
delete apr_file ;
|
||||
removeCache() ;
|
||||
if (remove_cache_on_error)
|
||||
{
|
||||
removeCache() ;
|
||||
}
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
|
|
@ -415,7 +423,8 @@ void LLVOCache::readCacheHeader()
|
|||
{
|
||||
if(!mEnabled)
|
||||
{
|
||||
return ;
|
||||
llwarns << "Not reading cache header: Cache is currently disabled." << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
//clear stale info.
|
||||
|
|
@ -423,33 +432,35 @@ 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)))
|
||||
bool remove_cache_on_error = false;
|
||||
if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo), remove_cache_on_error))
|
||||
{
|
||||
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)))
|
||||
if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo), remove_cache_on_error))
|
||||
{
|
||||
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 +473,57 @@ void LLVOCache::readCacheHeader()
|
|||
|
||||
void LLVOCache::writeCacheHeader()
|
||||
{
|
||||
if(mReadOnly || !mEnabled)
|
||||
if (!mEnabled)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
llwarns << "Not writing cache header: Cache is currently disabled." << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
|
||||
if(mReadOnly)
|
||||
{
|
||||
llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
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)))
|
||||
{
|
||||
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 ;
|
||||
|
|
@ -505,16 +533,19 @@ 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)) ;
|
||||
|
||||
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,22 +553,24 @@ 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 ;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
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 +578,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 +588,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 ;
|
||||
|
|
@ -567,86 +601,104 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
|
|||
|
||||
void LLVOCache::purgeEntries()
|
||||
{
|
||||
U32 limit = mCacheSize - NUM_ENTRIES_TO_PURGE ;
|
||||
while(mHeaderEntryQueue.size() > limit)
|
||||
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<HeaderEntryInfo*> 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_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ;
|
||||
HeaderEntryInfo* entry = *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)
|
||||
{
|
||||
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 ;
|
||||
}
|
||||
|
||||
U32 num_handle_entries = mHandleEntryMap.size();
|
||||
|
||||
HeaderEntryInfo* entry;
|
||||
handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
|
||||
if(iter == mHandleEntryMap.end()) //new entry
|
||||
{
|
||||
if(mNumEntries >= mCacheSize)
|
||||
{
|
||||
if(num_handle_entries >= mCacheSize)
|
||||
{
|
||||
purgeEntries() ;
|
||||
num_handle_entries = mHandleEntryMap.size();
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
//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))
|
||||
{
|
||||
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 +706,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,10 +95,13 @@ private:
|
|||
{
|
||||
bool operator()(const HeaderEntryInfo* lhs, const HeaderEntryInfo* rhs) const
|
||||
{
|
||||
return lhs->mTime < rhs->mTime; // older entry in front of queue (set)
|
||||
if (lhs->mTime == rhs->mTime)
|
||||
{
|
||||
return lhs->mHandle < rhs->mHandle;
|
||||
}
|
||||
return lhs->mTime < rhs->mTime; // older entry in front
|
||||
}
|
||||
};
|
||||
typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t;
|
||||
typedef std::map<U64, HeaderEntryInfo*> handle_entry_map_t;
|
||||
private:
|
||||
LLVOCache() ;
|
||||
|
|
@ -125,8 +128,8 @@ private:
|
|||
void removeCache() ;
|
||||
void purgeEntries();
|
||||
BOOL updateEntry(const HeaderEntryInfo* entry);
|
||||
BOOL checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes) ;
|
||||
BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) ;
|
||||
BOOL checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error = true) ;
|
||||
BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error = true) ;
|
||||
|
||||
private:
|
||||
BOOL mEnabled;
|
||||
|
|
@ -134,11 +137,9 @@ private:
|
|||
BOOL mReadOnly ;
|
||||
HeaderMetaInfo mMetaInfo;
|
||||
U32 mCacheSize;
|
||||
U32 mNumEntries;
|
||||
std::string mHeaderFileName ;
|
||||
std::string mObjectCacheDirName;
|
||||
LLVolatileAPRPool* mLocalAPRFilePoolp ;
|
||||
header_entry_queue_t mHeaderEntryQueue;
|
||||
handle_entry_map_t mHandleEntryMap;
|
||||
|
||||
static LLVOCache* sInstance ;
|
||||
|
|
|
|||
|
|
@ -424,6 +424,7 @@ public:
|
|||
RENDER_DEBUG_AVATAR_VOLUME = 0x0100000,
|
||||
RENDER_DEBUG_BUILD_QUEUE = 0x0200000,
|
||||
RENDER_DEBUG_AGENT_TARGET = 0x0400000,
|
||||
RENDER_DEBUG_UPDATE_TYPE = 0x0800000,
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -2152,6 +2152,16 @@
|
|||
function="Advanced.ToggleInfoDisplay"
|
||||
parameter="render batches" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
label="Update Type"
|
||||
name="Update Type">
|
||||
<menu_item_check.on_check
|
||||
function="Advanced.CheckInfoDisplay"
|
||||
parameter="update type" />
|
||||
<menu_item_check.on_click
|
||||
function="Advanced.ToggleInfoDisplay"
|
||||
parameter="update type" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
label="Texture Anim"
|
||||
name="Texture Anim">
|
||||
|
|
|
|||
Loading…
Reference in New Issue