LLVOCache class implemented.
This commit is contained in:
107
indra/llcommon/stringize.h
Normal file
107
indra/llcommon/stringize.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @file stringize.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2008-12-17
|
||||
* @brief stringize(item) template function and STRINGIZE(expression) macro
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&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$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_STRINGIZE_H)
|
||||
#define LL_STRINGIZE_H
|
||||
|
||||
#include <sstream>
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
|
||||
/**
|
||||
* stringize(item) encapsulates an idiom we use constantly, using
|
||||
* operator<<(std::ostringstream&, TYPE) followed by std::ostringstream::str()
|
||||
* to render a string expressing some item.
|
||||
*/
|
||||
template <typename T>
|
||||
std::string stringize(const T& item)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << item;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* stringize_f(functor)
|
||||
*/
|
||||
template <typename Functor>
|
||||
std::string stringize_f(Functor const & f)
|
||||
{
|
||||
std::ostringstream out;
|
||||
f(out);
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* STRINGIZE(item1 << item2 << item3 ...) effectively expands to the
|
||||
* following:
|
||||
* @code
|
||||
* std::ostringstream out;
|
||||
* out << item1 << item2 << item3 ... ;
|
||||
* return out.str();
|
||||
* @endcode
|
||||
*/
|
||||
#define STRINGIZE(EXPRESSION) (stringize_f(boost::lambda::_1 << EXPRESSION))
|
||||
|
||||
|
||||
/**
|
||||
* destringize(str)
|
||||
* defined for symmetry with stringize
|
||||
* *NOTE - this has distinct behavior from boost::lexical_cast<T> regarding
|
||||
* leading/trailing whitespace and handling of bad_lexical_cast exceptions
|
||||
*/
|
||||
template <typename T>
|
||||
T destringize(std::string const & str)
|
||||
{
|
||||
T val;
|
||||
std::istringstream in(str);
|
||||
in >> val;
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* destringize_f(str, functor)
|
||||
*/
|
||||
template <typename Functor>
|
||||
void destringize_f(std::string const & str, Functor const & f)
|
||||
{
|
||||
std::istringstream in(str);
|
||||
f(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* DESTRINGIZE(str, item1 >> item2 >> item3 ...) effectively expands to the
|
||||
* following:
|
||||
* @code
|
||||
* std::istringstream in(str);
|
||||
* in >> item1 >> item2 >> item3 ... ;
|
||||
* @endcode
|
||||
*/
|
||||
#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), (boost::lambda::_1 >> EXPRESSION)))
|
||||
|
||||
|
||||
#endif /* ! defined(LL_STRINGIZE_H) */
|
||||
@@ -80,6 +80,7 @@
|
||||
#include "llrender.h"
|
||||
#include "llfont.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llvocache.h"
|
||||
|
||||
#include "llweb.h"
|
||||
#include "llsecondlifeurls.h"
|
||||
@@ -1552,6 +1553,8 @@ bool LLAppViewer::cleanup()
|
||||
}
|
||||
#endif
|
||||
|
||||
llinfos << "Misc Cleanup" << llendflush;
|
||||
|
||||
// For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up.
|
||||
// (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve
|
||||
delete gStaticVFS;
|
||||
@@ -1566,6 +1569,7 @@ bool LLAppViewer::cleanup()
|
||||
|
||||
LLWatchdog::getInstance()->cleanup();
|
||||
|
||||
llinfos << "Shutting down message system" << llendflush;
|
||||
end_messaging_system();
|
||||
llinfos << "Message system deleted." << llendflush;
|
||||
|
||||
@@ -3041,11 +3045,23 @@ U32 LLAppViewer::getTextureCacheVersion()
|
||||
|
||||
return TEXTURE_CACHE_VERSION ;
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLAppViewer::getObjectCacheVersion()
|
||||
{
|
||||
// Viewer object cache version, change if object update
|
||||
// format changes. JC
|
||||
const U32 INDRA_OBJECT_CACHE_VERSION = 14;
|
||||
|
||||
return INDRA_OBJECT_CACHE_VERSION;
|
||||
}
|
||||
|
||||
bool LLAppViewer::initCache()
|
||||
{
|
||||
mPurgeCache = false;
|
||||
BOOL read_only = mSecondInstance ? TRUE : FALSE;
|
||||
LLAppViewer::getTextureCache()->setReadOnly(read_only);
|
||||
LLAppViewer::getTextureCache()->setReadOnly(read_only) ;
|
||||
LLVOCache::getInstance()->setReadOnly(read_only);
|
||||
|
||||
bool texture_cache_mismatch = false;
|
||||
if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion())
|
||||
@@ -3125,6 +3141,8 @@ bool LLAppViewer::initCache()
|
||||
S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
|
||||
texture_cache_size -= extra;
|
||||
|
||||
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()) ;
|
||||
|
||||
LLSplashScreen::update("Initializing VFS...");
|
||||
|
||||
// Init the VFS
|
||||
@@ -3281,8 +3299,9 @@ bool LLAppViewer::initCache()
|
||||
|
||||
void LLAppViewer::purgeCache()
|
||||
{
|
||||
LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;
|
||||
LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl;
|
||||
LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
|
||||
LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
|
||||
std::string mask = "*.*";
|
||||
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask);
|
||||
}
|
||||
@@ -4245,7 +4264,10 @@ void LLAppViewer::disconnectViewer()
|
||||
|
||||
// This is where we used to call gObjectList.destroy() and then delete gWorldp.
|
||||
// Now we just ask the LLWorld singleton to cleanly shut down.
|
||||
LLWorld::getInstance()->destroyClass();
|
||||
if(LLWorld::instanceExists())
|
||||
{
|
||||
LLWorld::getInstance()->destroyClass();
|
||||
}
|
||||
|
||||
// call all self-registered classes
|
||||
LLDestroyClassList::instance().fireCallbacks();
|
||||
|
||||
@@ -96,7 +96,9 @@ public:
|
||||
static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; }
|
||||
static LLTextureFetch* getTextureFetch() { return sTextureFetch; }
|
||||
|
||||
static U32 getTextureCacheVersion();
|
||||
static U32 getTextureCacheVersion() ;
|
||||
static U32 getObjectCacheVersion() ;
|
||||
|
||||
const std::string& getSerialNumber() { return mSerialNumber; }
|
||||
|
||||
bool getPurgeCache() const { return mPurgeCache; }
|
||||
|
||||
@@ -167,13 +167,13 @@ U64 LLViewerObjectList::getIndex(const U32 local_id,
|
||||
return (((U64)index) << 32) | (U64)local_id;
|
||||
}
|
||||
|
||||
BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
|
||||
BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp)
|
||||
{
|
||||
if(object.getRegion())
|
||||
if(objectp && objectp->getRegion())
|
||||
{
|
||||
U32 local_id = object.mLocalID;
|
||||
U32 ip = object.getRegion()->getHost().getAddress();
|
||||
U32 port = object.getRegion()->getHost().getPort();
|
||||
U32 local_id = objectp->mLocalID;
|
||||
U32 ip = objectp->getRegion()->getHost().getAddress();
|
||||
U32 port = objectp->getRegion()->getHost().getPort();
|
||||
U64 ipport = (((U64)ip) << 32) | (U64)port;
|
||||
U32 index = sIPAndPortToIndex[ipport];
|
||||
|
||||
@@ -188,7 +188,7 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
|
||||
}
|
||||
|
||||
// Found existing entry
|
||||
if (iter->second == object.getID())
|
||||
if (iter->second == objectp->getID())
|
||||
{ // Full UUIDs match, so remove the entry
|
||||
sIndexAndLocalIDToUUID.erase(iter);
|
||||
return TRUE;
|
||||
@@ -364,9 +364,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");
|
||||
@@ -374,6 +376,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
|
||||
}
|
||||
}
|
||||
@@ -465,7 +472,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
||||
// << ", regionp " << (U32) regionp << ", object region " << (U32) objectp->getRegion()
|
||||
// << llendl;
|
||||
//}
|
||||
removeFromLocalIDTable(*objectp);
|
||||
removeFromLocalIDTable(objectp);
|
||||
setUUIDAndLocal(fullid,
|
||||
local_id,
|
||||
gMessageSystem->getSenderIP(),
|
||||
@@ -530,6 +537,7 @@ 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)
|
||||
@@ -539,6 +547,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
||||
processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated);
|
||||
if (update_type != OUT_TERSE_IMPROVED)
|
||||
{
|
||||
bCached = true;
|
||||
objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
|
||||
}
|
||||
}
|
||||
@@ -557,7 +566,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
|
||||
}
|
||||
|
||||
objectp->setLastUpdateType(update_type);
|
||||
objectp->setLastUpdateCached(cached);
|
||||
objectp->setLastUpdateCached(bCached);
|
||||
}
|
||||
|
||||
LLVOAvatar::cullAvatarsByPixelArea();
|
||||
@@ -858,7 +867,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
|
||||
// << objectp->getRegion()->getHost().getPort() << llendl;
|
||||
//}
|
||||
|
||||
removeFromLocalIDTable(*objectp);
|
||||
removeFromLocalIDTable(objectp);
|
||||
|
||||
if (objectp->onActiveList())
|
||||
{
|
||||
@@ -1108,6 +1117,60 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
|
||||
LLWorld::getInstance()->shiftRegions(offset);
|
||||
}
|
||||
|
||||
//debug code
|
||||
bool LLViewerObjectList::hasMapObjectInRegion(LLViewerRegion* regionp)
|
||||
{
|
||||
for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
|
||||
{
|
||||
LLViewerObject* objectp = *iter;
|
||||
|
||||
if(objectp->isDead() || objectp->getRegion() == regionp)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
//make sure the region is cleaned up.
|
||||
void LLViewerObjectList::clearAllMapObjectsInRegion(LLViewerRegion* regionp)
|
||||
{
|
||||
std::set<LLViewerObject*> dead_object_list ;
|
||||
std::set<LLViewerObject*> region_object_list ;
|
||||
for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
|
||||
{
|
||||
LLViewerObject* objectp = *iter;
|
||||
|
||||
if(objectp->isDead())
|
||||
{
|
||||
dead_object_list.insert(objectp) ;
|
||||
}
|
||||
else if(objectp->getRegion() == regionp)
|
||||
{
|
||||
region_object_list.insert(objectp) ;
|
||||
}
|
||||
}
|
||||
|
||||
if(dead_object_list.size() > 0)
|
||||
{
|
||||
llwarns << "There are " << dead_object_list.size() << " dead objects on the map!" << llendl ;
|
||||
|
||||
for(std::set<LLViewerObject*>::iterator iter = dead_object_list.begin(); iter != dead_object_list.end(); ++iter)
|
||||
{
|
||||
cleanupReferences(*iter) ;
|
||||
}
|
||||
}
|
||||
if(region_object_list.size() > 0)
|
||||
{
|
||||
llwarns << "There are " << region_object_list.size() << " objects not removed from the deleted region!" << llendl ;
|
||||
|
||||
for(std::set<LLViewerObject*>::iterator iter = region_object_list.begin(); iter != region_object_list.end(); ++iter)
|
||||
{
|
||||
(*iter)->markDead() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
|
||||
{
|
||||
LLColor4 above_water_color = gColors.getColor( "NetMapOtherOwnAboveWater" );
|
||||
|
||||
@@ -96,6 +96,8 @@ public:
|
||||
|
||||
void shiftObjects(const LLVector3 &offset);
|
||||
|
||||
bool hasMapObjectInRegion(LLViewerRegion* regionp) ;
|
||||
void clearAllMapObjectsInRegion(LLViewerRegion* regionp) ;
|
||||
void renderObjectsForMap(LLNetMap &netmap);
|
||||
void renderObjectBounds(const LLVector3 ¢er);
|
||||
|
||||
@@ -182,7 +184,7 @@ public:
|
||||
const U32 ip,
|
||||
const U32 port); // Requires knowledge of message system info!
|
||||
|
||||
static BOOL removeFromLocalIDTable(const LLViewerObject &object);
|
||||
static BOOL removeFromLocalIDTable(const LLViewerObject* objectp);
|
||||
// Used ONLY by the orphaned object code.
|
||||
static U64 getIndex(const U32 local_id, const U32 ip, const U32 port);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "llsdutil.h"
|
||||
#include "llstartup.h"
|
||||
#include "lltrans.h"
|
||||
#include "llurldispatcher.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerparceloverlay.h"
|
||||
#include "llvlmanager.h"
|
||||
@@ -66,16 +67,82 @@
|
||||
#include "llvoclouds.h"
|
||||
#include "llworld.h"
|
||||
#include "llspatialpartition.h"
|
||||
|
||||
// Viewer object cache version, change if object update
|
||||
// format changes. JC
|
||||
const U32 INDRA_OBJECT_CACHE_VERSION = 14;
|
||||
#include "stringize.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
|
||||
extern BOOL gNoRender;
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region
|
||||
const S16 MAX_MAP_DIST = 10;
|
||||
typedef std::map<std::string, std::string> CapabilityMap;
|
||||
|
||||
class LLViewerRegionImpl {
|
||||
public:
|
||||
LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host)
|
||||
: mHost(host),
|
||||
mCompositionp(NULL),
|
||||
mEventPoll(NULL)//,
|
||||
// I'd prefer to set the LLCapabilityListener name to match the region
|
||||
// name -- it's disappointing that's not available at construction time.
|
||||
// We could instead store an LLCapabilityListener*, making
|
||||
// setRegionNameAndZone() replace the instance. Would that pose
|
||||
// consistency problems? Can we even request a capability before calling
|
||||
// setRegionNameAndZone()?
|
||||
// For testability -- the new Michael Feathers paradigm --
|
||||
// LLCapabilityListener binds all the globals it expects to need at
|
||||
// construction time.
|
||||
//mCapabilityListener(host.getString(), gMessageSystem, *region,
|
||||
//gAgent.getID(), gAgent.getSessionID())
|
||||
{
|
||||
}
|
||||
|
||||
// The surfaces and other layers
|
||||
LLSurface* mLandp;
|
||||
|
||||
// Region geometry data
|
||||
LLVector3d mOriginGlobal; // Location of southwest corner of region (meters)
|
||||
LLVector3d mCenterGlobal; // Location of center in world space (meters)
|
||||
LLHost mHost;
|
||||
|
||||
// The unique ID for this region.
|
||||
LLUUID mRegionID;
|
||||
|
||||
// region/estate owner - usually null.
|
||||
LLUUID mOwnerID;
|
||||
|
||||
// Network statistics for the region's circuit...
|
||||
LLTimer mLastNetUpdate;
|
||||
|
||||
// Misc
|
||||
LLVLComposition *mCompositionp; // Composition layer for the surface
|
||||
|
||||
LLVOCacheEntry::vocache_entry_map_t mCacheMap;
|
||||
// time?
|
||||
// LRU info?
|
||||
|
||||
// Cache ID is unique per-region, across renames, moving locations,
|
||||
// etc.
|
||||
LLUUID mCacheID;
|
||||
|
||||
CapabilityMap mCapabilities;
|
||||
|
||||
LLEventPoll* mEventPoll;
|
||||
|
||||
/// Post an event to this LLCapabilityListener to invoke a capability message on
|
||||
/// this LLViewerRegion's server
|
||||
/// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
|
||||
//LLCapabilityListener mCapabilityListener;
|
||||
|
||||
//spatial partitions for objects in this region
|
||||
std::vector<LLSpatialPartition*> mObjectPartition;
|
||||
|
||||
LLHTTPClient::ResponderPtr mHttpResponderPtr ;
|
||||
};
|
||||
|
||||
class BaseCapabilitiesComplete : public LLHTTPClient::Responder
|
||||
{
|
||||
@@ -153,15 +220,12 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
|
||||
const U32 grids_per_region_edge,
|
||||
const U32 grids_per_patch_edge,
|
||||
const F32 region_width_meters)
|
||||
: mCenterGlobal(),
|
||||
: mImpl(new LLViewerRegionImpl(this, host)),
|
||||
mHandle(handle),
|
||||
mHost( host ),
|
||||
mTimeDilation(1.0f),
|
||||
mName(""),
|
||||
mZoning(""),
|
||||
mOwnerID(),
|
||||
mIsEstateManager(FALSE),
|
||||
mCompositionp(NULL),
|
||||
mRegionFlags( REGION_FLAGS_DEFAULT ),
|
||||
mSimAccess( SIM_ACCESS_MIN ),
|
||||
mBillableFactor(1.0),
|
||||
@@ -171,28 +235,32 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
|
||||
mColoName("unknown"),
|
||||
mProductSKU("unknown"),
|
||||
mProductName("unknown"),
|
||||
mHttpUrl(""),
|
||||
mCacheLoaded(FALSE),
|
||||
mCacheEntriesCount(0),
|
||||
mCacheID(),
|
||||
mEventPoll(NULL),
|
||||
mReleaseNotesRequested(FALSE)
|
||||
mCacheDirty(FALSE),
|
||||
mReleaseNotesRequested(FALSE),
|
||||
mCapabilitiesReceived(false)
|
||||
{
|
||||
mWidth = region_width_meters;
|
||||
mOriginGlobal = from_region_handle(handle);
|
||||
mImpl->mOriginGlobal = from_region_handle(handle);
|
||||
updateRenderMatrix();
|
||||
|
||||
mLandp = new LLSurface('l', NULL);
|
||||
mImpl->mLandp = new LLSurface('l', NULL);
|
||||
|
||||
if (!gNoRender)
|
||||
{
|
||||
// Create the composition layer for the surface
|
||||
mCompositionp = new LLVLComposition(mLandp, grids_per_region_edge, region_width_meters/grids_per_region_edge);
|
||||
mCompositionp->setSurface(mLandp);
|
||||
mImpl->mCompositionp =
|
||||
new LLVLComposition(mImpl->mLandp,
|
||||
grids_per_region_edge,
|
||||
region_width_meters / grids_per_region_edge);
|
||||
mImpl->mCompositionp->setSurface(mImpl->mLandp);
|
||||
|
||||
// Create the surfaces
|
||||
mLandp->setRegion(this);
|
||||
mLandp->create(grids_per_region_edge,
|
||||
mImpl->mLandp->setRegion(this);
|
||||
mImpl->mLandp->create(grids_per_region_edge,
|
||||
grids_per_patch_edge,
|
||||
mOriginGlobal,
|
||||
mImpl->mOriginGlobal,
|
||||
mWidth);
|
||||
}
|
||||
|
||||
@@ -211,29 +279,26 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
|
||||
// Create the object lists
|
||||
initStats();
|
||||
|
||||
mCacheStart.append(mCacheEnd);
|
||||
|
||||
//create object partitions
|
||||
//MUST MATCH declaration of eObjectPartitions
|
||||
mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD
|
||||
mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN
|
||||
mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER
|
||||
mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER
|
||||
mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE
|
||||
mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE
|
||||
mObjectPartition.push_back(new LLCloudPartition()); //PARTITION_CLOUD
|
||||
mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS
|
||||
mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME
|
||||
mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE
|
||||
mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE
|
||||
mObjectPartition.push_back(NULL); //PARTITION_NONE
|
||||
|
||||
mImpl->mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD
|
||||
mImpl->mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN
|
||||
mImpl->mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER
|
||||
mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER
|
||||
mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE
|
||||
mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE
|
||||
mImpl->mObjectPartition.push_back(new LLCloudPartition()); //PARTITION_CLOUD
|
||||
mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS
|
||||
mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME
|
||||
mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE
|
||||
mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE
|
||||
mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE
|
||||
}
|
||||
|
||||
|
||||
void LLViewerRegion::initStats()
|
||||
{
|
||||
mLastNetUpdate.reset();
|
||||
mImpl->mLastNetUpdate.reset();
|
||||
mPacketsIn = 0;
|
||||
mBitsIn = 0;
|
||||
mLastBitsIn = 0;
|
||||
@@ -248,9 +313,9 @@ void LLViewerRegion::initStats()
|
||||
|
||||
LLViewerRegion::~LLViewerRegion()
|
||||
{
|
||||
if(mHttpResponderPtr)
|
||||
if(mImpl->mHttpResponderPtr)
|
||||
{
|
||||
(static_cast<BaseCapabilitiesComplete*>(mHttpResponderPtr.get()))->setRegion(NULL) ;
|
||||
(static_cast<BaseCapabilitiesComplete*>(mImpl->mHttpResponderPtr.get()))->setRegion(NULL) ;
|
||||
}
|
||||
|
||||
gVLManager.cleanupData(this);
|
||||
@@ -262,19 +327,47 @@ LLViewerRegion::~LLViewerRegion()
|
||||
|
||||
gObjectList.killObjects(this);
|
||||
|
||||
delete mCompositionp;
|
||||
delete mImpl->mCompositionp;
|
||||
delete mParcelOverlay;
|
||||
delete mLandp;
|
||||
delete mEventPoll;
|
||||
LLHTTPSender::clearSender(mHost);
|
||||
delete mImpl->mLandp;
|
||||
delete mImpl->mEventPoll;
|
||||
LLHTTPSender::clearSender(mImpl->mHost);
|
||||
|
||||
saveCache();
|
||||
saveObjectCache();
|
||||
|
||||
std::for_each(mObjectPartition.begin(), mObjectPartition.end(), DeletePointer());
|
||||
std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer());
|
||||
|
||||
delete mImpl;
|
||||
mImpl = NULL;
|
||||
}
|
||||
|
||||
/*LLEventPump& LLViewerRegion::getCapAPI() const
|
||||
{
|
||||
return mImpl->mCapabilityListener.getCapAPI();
|
||||
}*/
|
||||
|
||||
void LLViewerRegion::loadCache()
|
||||
/*virtual*/
|
||||
const LLHost& LLViewerRegion::getHost() const
|
||||
{
|
||||
return mImpl->mHost;
|
||||
}
|
||||
|
||||
LLSurface & LLViewerRegion::getLand() const
|
||||
{
|
||||
return *mImpl->mLandp;
|
||||
}
|
||||
|
||||
const LLUUID& LLViewerRegion::getRegionID() const
|
||||
{
|
||||
return mImpl->mRegionID;
|
||||
}
|
||||
|
||||
void LLViewerRegion::setRegionID(const LLUUID& region_id)
|
||||
{
|
||||
mImpl->mRegionID = region_id;
|
||||
}
|
||||
|
||||
void LLViewerRegion::loadObjectCache()
|
||||
{
|
||||
if (mCacheLoaded)
|
||||
{
|
||||
@@ -284,154 +377,46 @@ void LLViewerRegion::loadCache()
|
||||
// Presume success. If it fails, we don't want to try again.
|
||||
mCacheLoaded = TRUE;
|
||||
|
||||
LLVOCacheEntry *entry;
|
||||
|
||||
std::string filename;
|
||||
filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"") + gDirUtilp->getDirDelimiter() +
|
||||
llformat("objects_%d_%d.slc",U32(mHandle>>32)/REGION_WIDTH_UNITS, U32(mHandle)/REGION_WIDTH_UNITS );
|
||||
|
||||
LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
|
||||
if (!fp)
|
||||
if(LLVOCache::hasInstance())
|
||||
{
|
||||
// might not have a file, which is normal
|
||||
return;
|
||||
LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ;
|
||||
}
|
||||
|
||||
U32 zero;
|
||||
size_t nread;
|
||||
nread = fread(&zero, sizeof(U32), 1, fp);
|
||||
if (nread != 1 || zero)
|
||||
{
|
||||
// a non-zero value here means bad things!
|
||||
// skip reading the cached values
|
||||
llinfos << "Cache file invalid" << llendl;
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
U32 version;
|
||||
nread = fread(&version, sizeof(U32), 1, fp);
|
||||
if (nread != 1 || version != INDRA_OBJECT_CACHE_VERSION)
|
||||
{
|
||||
// a version mismatch here means we've changed the binary format!
|
||||
// skip reading the cached values
|
||||
llinfos << "Cache version changed, discarding" << llendl;
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
LLUUID cache_id;
|
||||
nread = fread(&cache_id.mData, 1, UUID_BYTES, fp);
|
||||
if (nread != (size_t)UUID_BYTES || mCacheID != cache_id)
|
||||
{
|
||||
llinfos << "Cache ID doesn't match for this region, discarding"
|
||||
<< llendl;
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
S32 num_entries;
|
||||
nread = fread(&num_entries, sizeof(S32), 1, fp);
|
||||
if (nread != 1)
|
||||
{
|
||||
llinfos << "Short read, discarding" << llendl;
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
S32 i;
|
||||
for (i = 0; i < num_entries; i++)
|
||||
{
|
||||
entry = new LLVOCacheEntry(fp);
|
||||
if (!entry->getLocalID())
|
||||
{
|
||||
llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl;
|
||||
delete entry;
|
||||
entry = NULL;
|
||||
break;
|
||||
}
|
||||
mCacheEnd.insert(*entry);
|
||||
mCacheMap[entry->getLocalID()] = entry;
|
||||
mCacheEntriesCount++;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
void LLViewerRegion::saveCache()
|
||||
void LLViewerRegion::saveObjectCache()
|
||||
{
|
||||
if (!mCacheLoaded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
S32 num_entries = mCacheEntriesCount;
|
||||
if (0 == num_entries)
|
||||
if (mImpl->mCacheMap.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename;
|
||||
filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"") + gDirUtilp->getDirDelimiter() +
|
||||
llformat("objects_%d_%d.slc", U32(mHandle>>32)/REGION_WIDTH_UNITS, U32(mHandle)/REGION_WIDTH_UNITS );
|
||||
|
||||
LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */
|
||||
if (!fp)
|
||||
if(LLVOCache::hasInstance())
|
||||
{
|
||||
llwarns << "Unable to write cache file " << filename << llendl;
|
||||
return;
|
||||
LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ;
|
||||
mCacheDirty = FALSE;
|
||||
}
|
||||
|
||||
// write out zero to indicate a version cache file
|
||||
U32 zero = 0;
|
||||
if (fwrite(&zero, sizeof(U32), 1, fp) != 1)
|
||||
for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter)
|
||||
{
|
||||
llwarns << "Short write" << llendl;
|
||||
delete iter->second;
|
||||
}
|
||||
|
||||
// write out version number
|
||||
U32 version = INDRA_OBJECT_CACHE_VERSION;
|
||||
if (fwrite(&version, sizeof(U32), 1, fp) != 1)
|
||||
{
|
||||
llwarns << "Short write" << llendl;
|
||||
}
|
||||
|
||||
// write the cache id for this sim
|
||||
if (fwrite(&mCacheID.mData, 1, UUID_BYTES, fp) != (size_t)UUID_BYTES)
|
||||
{
|
||||
llwarns << "Short write" << llendl;
|
||||
}
|
||||
|
||||
if (fwrite(&num_entries, sizeof(S32), 1, fp) != 1)
|
||||
{
|
||||
llwarns << "Short write" << llendl;
|
||||
}
|
||||
|
||||
LLVOCacheEntry *entry;
|
||||
|
||||
for (entry = mCacheStart.getNext(); entry && (entry != &mCacheEnd); entry = entry->getNext())
|
||||
{
|
||||
entry->writeToFile(fp);
|
||||
}
|
||||
|
||||
mCacheMap.clear();
|
||||
mCacheEnd.unlink();
|
||||
mCacheEnd.init();
|
||||
mCacheStart.deleteAll();
|
||||
mCacheStart.init();
|
||||
|
||||
fclose(fp);
|
||||
mImpl->mCacheMap.clear();
|
||||
}
|
||||
|
||||
void LLViewerRegion::sendMessage()
|
||||
{
|
||||
gMessageSystem->sendMessage(mHost);
|
||||
gMessageSystem->sendMessage(mImpl->mHost);
|
||||
}
|
||||
|
||||
void LLViewerRegion::sendReliableMessage()
|
||||
{
|
||||
gMessageSystem->sendReliable(mHost);
|
||||
gMessageSystem->sendReliable(mImpl->mHost);
|
||||
}
|
||||
|
||||
void LLViewerRegion::setFlags(BOOL b, U32 flags)
|
||||
@@ -448,12 +433,12 @@ void LLViewerRegion::setFlags(BOOL b, U32 flags)
|
||||
|
||||
void LLViewerRegion::setWaterHeight(F32 water_level)
|
||||
{
|
||||
mLandp->setWaterHeight(water_level);
|
||||
mImpl->mLandp->setWaterHeight(water_level);
|
||||
}
|
||||
|
||||
F32 LLViewerRegion::getWaterHeight() const
|
||||
{
|
||||
return mLandp->getWaterHeight();
|
||||
return mImpl->mLandp->getWaterHeight();
|
||||
}
|
||||
|
||||
BOOL LLViewerRegion::isVoiceEnabled() const
|
||||
@@ -469,9 +454,9 @@ void LLViewerRegion::setRegionFlags(U32 flags)
|
||||
|
||||
void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global)
|
||||
{
|
||||
mOriginGlobal = origin_global;
|
||||
mImpl->mOriginGlobal = origin_global;
|
||||
updateRenderMatrix();
|
||||
mLandp->setOriginGlobal(origin_global);
|
||||
mImpl->mLandp->setOriginGlobal(origin_global);
|
||||
mWind.setOriginGlobal(origin_global);
|
||||
mCloudLayer.setOriginGlobal(origin_global);
|
||||
calculateCenterGlobal();
|
||||
@@ -487,16 +472,34 @@ void LLViewerRegion::setTimeDilation(F32 time_dilation)
|
||||
mTimeDilation = time_dilation;
|
||||
}
|
||||
|
||||
const LLVector3d & LLViewerRegion::getOriginGlobal() const
|
||||
{
|
||||
return mImpl->mOriginGlobal;
|
||||
}
|
||||
|
||||
LLVector3 LLViewerRegion::getOriginAgent() const
|
||||
{
|
||||
return gAgent.getPosAgentFromGlobal(mOriginGlobal);
|
||||
return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal);
|
||||
}
|
||||
|
||||
const LLVector3d & LLViewerRegion::getCenterGlobal() const
|
||||
{
|
||||
return mImpl->mCenterGlobal;
|
||||
}
|
||||
|
||||
LLVector3 LLViewerRegion::getCenterAgent() const
|
||||
{
|
||||
return gAgent.getPosAgentFromGlobal(mCenterGlobal);
|
||||
return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal);
|
||||
}
|
||||
|
||||
void LLViewerRegion::setOwner(const LLUUID& owner_id)
|
||||
{
|
||||
mImpl->mOwnerID = owner_id;
|
||||
}
|
||||
|
||||
const LLUUID& LLViewerRegion::getOwner() const
|
||||
{
|
||||
return mImpl->mOwnerID;
|
||||
}
|
||||
|
||||
void LLViewerRegion::setRegionNameAndZone (const std::string& name_zone)
|
||||
@@ -646,7 +649,10 @@ void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
|
||||
LLFloaterReporter::processRegionInfo(msg);
|
||||
}
|
||||
|
||||
|
||||
void LLViewerRegion::setCacheID(const LLUUID& id)
|
||||
{
|
||||
mImpl->mCacheID = id;
|
||||
}
|
||||
|
||||
S32 LLViewerRegion::renderPropertyLines()
|
||||
{
|
||||
@@ -673,7 +679,7 @@ void LLViewerRegion::dirtyHeights()
|
||||
BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
|
||||
{
|
||||
// did_update returns TRUE if we did at least one significant update
|
||||
BOOL did_update = mLandp->idleUpdate(max_update_time);
|
||||
BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time);
|
||||
|
||||
if (mParcelOverlay)
|
||||
{
|
||||
@@ -688,7 +694,7 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
|
||||
// As above, but forcibly do the update.
|
||||
void LLViewerRegion::forceUpdate()
|
||||
{
|
||||
mLandp->idleUpdate(0.f);
|
||||
mImpl->mLandp->idleUpdate(0.f);
|
||||
|
||||
if (mParcelOverlay)
|
||||
{
|
||||
@@ -698,17 +704,21 @@ void LLViewerRegion::forceUpdate()
|
||||
|
||||
void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction)
|
||||
{
|
||||
mLandp->connectNeighbor(neighborp->mLandp, direction);
|
||||
mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction);
|
||||
mCloudLayer.connectNeighbor(&(neighborp->mCloudLayer), direction);
|
||||
}
|
||||
|
||||
|
||||
void LLViewerRegion::disconnectAllNeighbors()
|
||||
{
|
||||
mLandp->disconnectAllNeighbors();
|
||||
mImpl->mLandp->disconnectAllNeighbors();
|
||||
mCloudLayer.disconnectAllNeighbors();
|
||||
}
|
||||
|
||||
LLVLComposition * LLViewerRegion::getComposition() const
|
||||
{
|
||||
return mImpl->mCompositionp;
|
||||
}
|
||||
|
||||
F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const
|
||||
{
|
||||
@@ -802,10 +812,10 @@ F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const
|
||||
|
||||
void LLViewerRegion::calculateCenterGlobal()
|
||||
{
|
||||
mCenterGlobal = mOriginGlobal;
|
||||
mCenterGlobal.mdV[VX] += 0.5 * mWidth;
|
||||
mCenterGlobal.mdV[VY] += 0.5 * mWidth;
|
||||
mCenterGlobal.mdV[VZ] = 0.5*mLandp->getMinZ() + mLandp->getMaxZ();
|
||||
mImpl->mCenterGlobal = mImpl->mOriginGlobal;
|
||||
mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth;
|
||||
mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth;
|
||||
mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ();
|
||||
}
|
||||
|
||||
void LLViewerRegion::calculateCameraDistance()
|
||||
@@ -821,8 +831,17 @@ U32 LLViewerRegion::getNetDetailsForLCD()
|
||||
std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion)
|
||||
{
|
||||
s << "{ ";
|
||||
s << region.mHost;
|
||||
s << region.mImpl->mHost;
|
||||
s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n";
|
||||
std::string name(region.getName()), zone(region.getZoning());
|
||||
if (! name.empty())
|
||||
{
|
||||
s << " mName = " << name << '\n';
|
||||
}
|
||||
if (! zone.empty())
|
||||
{
|
||||
s << " mZoning = " << zone << '\n';
|
||||
}
|
||||
s << "}";
|
||||
return s;
|
||||
}
|
||||
@@ -832,9 +851,9 @@ std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion)
|
||||
|
||||
void LLViewerRegion::updateNetStats()
|
||||
{
|
||||
F32 dt = mLastNetUpdate.getElapsedTimeAndResetF32();
|
||||
F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32();
|
||||
|
||||
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mHost);
|
||||
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost);
|
||||
if (!cdp)
|
||||
{
|
||||
mAlive = false;
|
||||
@@ -863,10 +882,10 @@ void LLViewerRegion::updateNetStats()
|
||||
|
||||
U32 LLViewerRegion::getPacketsLost() const
|
||||
{
|
||||
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mHost);
|
||||
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost);
|
||||
if (!cdp)
|
||||
{
|
||||
llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mHost << llendl;
|
||||
llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << llendl;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@@ -875,6 +894,16 @@ U32 LLViewerRegion::getPacketsLost() const
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerRegion::setHttpResponderPtrNULL()
|
||||
{
|
||||
mImpl->mHttpResponderPtr = NULL;
|
||||
}
|
||||
|
||||
const LLHTTPClient::ResponderPtr LLViewerRegion::getHttpResponderPtr() const
|
||||
{
|
||||
return mImpl->mHttpResponderPtr;
|
||||
}
|
||||
|
||||
BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const
|
||||
{
|
||||
LLVector3 pos_region = getPosRegionFromGlobal(point_global);
|
||||
@@ -901,7 +930,7 @@ BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const
|
||||
LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const
|
||||
{
|
||||
LLVector3 pos_region;
|
||||
pos_region.setVec(point_global - mOriginGlobal);
|
||||
pos_region.setVec(point_global - mImpl->mOriginGlobal);
|
||||
return pos_region;
|
||||
}
|
||||
|
||||
@@ -909,7 +938,7 @@ LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) c
|
||||
{
|
||||
LLVector3d pos_region_d;
|
||||
pos_region_d.setVec(pos_region);
|
||||
return pos_region_d + mOriginGlobal;
|
||||
return pos_region_d + mImpl->mOriginGlobal;
|
||||
}
|
||||
|
||||
LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const
|
||||
@@ -926,7 +955,7 @@ LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) cons
|
||||
|
||||
F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos)
|
||||
{
|
||||
return mLandp->resolveHeightRegion( region_pos );
|
||||
return mImpl->mLandp->resolveHeightRegion( region_pos );
|
||||
}
|
||||
|
||||
bool LLViewerRegion::isAlive()
|
||||
@@ -1078,7 +1107,7 @@ void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg)
|
||||
// treat the target specially for the map
|
||||
if(i == target_index)
|
||||
{
|
||||
LLVector3d global_pos(mOriginGlobal);
|
||||
LLVector3d global_pos(mImpl->mOriginGlobal);
|
||||
global_pos.mdV[VX] += (F64)(x_pos);
|
||||
global_pos.mdV[VY] += (F64)(y_pos);
|
||||
global_pos.mdV[VZ] += (F64)(z_pos) * 4.0;
|
||||
@@ -1113,12 +1142,12 @@ 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();
|
||||
|
||||
LLVOCacheEntry* entry = get_if_there(mCacheMap, local_id, (LLVOCacheEntry*)NULL);
|
||||
LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
@@ -1127,45 +1156,40 @@ 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);
|
||||
mCacheEnd.insert(*entry);
|
||||
mCacheMap[local_id] = entry;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we haven't seen this object before
|
||||
|
||||
// Create new entry and add to map
|
||||
if (mCacheEntriesCount > MAX_OBJECT_CACHE_ENTRIES)
|
||||
{
|
||||
entry = mCacheStart.getNext();
|
||||
mCacheMap.erase(entry->getLocalID());
|
||||
delete entry;
|
||||
mCacheEntriesCount--;
|
||||
}
|
||||
// Update the cache entry
|
||||
mImpl->mCacheMap.erase(local_id);
|
||||
delete entry;
|
||||
entry = new LLVOCacheEntry(local_id, crc, dp);
|
||||
|
||||
mCacheEnd.insert(*entry);
|
||||
mCacheMap[local_id] = entry;
|
||||
mCacheEntriesCount++;
|
||||
mImpl->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 (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
|
||||
{
|
||||
mImpl->mCacheMap.erase(mImpl->mCacheMap.begin());
|
||||
result = CACHE_UPDATE_REPLACED;
|
||||
|
||||
}
|
||||
entry = new LLVOCacheEntry(local_id, crc, dp);
|
||||
|
||||
mImpl->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);
|
||||
//llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18
|
||||
|
||||
LLVOCacheEntry* entry = get_if_there(mCacheMap, local_id, (LLVOCacheEntry*)NULL);
|
||||
LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
@@ -1174,19 +1198,23 @@ 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;
|
||||
}
|
||||
|
||||
@@ -1206,9 +1234,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++)
|
||||
@@ -1269,7 +1294,13 @@ void LLViewerRegion::requestCacheMisses()
|
||||
mCacheMissFull.reset();
|
||||
mCacheMissCRC.reset();
|
||||
|
||||
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()
|
||||
@@ -1286,9 +1317,10 @@ void LLViewerRegion::dumpCache()
|
||||
}
|
||||
|
||||
LLVOCacheEntry *entry;
|
||||
|
||||
for (entry = mCacheStart.getNext(); entry && (entry != &mCacheEnd); entry = entry->getNext())
|
||||
for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter)
|
||||
{
|
||||
entry = iter->second ;
|
||||
|
||||
S32 hits = entry->getHitCount();
|
||||
S32 changes = entry->getCRCChangeCount();
|
||||
|
||||
@@ -1299,7 +1331,7 @@ void LLViewerRegion::dumpCache()
|
||||
change_bin[changes]++;
|
||||
}
|
||||
|
||||
llinfos << "Count " << mCacheEntriesCount << llendl;
|
||||
llinfos << "Count " << mImpl->mCacheMap.size() << llendl;
|
||||
for (i = 0; i < BINS; i++)
|
||||
{
|
||||
llinfos << "Hits " << i << " " << hit_bin[i] << llendl;
|
||||
@@ -1419,7 +1451,7 @@ void LLViewerRegion::unpackRegionHandshake()
|
||||
|
||||
// Now that we have the name, we can load the cache file
|
||||
// off disk.
|
||||
loadCache();
|
||||
loadObjectCache();
|
||||
|
||||
// After loading cache, signal that simulator can start
|
||||
// sending data.
|
||||
@@ -1436,15 +1468,16 @@ void LLViewerRegion::unpackRegionHandshake()
|
||||
|
||||
void LLViewerRegion::setSeedCapability(const std::string& url)
|
||||
{
|
||||
if (getCapability("Seed") == url)
|
||||
if (getCapability("Seed") == url)
|
||||
{
|
||||
llwarns << "Ignoring duplicate seed capability" << llendl;
|
||||
return;
|
||||
// llwarns << "Ignoring duplicate seed capability" << llendl;
|
||||
return;
|
||||
}
|
||||
delete mEventPoll;
|
||||
mEventPoll = NULL;
|
||||
|
||||
mCapabilities.clear();
|
||||
delete mImpl->mEventPoll;
|
||||
mImpl->mEventPoll = NULL;
|
||||
|
||||
mImpl->mCapabilities.clear();
|
||||
setCapability("Seed", url);
|
||||
|
||||
LLSD capabilityNames = LLSD::emptyArray();
|
||||
@@ -1460,9 +1493,10 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
|
||||
capabilityNames.append("FetchInventory");
|
||||
capabilityNames.append("FetchInventoryDescendents");
|
||||
}
|
||||
capabilityNames.append("GetDisplayNames");
|
||||
capabilityNames.append("GetTexture");
|
||||
capabilityNames.append("GroupProposalBallot");
|
||||
capabilityNames.append("GetDisplayNames");
|
||||
|
||||
capabilityNames.append("HomeLocation");
|
||||
capabilityNames.append("MapLayer");
|
||||
capabilityNames.append("MapLayerGod");
|
||||
@@ -1480,8 +1514,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
|
||||
capabilityNames.append("SendPostcard");
|
||||
capabilityNames.append("SendUserReport");
|
||||
capabilityNames.append("SendUserReportWithScreenshot");
|
||||
capabilityNames.append("SetDisplayName");
|
||||
capabilityNames.append("ServerReleaseNotes");
|
||||
capabilityNames.append("SetDisplayName");
|
||||
capabilityNames.append("StartGroupProposal");
|
||||
capabilityNames.append("TextureStats");
|
||||
capabilityNames.append("UntrustedSimulatorMessage");
|
||||
@@ -1501,25 +1535,29 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
|
||||
|
||||
llinfos << "posting to seed " << url << llendl;
|
||||
|
||||
mHttpResponderPtr = BaseCapabilitiesComplete::build(this) ;
|
||||
LLHTTPClient::post(url, capabilityNames, mHttpResponderPtr);
|
||||
mImpl->mHttpResponderPtr = BaseCapabilitiesComplete::build(this) ;
|
||||
LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr);
|
||||
}
|
||||
|
||||
void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
|
||||
{
|
||||
if(name == "EventQueueGet")
|
||||
{
|
||||
delete mEventPoll;
|
||||
mEventPoll = NULL;
|
||||
mEventPoll = new LLEventPoll(url, getHost());
|
||||
delete mImpl->mEventPoll;
|
||||
mImpl->mEventPoll = NULL;
|
||||
mImpl->mEventPoll = new LLEventPoll(url, getHost());
|
||||
}
|
||||
else if(name == "UntrustedSimulatorMessage")
|
||||
{
|
||||
LLHTTPSender::setSender(mHost, new LLCapHTTPSender(url));
|
||||
LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
|
||||
}
|
||||
else
|
||||
{
|
||||
mCapabilities[name] = url;
|
||||
mImpl->mCapabilities[name] = url;
|
||||
if(name == "GetTexture")
|
||||
{
|
||||
mHttpUrl = url ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1530,8 +1568,8 @@ bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
|
||||
|
||||
std::string LLViewerRegion::getCapability(const std::string& name) const
|
||||
{
|
||||
CapabilityMap::const_iterator iter = mCapabilities.find(name);
|
||||
if(iter == mCapabilities.end())
|
||||
CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
|
||||
if(iter == mImpl->mCapabilities.end())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
@@ -1552,7 +1590,7 @@ void LLViewerRegion::logActiveCapabilities() const
|
||||
{
|
||||
int count = 0;
|
||||
CapabilityMap::const_iterator iter;
|
||||
for (iter = mCapabilities.begin(); iter != mCapabilities.end(); iter++, count++)
|
||||
for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count)
|
||||
{
|
||||
if (!iter->second.empty())
|
||||
{
|
||||
@@ -1564,9 +1602,9 @@ void LLViewerRegion::logActiveCapabilities() const
|
||||
|
||||
LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
|
||||
{
|
||||
if (type < mObjectPartition.size())
|
||||
if (type < mImpl->mObjectPartition.size())
|
||||
{
|
||||
return mObjectPartition[type];
|
||||
return mImpl->mObjectPartition[type];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1585,3 +1623,8 @@ void LLViewerRegion::showReleaseNotes()
|
||||
LLWeb::loadURL(url);
|
||||
mReleaseNotesRequested = FALSE;
|
||||
}
|
||||
|
||||
std::string LLViewerRegion::getDescription() const
|
||||
{
|
||||
return stringize(*this);
|
||||
}
|
||||
|
||||
@@ -42,18 +42,18 @@
|
||||
#include "llcloud.h"
|
||||
#include "llstat.h"
|
||||
#include "v3dmath.h"
|
||||
#include "llhost.h"
|
||||
#include "llstring.h"
|
||||
#include "llregionflags.h"
|
||||
#include "lluuid.h"
|
||||
#include "lldatapacker.h"
|
||||
#include "llvocache.h"
|
||||
#include "llweb.h"
|
||||
#include "llcapabilityprovider.h"
|
||||
#include "m4math.h" // LLMatrix4
|
||||
#include "llhttpclient.h"
|
||||
|
||||
// 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;
|
||||
@@ -66,8 +66,16 @@ class LLSurface;
|
||||
class LLVOCache;
|
||||
class LLVOCacheEntry;
|
||||
class LLSpatialPartition;
|
||||
class LLEventPump;
|
||||
//class LLCapabilityListener;
|
||||
class LLDataPacker;
|
||||
class LLDataPackerBinaryBuffer;
|
||||
class LLHost;
|
||||
class LLBBox;
|
||||
|
||||
class LLViewerRegion
|
||||
class LLViewerRegionImpl;
|
||||
|
||||
class LLViewerRegion: public LLCapabilityProvider // implements this interface
|
||||
{
|
||||
public:
|
||||
//MUST MATCH THE ORDER OF DECLARATION IN CONSTRUCTOR
|
||||
@@ -96,9 +104,8 @@ public:
|
||||
~LLViewerRegion();
|
||||
|
||||
// Call this after you have the region name and handle.
|
||||
void loadCache();
|
||||
|
||||
void saveCache();
|
||||
void loadObjectCache();
|
||||
void saveObjectCache();
|
||||
|
||||
void sendMessage(); // Send the current message to this region's simulator
|
||||
void sendReliableMessage(); // Send the current message to this region's simulator
|
||||
@@ -161,19 +168,19 @@ public:
|
||||
F32 getTimeDilation() const { return mTimeDilation; }
|
||||
|
||||
// Origin height is at zero.
|
||||
const LLVector3d &getOriginGlobal() const { return mOriginGlobal; }
|
||||
const LLVector3d &getOriginGlobal() const;
|
||||
LLVector3 getOriginAgent() const;
|
||||
|
||||
// Center is at the height of the water table.
|
||||
const LLVector3d &getCenterGlobal() const { return mCenterGlobal; }
|
||||
const LLVector3d &getCenterGlobal() const;
|
||||
LLVector3 getCenterAgent() const;
|
||||
|
||||
void setRegionNameAndZone(const std::string& name_and_zone);
|
||||
const std::string& getName() const { return mName; }
|
||||
const std::string& getZoning() const { return mZoning; }
|
||||
|
||||
void setOwner(const LLUUID& owner_id) { mOwnerID = owner_id; }
|
||||
const LLUUID& getOwner() const { return mOwnerID; }
|
||||
void setOwner(const LLUUID& owner_id);
|
||||
const LLUUID& getOwner() const;
|
||||
|
||||
// Is the current agent on the estate manager list for this region?
|
||||
void setIsEstateManager(BOOL b) { mIsEstateManager = b; }
|
||||
@@ -205,7 +212,7 @@ public:
|
||||
// can process the message.
|
||||
static void processRegionInfo(LLMessageSystem* msg, void**);
|
||||
|
||||
void setCacheID(const LLUUID& id) { mCacheID = id; }
|
||||
void setCacheID(const LLUUID& id);
|
||||
|
||||
F32 getWidth() const { return mWidth; }
|
||||
|
||||
@@ -221,27 +228,35 @@ public:
|
||||
|
||||
U32 getPacketsLost() const;
|
||||
|
||||
void setHttpResponderPtrNULL() {mHttpResponderPtr = NULL ;}
|
||||
const LLHTTPClient::ResponderPtr getHttpResponderPtr() const {return mHttpResponderPtr ;}
|
||||
void setHttpResponderPtrNULL();
|
||||
const LLHTTPClient::ResponderPtr getHttpResponderPtr() const;
|
||||
|
||||
// Get/set named capability URLs for this region.
|
||||
void setSeedCapability(const std::string& url);
|
||||
void setCapability(const std::string& name, const std::string& url);
|
||||
std::string getCapability(const std::string& name) const;
|
||||
static bool isSpecialCapabilityName(const std::string &name);
|
||||
void logActiveCapabilities() const;
|
||||
// implements LLCapabilityProvider
|
||||
virtual std::string getCapability(const std::string& name) const;
|
||||
|
||||
// has region received its final (not seed) capability list?
|
||||
bool capabilitiesReceived() const;
|
||||
void setCapabilitiesReceived(bool received);
|
||||
|
||||
const LLHost &getHost() const { return mHost; }
|
||||
static bool isSpecialCapabilityName(const std::string &name);
|
||||
void logActiveCapabilities() const;
|
||||
|
||||
/// Get LLEventPump on which we listen for capability requests
|
||||
/// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
|
||||
// LLEventPump& getCapAPI() const;
|
||||
|
||||
/// implements LLCapabilityProvider
|
||||
/*virtual*/ const LLHost& getHost() const;
|
||||
const U64 &getHandle() const { return mHandle; }
|
||||
|
||||
LLSurface &getLand() const { return *mLandp; }
|
||||
LLSurface &getLand() const;
|
||||
|
||||
// set and get the region id
|
||||
const LLUUID& getRegionID() const { return mRegionID; }
|
||||
void setRegionID(const LLUUID& region_id) { mRegionID = region_id; }
|
||||
const LLUUID& getRegionID() const;
|
||||
void setRegionID(const LLUUID& region_id);
|
||||
|
||||
BOOL pointInRegionGlobal(const LLVector3d &point_global) const;
|
||||
LLVector3 getPosRegionFromGlobal(const LLVector3d &point_global) const;
|
||||
@@ -249,7 +264,7 @@ public:
|
||||
LLVector3 getPosAgentFromRegion(const LLVector3 ®ion_pos) const;
|
||||
LLVector3d getPosGlobalFromRegion(const LLVector3 &offset) const;
|
||||
|
||||
LLVLComposition *getComposition() const { return mCompositionp; }
|
||||
LLVLComposition *getComposition() const;
|
||||
F32 getCompositionXY(const S32 x, const S32 y) const;
|
||||
|
||||
BOOL isOwnedSelf(const LLVector3& pos);
|
||||
@@ -263,10 +278,26 @@ public:
|
||||
F32 getLandHeightRegion(const LLVector3& region_pos);
|
||||
|
||||
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);
|
||||
|
||||
@@ -281,8 +312,14 @@ public:
|
||||
|
||||
// used by LCD to get details for debug screen
|
||||
U32 getNetDetailsForLCD();
|
||||
|
||||
/// implements LLCapabilityProvider
|
||||
virtual std::string getDescription() const;
|
||||
std::string getHttpUrl() const { return mHttpUrl ;}
|
||||
|
||||
LLSpatialPartition* getSpatialPartition(U32 type);
|
||||
|
||||
bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;
|
||||
public:
|
||||
struct CompareDistance
|
||||
{
|
||||
@@ -319,34 +356,19 @@ public:
|
||||
LLDynamicArray<LLUUID> mMapAvatarIDs;
|
||||
|
||||
private:
|
||||
// The surfaces and other layers
|
||||
LLSurface* mLandp;
|
||||
LLViewerRegionImpl * mImpl;
|
||||
|
||||
// Region geometry data
|
||||
LLVector3d mOriginGlobal; // Location of southwest corner of region (meters)
|
||||
LLVector3d mCenterGlobal; // Location of center in world space (meters)
|
||||
F32 mWidth; // Width of region on a side (meters)
|
||||
|
||||
U64 mHandle;
|
||||
LLHost mHost;
|
||||
|
||||
// The unique ID for this region.
|
||||
LLUUID mRegionID;
|
||||
|
||||
F32 mTimeDilation; // time dilation of physics simulation on simulator
|
||||
|
||||
// simulator name
|
||||
std::string mName;
|
||||
std::string mZoning;
|
||||
|
||||
// region/estate owner - usually null.
|
||||
LLUUID mOwnerID;
|
||||
|
||||
// Is this agent on the estate managers list for this region?
|
||||
BOOL mIsEstateManager;
|
||||
|
||||
// Network statistics for the region's circuit...
|
||||
LLTimer mLastNetUpdate;
|
||||
U32 mPacketsIn;
|
||||
U32 mBitsIn;
|
||||
U32 mLastBitsIn;
|
||||
@@ -358,9 +380,6 @@ private:
|
||||
U32 mPingDelay;
|
||||
F32 mDeltaTime; // Time since last measurement of lastPackets, Bits, etc
|
||||
|
||||
// Misc
|
||||
LLVLComposition *mCompositionp; // Composition layer for the surface
|
||||
|
||||
U32 mRegionFlags; // includes damage flags
|
||||
U8 mSimAccess;
|
||||
F32 mBillableFactor;
|
||||
@@ -370,43 +389,24 @@ private:
|
||||
// Information for Homestead / CR-53
|
||||
S32 mClassID;
|
||||
S32 mCPURatio;
|
||||
|
||||
std::string mColoName;
|
||||
std::string mProductSKU;
|
||||
std::string mProductName;
|
||||
|
||||
std::string mHttpUrl ;
|
||||
|
||||
// Maps local ids to cache entries.
|
||||
// Regions can have order 10,000 objects, so assume
|
||||
// a structure of size 2^14 = 16,000
|
||||
BOOL mCacheLoaded;
|
||||
typedef std::map<U32, LLVOCacheEntry *> cache_map_t;
|
||||
cache_map_t mCacheMap;
|
||||
LLVOCacheEntry mCacheStart;
|
||||
LLVOCacheEntry mCacheEnd;
|
||||
U32 mCacheEntriesCount;
|
||||
BOOL mCacheDirty;
|
||||
|
||||
LLDynamicArray<U32> mCacheMissFull;
|
||||
LLDynamicArray<U32> mCacheMissCRC;
|
||||
// time?
|
||||
// LRU info?
|
||||
|
||||
// Cache ID is unique per-region, across renames, moving locations,
|
||||
// etc.
|
||||
LLUUID mCacheID;
|
||||
|
||||
typedef std::map<std::string, std::string> CapabilityMap;
|
||||
CapabilityMap mCapabilities;
|
||||
|
||||
LLEventPoll* mEventPoll;
|
||||
|
||||
private:
|
||||
bool mAlive; // can become false if circuit disconnects
|
||||
bool mCapabilitiesReceived;
|
||||
|
||||
//spatial partitions for objects in this region
|
||||
std::vector<LLSpatialPartition*> mObjectPartition;
|
||||
|
||||
LLHTTPClient::ResponderPtr mHttpResponderPtr ;
|
||||
|
||||
BOOL mReleaseNotesRequested;
|
||||
};
|
||||
|
||||
|
||||
@@ -35,54 +35,74 @@
|
||||
#include "llvocache.h"
|
||||
|
||||
#include "llerror.h"
|
||||
#include "llregionhandle.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes)
|
||||
{
|
||||
return apr_file->read(src, n_bytes) == n_bytes ;
|
||||
}
|
||||
|
||||
BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)
|
||||
{
|
||||
return apr_file->write(src, n_bytes) == n_bytes ;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
// LLVOCacheEntry
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp)
|
||||
:
|
||||
mLocalID(local_id),
|
||||
mCRC(crc),
|
||||
mHitCount(0),
|
||||
mDupeCount(0),
|
||||
mCRCChangeCount(0)
|
||||
{
|
||||
mLocalID = local_id;
|
||||
mCRC = crc;
|
||||
mHitCount = 0;
|
||||
mDupeCount = 0;
|
||||
mCRCChangeCount = 0;
|
||||
mBuffer = new U8[dp.getBufferSize()];
|
||||
mDP.assignBuffer(mBuffer, dp.getBufferSize());
|
||||
mDP = dp;
|
||||
mDP = dp; //memcpy
|
||||
}
|
||||
|
||||
LLVOCacheEntry::LLVOCacheEntry()
|
||||
:
|
||||
mLocalID(0),
|
||||
mCRC(0),
|
||||
mHitCount(0),
|
||||
mDupeCount(0),
|
||||
mCRCChangeCount(0),
|
||||
mBuffer(NULL)
|
||||
{
|
||||
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)
|
||||
LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
|
||||
: mBuffer(NULL)
|
||||
{
|
||||
if (fread(data, 1, nbytes, fp) != nbytes)
|
||||
S32 size = -1;
|
||||
BOOL success;
|
||||
|
||||
mDP.assignBuffer(mBuffer, 0);
|
||||
success = check_read(apr_file, &mLocalID, sizeof(U32));
|
||||
if(success)
|
||||
{
|
||||
llwarns << "Short read" << llendl;
|
||||
memset(data, 0, nbytes);
|
||||
success = check_read(apr_file, &mCRC, sizeof(U32));
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
if(success)
|
||||
{
|
||||
success = check_read(apr_file, &mHitCount, sizeof(S32));
|
||||
}
|
||||
if(success)
|
||||
{
|
||||
success = check_read(apr_file, &mDupeCount, sizeof(S32));
|
||||
}
|
||||
if(success)
|
||||
{
|
||||
success = check_read(apr_file, &mCRCChangeCount, sizeof(S32));
|
||||
}
|
||||
if(success)
|
||||
{
|
||||
success = check_read(apr_file, &size, sizeof(S32));
|
||||
|
||||
// Corruption in the cache entries
|
||||
if ((size > 10000) || (size < 1))
|
||||
@@ -90,24 +110,40 @@ LLVOCacheEntry::LLVOCacheEntry(LLFILE *fp)
|
||||
// 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;
|
||||
llwarns << "Bogus cache entry, size " << size << ", aborting!" << llendl;
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
if(success && size > 0)
|
||||
{
|
||||
mBuffer = new U8[size];
|
||||
success = check_read(apr_file, mBuffer, size);
|
||||
|
||||
if(success)
|
||||
{
|
||||
mDP.assignBuffer(mBuffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] mBuffer ;
|
||||
mBuffer = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
mBuffer = new U8[size];
|
||||
checkedRead(fp, mBuffer, size);
|
||||
mDP.assignBuffer(mBuffer, size);
|
||||
if(!success)
|
||||
{
|
||||
mLocalID = 0;
|
||||
mCRC = 0;
|
||||
mHitCount = 0;
|
||||
mDupeCount = 0;
|
||||
mCRCChangeCount = 0;
|
||||
mBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LLVOCacheEntry::~LLVOCacheEntry()
|
||||
{
|
||||
if(mBuffer)
|
||||
{
|
||||
delete [] mBuffer;
|
||||
}
|
||||
mDP.freeBuffer();
|
||||
}
|
||||
|
||||
|
||||
@@ -157,22 +193,564 @@ void LLVOCacheEntry::dump() const
|
||||
<< llendl;
|
||||
}
|
||||
|
||||
static inline void checkedWrite(LLFILE *fp, const void *data, size_t nbytes)
|
||||
BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
|
||||
{
|
||||
if (fwrite(data, 1, nbytes, fp) != nbytes)
|
||||
BOOL success;
|
||||
success = check_write(apr_file, (void*)&mLocalID, sizeof(U32));
|
||||
if(success)
|
||||
{
|
||||
llwarns << "Short write" << llendl;
|
||||
success = check_write(apr_file, (void*)&mCRC, sizeof(U32));
|
||||
}
|
||||
if(success)
|
||||
{
|
||||
success = check_write(apr_file, (void*)&mHitCount, sizeof(S32));
|
||||
}
|
||||
if(success)
|
||||
{
|
||||
success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32));
|
||||
}
|
||||
if(success)
|
||||
{
|
||||
success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32));
|
||||
}
|
||||
if(success)
|
||||
{
|
||||
S32 size = mDP.getBufferSize();
|
||||
success = check_write(apr_file, (void*)&size, sizeof(S32));
|
||||
|
||||
if(success)
|
||||
{
|
||||
success = check_write(apr_file, (void*)mBuffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
return success ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//LLVOCache
|
||||
//-------------------------------------------------------------------
|
||||
// Format string used to construct filename for the object cache
|
||||
static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc";
|
||||
|
||||
const U32 MAX_NUM_OBJECT_ENTRIES = 128 ;
|
||||
const U32 MIN_ENTRIES_TO_PURGE = 16 ;
|
||||
const U32 INVALID_TIME = 0 ;
|
||||
const char* object_cache_dirname = "objectcache";
|
||||
const char* header_filename = "object.cache";
|
||||
|
||||
LLVOCache* LLVOCache::sInstance = NULL;
|
||||
|
||||
//static
|
||||
LLVOCache* LLVOCache::getInstance()
|
||||
{
|
||||
if(!sInstance)
|
||||
{
|
||||
sInstance = new LLVOCache() ;
|
||||
}
|
||||
return sInstance ;
|
||||
}
|
||||
|
||||
//static
|
||||
BOOL LLVOCache::hasInstance()
|
||||
{
|
||||
return sInstance != NULL ;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVOCache::destroyClass()
|
||||
{
|
||||
if(sInstance)
|
||||
{
|
||||
delete sInstance ;
|
||||
sInstance = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
void LLVOCacheEntry::writeToFile(LLFILE *fp) const
|
||||
LLVOCache::LLVOCache():
|
||||
mInitialized(FALSE),
|
||||
mReadOnly(TRUE),
|
||||
mNumEntries(0),
|
||||
mCacheSize(1)
|
||||
{
|
||||
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);
|
||||
mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled");
|
||||
}
|
||||
|
||||
LLVOCache::~LLVOCache()
|
||||
{
|
||||
if(mEnabled)
|
||||
{
|
||||
writeCacheHeader();
|
||||
clearCacheInMemory();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVOCache::setDirNames(ELLPath location)
|
||||
{
|
||||
std::string delem = gDirUtilp->getDirDelimiter();
|
||||
|
||||
mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename);
|
||||
mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
|
||||
}
|
||||
|
||||
void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)
|
||||
{
|
||||
if(!mEnabled)
|
||||
{
|
||||
llwarns << "Not initializing cache: Cache is currently disabled." << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(mInitialized)
|
||||
{
|
||||
llwarns << "Cache already initialized." << llendl;
|
||||
return ;
|
||||
}
|
||||
mInitialized = TRUE ;
|
||||
|
||||
setDirNames(location);
|
||||
if (!mReadOnly)
|
||||
{
|
||||
LLFile::mkdir(mObjectCacheDirName);
|
||||
}
|
||||
mCacheSize = llclamp(size, MIN_ENTRIES_TO_PURGE, MAX_NUM_OBJECT_ENTRIES);
|
||||
mMetaInfo.mVersion = cache_version;
|
||||
readCacheHeader();
|
||||
|
||||
if(mMetaInfo.mVersion != cache_version)
|
||||
{
|
||||
mMetaInfo.mVersion = cache_version ;
|
||||
if(mReadOnly) //disable cache
|
||||
{
|
||||
clearCacheInMemory();
|
||||
}
|
||||
else //delete the current cache if the format does not match.
|
||||
{
|
||||
removeCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLVOCache::removeCache(ELLPath location)
|
||||
{
|
||||
if(mReadOnly)
|
||||
{
|
||||
llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
llinfos << "about to remove the object cache due to settings." << llendl ;
|
||||
|
||||
std::string mask = "*";
|
||||
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);
|
||||
|
||||
clearCacheInMemory();
|
||||
mInitialized = FALSE ;
|
||||
}
|
||||
|
||||
void LLVOCache::removeCache()
|
||||
{
|
||||
llassert_always(mInitialized) ;
|
||||
if(mReadOnly)
|
||||
{
|
||||
llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
llinfos << "about to remove the object cache due to some error." << llendl ;
|
||||
|
||||
std::string mask = "*";
|
||||
llinfos << "Removing cache at " << mObjectCacheDirName << llendl;
|
||||
gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask);
|
||||
|
||||
clearCacheInMemory() ;
|
||||
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())
|
||||
{
|
||||
mHandleEntryMap.erase(entry->mHandle) ;
|
||||
mHeaderEntryQueue.erase(iter) ;
|
||||
removeFromCache(entry) ;
|
||||
delete entry ;
|
||||
|
||||
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())
|
||||
{
|
||||
for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin(); iter != mHeaderEntryQueue.end(); ++iter)
|
||||
{
|
||||
delete *iter ;
|
||||
}
|
||||
mHeaderEntryQueue.clear();
|
||||
mHandleEntryMap.clear();
|
||||
mNumEntries = 0 ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename)
|
||||
{
|
||||
U32 region_x, region_y;
|
||||
|
||||
grid_from_region_handle(handle, ®ion_x, ®ion_y);
|
||||
filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname,
|
||||
llformat(OBJECT_CACHE_FILENAME, region_x, region_y));
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void LLVOCache::removeFromCache(HeaderEntryInfo* entry)
|
||||
{
|
||||
if(mReadOnly)
|
||||
{
|
||||
llwarns << "Not removing cache for handle " << entry->mHandle << ": Cache is currently in read-only mode." << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
std::string filename;
|
||||
getObjectCacheFilename(entry->mHandle, filename);
|
||||
LLAPRFile::remove(filename);
|
||||
entry->mTime = INVALID_TIME ;
|
||||
updateEntry(entry) ; //update the head file.
|
||||
}
|
||||
|
||||
void LLVOCache::readCacheHeader()
|
||||
{
|
||||
if(!mEnabled)
|
||||
{
|
||||
llwarns << "Not reading cache header: Cache is currently disabled." << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
//clear stale info.
|
||||
clearCacheInMemory();
|
||||
|
||||
bool success = true ;
|
||||
if (LLAPRFile::isExist(mHeaderFileName))
|
||||
{
|
||||
LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, LLAPRFile::local);
|
||||
|
||||
//read the meta element
|
||||
success = check_read(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ;
|
||||
|
||||
if(success)
|
||||
{
|
||||
HeaderEntryInfo* entry = NULL ;
|
||||
mNumEntries = 0 ;
|
||||
U32 num_read = 0 ;
|
||||
while(num_read++ < MAX_NUM_OBJECT_ENTRIES)
|
||||
{
|
||||
if(!entry)
|
||||
{
|
||||
entry = new HeaderEntryInfo() ;
|
||||
}
|
||||
success = check_read(&apr_file, entry, sizeof(HeaderEntryInfo));
|
||||
|
||||
if(!success) //failed
|
||||
{
|
||||
llwarns << "Error reading cache header entry. (entry_index=" << mNumEntries << ")" << llendl;
|
||||
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
|
||||
{
|
||||
writeCacheHeader() ;
|
||||
}
|
||||
|
||||
if(!success)
|
||||
{
|
||||
removeCache() ; //failed to read header, clear the cache
|
||||
}
|
||||
else if(mNumEntries >= mCacheSize)
|
||||
{
|
||||
purgeEntries(mCacheSize) ;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void LLVOCache::writeCacheHeader()
|
||||
{
|
||||
if (!mEnabled)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool success = true ;
|
||||
{
|
||||
LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, LLAPRFile::local);
|
||||
|
||||
//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)
|
||||
{
|
||||
(*iter)->mIndex = mNumEntries++ ;
|
||||
success = check_write(&apr_file, (void*)*iter, sizeof(HeaderEntryInfo));
|
||||
}
|
||||
|
||||
mNumEntries = mHeaderEntryQueue.size() ;
|
||||
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.
|
||||
success = check_write(&apr_file, entry, sizeof(HeaderEntryInfo)) ;
|
||||
|
||||
}
|
||||
delete entry ;
|
||||
}
|
||||
}
|
||||
|
||||
if(!success)
|
||||
{
|
||||
clearCacheInMemory() ;
|
||||
mReadOnly = TRUE ; //disable the cache.
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry)
|
||||
{
|
||||
LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY, LLAPRFile::local);
|
||||
apr_file.seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ;
|
||||
|
||||
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)
|
||||
{
|
||||
if(!mEnabled)
|
||||
{
|
||||
llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl;
|
||||
return ;
|
||||
}
|
||||
llassert_always(mInitialized);
|
||||
|
||||
handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
|
||||
if(iter == mHandleEntryMap.end()) //no cache
|
||||
{
|
||||
llwarns << "No handle map entry for " << handle << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
bool success = true ;
|
||||
{
|
||||
std::string filename;
|
||||
getObjectCacheFilename(handle, filename);
|
||||
LLAPRFile apr_file(filename, APR_READ|APR_BINARY, LLAPRFile::local);
|
||||
|
||||
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 ;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!success)
|
||||
{
|
||||
if(cache_entry_map.empty())
|
||||
{
|
||||
removeEntry(iter->second) ;
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void LLVOCache::purgeEntries(U32 size)
|
||||
{
|
||||
while(mHeaderEntryQueue.size() > size)
|
||||
{
|
||||
header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ;
|
||||
HeaderEntryInfo* entry = *iter ;
|
||||
mHandleEntryMap.erase(entry->mHandle);
|
||||
mHeaderEntryQueue.erase(iter) ;
|
||||
removeFromCache(entry) ;
|
||||
delete entry;
|
||||
}
|
||||
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) ;
|
||||
if(iter == mHandleEntryMap.end()) //new entry
|
||||
{
|
||||
if(mNumEntries >= mCacheSize - 1)
|
||||
{
|
||||
purgeEntries(mCacheSize - 1) ;
|
||||
}
|
||||
|
||||
entry = new HeaderEntryInfo();
|
||||
entry->mHandle = handle ;
|
||||
entry->mTime = time(NULL) ;
|
||||
entry->mIndex = mNumEntries++;
|
||||
mHeaderEntryQueue.insert(entry) ;
|
||||
mHandleEntryMap[handle] = entry ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update access time.
|
||||
entry = iter->second ;
|
||||
|
||||
//resort
|
||||
mHeaderEntryQueue.erase(entry) ;
|
||||
|
||||
entry->mTime = time(NULL) ;
|
||||
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
|
||||
bool success = true ;
|
||||
{
|
||||
std::string filename;
|
||||
getObjectCacheFilename(handle, filename);
|
||||
LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY, LLAPRFile::local);
|
||||
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!success)
|
||||
{
|
||||
removeEntry(entry) ;
|
||||
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,17 +36,18 @@
|
||||
#include "lluuid.h"
|
||||
#include "lldatapacker.h"
|
||||
#include "lldlinked.h"
|
||||
#include "lldir.h"
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Cache entries
|
||||
class LLVOCacheEntry;
|
||||
|
||||
class LLVOCacheEntry : public LLDLinked<LLVOCacheEntry>
|
||||
class LLVOCacheEntry
|
||||
{
|
||||
public:
|
||||
LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp);
|
||||
LLVOCacheEntry(LLFILE *fp);
|
||||
LLVOCacheEntry(LLAPRFile* apr_file);
|
||||
LLVOCacheEntry();
|
||||
~LLVOCacheEntry();
|
||||
|
||||
@@ -56,12 +57,15 @@ public:
|
||||
S32 getCRCChangeCount() const { return mCRCChangeCount; }
|
||||
|
||||
void dump() const;
|
||||
void writeToFile(LLFILE *fp) const;
|
||||
BOOL writeToFile(LLAPRFile* apr_file) const;
|
||||
void assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp);
|
||||
LLDataPackerBinaryBuffer *getDP(U32 crc);
|
||||
void recordHit();
|
||||
void recordDupe() { mDupeCount++; }
|
||||
|
||||
public:
|
||||
typedef std::map<U32, LLVOCacheEntry*> vocache_entry_map_t;
|
||||
|
||||
protected:
|
||||
U32 mLocalID;
|
||||
U32 mCRC;
|
||||
@@ -72,4 +76,86 @@ protected:
|
||||
U8 *mBuffer;
|
||||
};
|
||||
|
||||
//
|
||||
//Note: LLVOCache is not thread-safe
|
||||
//
|
||||
class LLVOCache
|
||||
{
|
||||
private:
|
||||
struct HeaderEntryInfo
|
||||
{
|
||||
HeaderEntryInfo() : mIndex(0), mHandle(0), mTime(0) {}
|
||||
S32 mIndex;
|
||||
U64 mHandle ;
|
||||
U32 mTime ;
|
||||
};
|
||||
|
||||
struct HeaderMetaInfo
|
||||
{
|
||||
HeaderMetaInfo() : mVersion(0){}
|
||||
|
||||
U32 mVersion;
|
||||
};
|
||||
|
||||
struct header_entry_less
|
||||
{
|
||||
bool operator()(const HeaderEntryInfo* lhs, const HeaderEntryInfo* rhs) const
|
||||
{
|
||||
if(lhs->mTime == rhs->mTime)
|
||||
{
|
||||
return lhs < rhs ;
|
||||
}
|
||||
|
||||
return lhs->mTime < rhs->mTime ; // older entry in front of queue (set)
|
||||
}
|
||||
};
|
||||
typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t;
|
||||
typedef std::map<U64, HeaderEntryInfo*> handle_entry_map_t;
|
||||
private:
|
||||
LLVOCache() ;
|
||||
|
||||
public:
|
||||
~LLVOCache() ;
|
||||
|
||||
void initCache(ELLPath location, U32 size, U32 cache_version) ;
|
||||
void removeCache(ELLPath location) ;
|
||||
|
||||
void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ;
|
||||
void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) ;
|
||||
void removeEntry(U64 handle) ;
|
||||
|
||||
void setReadOnly(BOOL read_only) {mReadOnly = read_only;}
|
||||
|
||||
private:
|
||||
void setDirNames(ELLPath location);
|
||||
// determine the cache filename for the region from the region handle
|
||||
void getObjectCacheFilename(U64 handle, std::string& filename);
|
||||
void removeFromCache(HeaderEntryInfo* entry);
|
||||
void readCacheHeader();
|
||||
void writeCacheHeader();
|
||||
void clearCacheInMemory();
|
||||
void removeCache() ;
|
||||
void removeEntry(HeaderEntryInfo* entry) ;
|
||||
void purgeEntries(U32 size);
|
||||
BOOL updateEntry(const HeaderEntryInfo* entry);
|
||||
|
||||
private:
|
||||
BOOL mEnabled;
|
||||
BOOL mInitialized ;
|
||||
BOOL mReadOnly ;
|
||||
HeaderMetaInfo mMetaInfo;
|
||||
U32 mCacheSize;
|
||||
U32 mNumEntries;
|
||||
std::string mHeaderFileName ;
|
||||
std::string mObjectCacheDirName;
|
||||
header_entry_queue_t mHeaderEntryQueue;
|
||||
handle_entry_map_t mHandleEntryMap;
|
||||
|
||||
static LLVOCache* sInstance ;
|
||||
public:
|
||||
static LLVOCache* getInstance() ;
|
||||
static BOOL hasInstance() ;
|
||||
static void destroyClass() ;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
#include "llworld.h"
|
||||
#include "llselectmgr.h"
|
||||
#include "pipeline.h"
|
||||
#include "llvocache.h"
|
||||
|
||||
// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d)
|
||||
#include "rlvhandler.h"
|
||||
// [/RLVa:KB]
|
||||
@@ -235,10 +237,12 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
|
||||
// Well, crap, there's something bogus in the data that we're unpacking.
|
||||
dp->dumpBufferToLog();
|
||||
llwarns << "Flushing cache files" << llendl;
|
||||
std::string mask;
|
||||
mask = gDirUtilp->getDirDelimiter() + "*.slc";
|
||||
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), mask);
|
||||
// llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl;
|
||||
|
||||
if(LLVOCache::hasInstance() && getRegion())
|
||||
{
|
||||
LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ;
|
||||
}
|
||||
|
||||
llwarns << "Bogus TE data in " << getID() << llendl;
|
||||
}
|
||||
else if (res2 & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "llviewerstats.h"
|
||||
#include "llvlcomposition.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llvocache.h"
|
||||
#include "llvowater.h"
|
||||
#include "message.h"
|
||||
#include "pipeline.h"
|
||||
@@ -129,6 +130,10 @@ void LLWorld::destroyClass()
|
||||
LLViewerRegion* region_to_delete = *region_it++;
|
||||
removeRegion(region_to_delete->getHost());
|
||||
}
|
||||
if(LLVOCache::hasInstance())
|
||||
{
|
||||
LLVOCache::getInstance()->destroyClass() ;
|
||||
}
|
||||
LLViewerPartSim::getInstance()->destroyClass();
|
||||
}
|
||||
|
||||
@@ -265,6 +270,7 @@ void LLWorld::removeRegion(const LLHost &host)
|
||||
llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl;
|
||||
LLAppViewer::instance()->forceDisconnect("You have been disconnected from the region you were in.");
|
||||
|
||||
regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -279,6 +285,10 @@ void LLWorld::removeRegion(const LLHost &host)
|
||||
delete regionp;
|
||||
|
||||
updateWaterObjects();
|
||||
|
||||
//double check all objects of this region are removed.
|
||||
gObjectList.clearAllMapObjectsInRegion(regionp) ;
|
||||
//llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -1386,17 +1396,17 @@ void send_agent_resume()
|
||||
LLAppViewer::instance()->resumeMainloopTimeout();
|
||||
}
|
||||
|
||||
static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin)
|
||||
{
|
||||
LLVector3d pos_global(region_origin);
|
||||
LLVector3d pos_local;
|
||||
|
||||
pos_local.mdV[VZ] = (compact_local & 0xFFU) * 4;
|
||||
pos_local.mdV[VY] = (compact_local >> 8) & 0xFFU;
|
||||
pos_local.mdV[VX] = (compact_local >> 16) & 0xFFU;
|
||||
|
||||
pos_global += pos_local;
|
||||
return pos_global;
|
||||
static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin)
|
||||
{
|
||||
LLVector3d pos_global(region_origin);
|
||||
LLVector3d pos_local;
|
||||
|
||||
pos_local.mdV[VZ] = (compact_local & 0xFFU) * 4;
|
||||
pos_local.mdV[VY] = (compact_local >> 8) & 0xFFU;
|
||||
pos_local.mdV[VX] = (compact_local >> 16) & 0xFFU;
|
||||
|
||||
pos_global += pos_local;
|
||||
return pos_global;
|
||||
}
|
||||
|
||||
void LLWorld::getAvatars(std::vector<LLUUID>* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const
|
||||
|
||||
Reference in New Issue
Block a user