summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llaudio/llaudioengine.cpp6
-rw-r--r--indra/llcommon/llfile.cpp11
-rw-r--r--indra/llcommon/llfile.h2
-rw-r--r--indra/llmath/llbbox.cpp22
-rw-r--r--indra/llmath/llbbox.h4
-rw-r--r--indra/llmessage/llregionflags.h18
-rw-r--r--indra/llui/llfloater.cpp5
-rw-r--r--indra/llui/llmenugl.cpp4
-rw-r--r--indra/llui/llurlentry.cpp87
-rw-r--r--indra/llui/llurlentry.h39
-rw-r--r--indra/llui/tests/llurlentry_stub.cpp18
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llagent.cpp5
-rw-r--r--indra/newview/llappearancemgr.cpp12
-rw-r--r--indra/newview/llappviewer.cpp16
-rw-r--r--indra/newview/llinventoryfunctions.cpp6
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.cpp4
-rw-r--r--indra/newview/llinventoryobserver.cpp4
-rw-r--r--indra/newview/lllocationinputctrl.cpp4
-rw-r--r--indra/newview/llpanelme.cpp24
-rw-r--r--indra/newview/llpanelobjectinventory.cpp20
-rw-r--r--indra/newview/llremoteparcelrequest.cpp13
-rw-r--r--indra/newview/llsidetray.cpp4
-rw-r--r--indra/newview/llspatialpartition.cpp48
-rw-r--r--indra/newview/llstartup.cpp9
-rw-r--r--indra/newview/llviewerinventory.cpp8
-rw-r--r--indra/newview/llviewermenu.cpp12
-rw-r--r--indra/newview/llviewerobject.cpp51
-rw-r--r--indra/newview/llviewerobject.h17
-rw-r--r--indra/newview/llviewerobjectlist.cpp92
-rw-r--r--indra/newview/llviewerparceloverlay.cpp29
-rw-r--r--indra/newview/llviewerparceloverlay.h7
-rw-r--r--indra/newview/llviewerregion.cpp78
-rw-r--r--indra/newview/llviewerregion.h24
-rw-r--r--indra/newview/llviewerstatsrecorder.cpp258
-rw-r--r--indra/newview/llviewerstatsrecorder.h97
-rw-r--r--indra/newview/llvoavatar.cpp25
-rw-r--r--indra/newview/llvocache.cpp202
-rw-r--r--indra/newview/llvocache.h13
-rw-r--r--indra/newview/pipeline.h1
-rw-r--r--indra/newview/skins/default/colors.xml6
-rw-r--r--indra/newview/skins/default/xui/da/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/de/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_object.xml20
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml22
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_land_money.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/floater.xml1
-rw-r--r--indra/newview/skins/default/xui/es/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/it/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/notifications.xml4
-rw-r--r--indra/newview/tests/llremoteparcelrequest_test.cpp2
55 files changed, 1105 insertions, 277 deletions
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index c9cb1cd6e7..5e540ad8c5 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -97,7 +97,11 @@ void LLAudioEngine::setDefaults()
}
mMasterGain = 1.f;
- mInternalGain = 0.f;
+ // Setting mInternalGain to an out of range value fixes the issue reported in STORM-830.
+ // There is an edge case in setMasterGain during startup which prevents setInternalGain from
+ // being called if the master volume setting and mInternalGain both equal 0, so using -1 forces
+ // the if statement in setMasterGain to execute when the viewer starts up.
+ mInternalGain = -1.f;
mNextWindUpdate = 0.f;
mStreamingAudioImpl = NULL;
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index 8f02391e75..c32a776c3f 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -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
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 4913af7cb5..dd7d36513a 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -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);
diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp
index b46a6e03d2..3e2c05a6e6 100644
--- a/indra/llmath/llbbox.cpp
+++ b/indra/llmath/llbbox.cpp
@@ -89,6 +89,19 @@ void LLBBox::addBBoxAgent(const LLBBox& b)
}
}
+LLBBox LLBBox::getAxisAligned() const
+{
+ // no rotation = axis aligned rotation
+ LLBBox aligned(mPosAgent, LLQuaternion(), LLVector3(), LLVector3());
+
+ // add the center point so that it's not empty
+ aligned.addPointAgent(mPosAgent);
+
+ // add our BBox
+ aligned.addBBoxAgent(*this);
+
+ return aligned;
+}
void LLBBox::expand( F32 delta )
{
@@ -147,6 +160,15 @@ BOOL LLBBox::containsPointAgent(const LLVector3& p) const
return containsPointLocal(point_local);
}
+LLVector3 LLBBox::getMinAgent() const
+{
+ return localToAgent(mMinLocal);
+}
+
+LLVector3 LLBBox::getMaxAgent() const
+{
+ return localToAgent(mMaxLocal);
+}
/*
LLBBox operator*(const LLBBox &a, const LLMatrix4 &b)
diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h
index 5b911793f0..28e69b75e1 100644
--- a/indra/llmath/llbbox.h
+++ b/indra/llmath/llbbox.h
@@ -51,9 +51,11 @@ public:
const LLVector3& getPositionAgent() const { return mPosAgent; }
const LLQuaternion& getRotation() const { return mRotation; }
+ LLVector3 getMinAgent() const;
const LLVector3& getMinLocal() const { return mMinLocal; }
void setMinLocal( const LLVector3& min ) { mMinLocal = min; }
+ LLVector3 getMaxAgent() const;
const LLVector3& getMaxLocal() const { return mMaxLocal; }
void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; }
@@ -80,6 +82,8 @@ public:
LLVector3 localToAgentBasis(const LLVector3& v) const;
LLVector3 agentToLocalBasis(const LLVector3& v) const;
+ // Get the smallest possible axis aligned bbox that contains this bbox
+ LLBBox getAxisAligned() const;
// friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b);
diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h
index b9b974ec4f..7b796a0fa8 100644
--- a/indra/llmessage/llregionflags.h
+++ b/indra/llmessage/llregionflags.h
@@ -42,9 +42,6 @@ const U32 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3);
// Does the sun move?
const U32 REGION_FLAGS_SUN_FIXED = (1 << 4);
-// Tax free zone (no taxes on objects, land, etc.)
-const U32 REGION_FLAGS_TAX_FREE = (1 << 5);
-
// Can't change the terrain heightfield, even on owned parcels,
// but can plant trees and grass.
const U32 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6);
@@ -54,17 +51,12 @@ const U32 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7);
// All content wiped once per night
const U32 REGION_FLAGS_SANDBOX = (1 << 8);
-const U32 REGION_FLAGS_NULL_LAYER = (1 << 9);
-// const U32 REGION_FLAGS_SKIP_AGENT_ACTION = (1 << 10);
-const U32 REGION_FLAGS_HARD_ALLOW_LAND_TRANSFER = (1 << 10); // Region allows land reselling
-// const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11);
-const U32 REGION_FLAGS_HARD_ALLOW_POST_CLASSIFIED = (1 << 11); // Region allows posting of classified ads
const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies
const U32 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13);
const U32 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics
const U32 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15);
-//const U32 REGION_FLAGS_MAINLAND_VISIBLE = (1 << 16);
-const U32 REGION_FLAGS_PUBLIC_ALLOWED = (1 << 17);
+const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16);
+const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17);
const U32 REGION_FLAGS_BLOCK_DWELL = (1 << 18);
// Is flight allowed?
@@ -81,18 +73,13 @@ const U32 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21);
const U32 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22);
const U32 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23);
-// const U32 REGION_FLAGS_DENY_IDENTIFIED = (1 << 24);
-// const U32 REGION_FLAGS_DENY_TRANSACTED = (1 << 25);
const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26);
-// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR
-
const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28);
const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29);
const U32 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30);
-const U32 REGION_FLAGS_SKIP_MONO_SCRIPTS = (1 << 31);
const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |
REGION_FLAGS_ALLOW_SET_HOME |
@@ -105,7 +92,6 @@ const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK
| REGION_FLAGS_ALLOW_SET_HOME;
const U32 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE
- | REGION_FLAGS_PUBLIC_ALLOWED
| REGION_FLAGS_SUN_FIXED
| REGION_FLAGS_DENY_ANONYMOUS
| REGION_FLAGS_DENY_AGEUNVERIFIED;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index d30697e178..c425782715 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -272,9 +272,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
initFromParams(p);
- // chrome floaters don't take focus at all
- setFocusRoot(!getIsChrome());
-
initFloater(p);
}
@@ -2910,8 +2907,6 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
params.from_xui = true;
applyXUILayout(params, parent);
initFromParams(params);
- // chrome floaters don't take focus at all
- setFocusRoot(!getIsChrome());
initFloater(params);
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 6c0d47ef63..32d7be377a 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -1637,6 +1637,10 @@ LLMenuScrollItem::LLMenuScrollItem(const Params& p)
}
LLButton::Params bparams;
+
+ // Disabled the Return key handling by LLMenuScrollItem instead of
+ // passing the key press to the currently selected menu item. See STORM-385.
+ bparams.commit_on_return(false);
bparams.mouse_opaque(true);
bparams.scale_image(false);
bparams.click_callback(p.scroll_callback);
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 4f7b4be526..9db1feafd1 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -36,6 +36,7 @@
#include "llcachename.h"
#include "lltrans.h"
#include "lluicolortable.h"
+#include "message.h"
#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
@@ -684,8 +685,8 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa
LLStyle::Params LLUrlEntryGroup::getStyle() const
{
LLStyle::Params style_params = LLUrlEntryBase::getStyle();
- style_params.color = LLUIColorTable::instance().getColor("GroupLinkColor");
- style_params.readonly_color = LLUIColorTable::instance().getColor("GroupLinkColor");
+ style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
return style_params;
}
@@ -740,6 +741,13 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const
return LLUrlEntryBase::getLocation(url);
}
+// LLUrlEntryParcel statics.
+LLUUID LLUrlEntryParcel::sAgentID(LLUUID::null);
+LLUUID LLUrlEntryParcel::sSessionID(LLUUID::null);
+LLHost LLUrlEntryParcel::sRegionHost(LLHost::invalid);
+bool LLUrlEntryParcel::sDisconnected(false);
+std::set<LLUrlEntryParcel*> LLUrlEntryParcel::sParcelInfoObservers;
+
///
/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
@@ -751,13 +759,88 @@ LLUrlEntryParcel::LLUrlEntryParcel()
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_parcel.xml";
mTooltip = LLTrans::getString("TooltipParcelUrl");
+
+ sParcelInfoObservers.insert(this);
+}
+
+LLUrlEntryParcel::~LLUrlEntryParcel()
+{
+ sParcelInfoObservers.erase(this);
}
std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
+ LLSD path_array = LLURI(url).pathArray();
+ S32 path_parts = path_array.size();
+
+ if (path_parts < 3) // no parcel id
+ {
+ llwarns << "Failed to parse url [" << url << "]" << llendl;
+ return url;
+ }
+
+ std::string parcel_id_string = unescapeUrl(path_array[2]); // parcel id
+
+ // Add an observer to call LLUrlLabelCallback when we have parcel name.
+ addObserver(parcel_id_string, url, cb);
+
+ LLUUID parcel_id(parcel_id_string);
+
+ sendParcelInfoRequest(parcel_id);
+
return unescapeUrl(url);
}
+void LLUrlEntryParcel::sendParcelInfoRequest(const LLUUID& parcel_id)
+{
+ if (sRegionHost == LLHost::invalid || sDisconnected) return;
+
+ LLMessageSystem *msg = gMessageSystem;
+ msg->newMessage("ParcelInfoRequest");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, sAgentID );
+ msg->addUUID("SessionID", sSessionID);
+ msg->nextBlock("Data");
+ msg->addUUID("ParcelID", parcel_id);
+ msg->sendReliable(sRegionHost);
+}
+
+void LLUrlEntryParcel::onParcelInfoReceived(const std::string &id, const std::string &label)
+{
+ callObservers(id, label.empty() ? LLTrans::getString("RegionInfoError") : label, mIcon);
+}
+
+// static
+void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data)
+{
+ std::string label(LLStringUtil::null);
+ if (!parcel_data.name.empty())
+ {
+ label = parcel_data.name;
+ }
+ // If parcel name is empty use Sim_name (x, y, z) for parcel label.
+ else if (!parcel_data.sim_name.empty())
+ {
+ S32 region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS;
+ S32 region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS;
+ S32 region_z = llround(parcel_data.global_z);
+
+ label = llformat("%s (%d, %d, %d)",
+ parcel_data.sim_name.c_str(), region_x, region_y, region_z);
+ }
+
+ for (std::set<LLUrlEntryParcel*>::iterator iter = sParcelInfoObservers.begin();
+ iter != sParcelInfoObservers.end();
+ ++iter)
+ {
+ LLUrlEntryParcel* url_entry = *iter;
+ if (url_entry)
+ {
+ url_entry->onParcelInfoReceived(parcel_data.parcel_id.asString(), label);
+ }
+ }
+}
+
//
// LLUrlEntryPlace Describes secondlife://<location> URLs
//
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 1791739061..5f82721c0f 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -31,6 +31,9 @@
#include "lluuid.h"
#include "lluicolor.h"
#include "llstyle.h"
+
+#include "llhost.h" // for resolving parcel name by parcel id
+
#include <boost/signals2.hpp>
#include <boost/regex.hpp>
#include <string>
@@ -285,8 +288,44 @@ private:
class LLUrlEntryParcel : public LLUrlEntryBase
{
public:
+ struct LLParcelData
+ {
+ LLUUID parcel_id;
+ std::string name;
+ std::string sim_name;
+ F32 global_x;
+ F32 global_y;
+ F32 global_z;
+ };
+
LLUrlEntryParcel();
+ ~LLUrlEntryParcel();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+
+ // Sends a parcel info request to sim.
+ void sendParcelInfoRequest(const LLUUID& parcel_id);
+
+ // Calls observers of certain parcel id providing them with parcel label.
+ void onParcelInfoReceived(const std::string &id, const std::string &label);
+
+ // Processes parcel label and triggers notifying observers.
+ static void processParcelInfo(const LLParcelData& parcel_data);
+
+ // Next 4 setters are used to update agent and viewer connection information
+ // upon events like user login, viewer disconnect and user changing region host.
+ // These setters are made public to be accessible from newview and should not be
+ // used in other cases.
+ static void setAgentID(const LLUUID& id) { sAgentID = id; }
+ static void setSessionID(const LLUUID& id) { sSessionID = id; }
+ static void setRegionHost(const LLHost& host) { sRegionHost = host; }
+ static void setDisconnected(bool disconnected) { sDisconnected = disconnected; }
+
+private:
+ static LLUUID sAgentID;
+ static LLUUID sSessionID;
+ static LLHost sRegionHost;
+ static bool sDisconnected;
+ static std::set<LLUrlEntryParcel*> sParcelInfoObservers;
};
///
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index f30704cb22..96ebe83826 100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -30,6 +30,7 @@
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "lluuid.h"
+#include "message.h"
#include <string>
@@ -191,3 +192,20 @@ LLFontGL* LLFontGL::getFontDefault()
{
return NULL;
}
+
+char* _PREHASH_AgentData = "AgentData";
+char* _PREHASH_AgentID = "AgentID";
+
+LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS);
+
+LLMessageSystem* gMessageSystem = NULL;
+
+//
+// Stub implementation for LLMessageSystem
+//
+void LLMessageSystem::newMessage(const char *name) { }
+void LLMessageSystem::nextBlockFast(const char *blockname) { }
+void LLMessageSystem::nextBlock(const char *blockname) { }
+void LLMessageSystem::addUUIDFast( const char *varname, const LLUUID& uuid) { }
+void LLMessageSystem::addUUID( const char *varname, const LLUUID& uuid) { }
+S32 LLMessageSystem::sendReliable(const LLHost &host) { return 0; }
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index a61c35abd2..5d2342e925 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -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
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 77552663ab..7d908df5ce 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -64,6 +64,7 @@
#include "lltool.h"
#include "lltoolmgr.h"
#include "lltrans.h"
+#include "llurlentry.h"
#include "llviewercontrol.h"
#include "llviewerdisplay.h"
#include "llviewerjoystick.h"
@@ -649,6 +650,10 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
}
mRegionp = regionp;
+ // Pass the region host to LLUrlEntryParcel to resolve parcel name
+ // with a server request.
+ LLUrlEntryParcel::setRegionHost(getRegionHost());
+
// Must shift hole-covering water object locations because local
// coordinate frame changed.
LLWorld::getInstance()->updateWaterObjects();
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 80734b0d41..f40fed5ad3 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1300,8 +1300,16 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
return false;
}
- // Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes).
- return getCanMakeFolderIntoOutfit(outfit_cat_id);
+ // Check whether the outfit contains any wearables we aren't wearing already (STORM-702).
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
+ gInventory.collectDescendentsIf(outfit_cat_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_worn);
+ return items.size() > 0;
}
void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 3a98c23e05..80c752da9a 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -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"
@@ -93,6 +94,7 @@
#include "llmemory.h"
#include "llprimitive.h"
#include "llurlaction.h"
+#include "llurlentry.h"
#include "llvfile.h"
#include "llvfsthread.h"
#include "llvolumemgr.h"
@@ -666,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();
@@ -989,6 +995,8 @@ bool LLAppViewer::init()
LLAgentLanguage::init();
+
+
return true;
}
@@ -1709,6 +1717,10 @@ bool LLAppViewer::cleanup()
}
LLMetricPerformanceTesterBasic::cleanClass() ;
+#if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::cleanupClass();
+#endif
+
llinfos << "Cleaning up Media and Textures" << llendflush;
//Note:
@@ -4567,6 +4579,10 @@ void LLAppViewer::disconnectViewer()
cleanup_xfer_manager();
gDisconnected = TRUE;
+
+ // Pass the connection state to LLUrlEntryParcel not to attempt
+ // parcel info requests while disconnected.
+ LLUrlEntryParcel::setDisconnected(gDisconnected);
}
void LLAppViewer::forceErrorLLError()
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index ef20869114..61d0a150b7 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -686,6 +686,12 @@ bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* it
return false;
}
+ // Skip broken links.
+ if (vitem->getIsBrokenLink())
+ {
+ return false;
+ }
+
return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;
}
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index eab8f187a7..570e48d526 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -181,7 +181,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
if (mBackgroundFetchActive && gAgent.getRegion())
{
// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
- std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
+ std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");
if (!url.empty())
{
bulkFetch(url);
@@ -604,7 +604,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
}
if (body_lib["folders"].size())
{
- std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
+ std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);
LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0);
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 91ff8c7867..0fd4b2bee5 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -203,8 +203,8 @@ void fetch_items_from_llsd(const LLSD& items_llsd)
{
if (!items_llsd.size() || gDisconnected) return;
LLSD body;
- body[0]["cap_name"] = "FetchInventory";
- body[1]["cap_name"] = "FetchLib";
+ body[0]["cap_name"] = "FetchInventory2";
+ body[1]["cap_name"] = "FetchLib2";
for (S32 i=0; i<items_llsd.size();i++)
{
if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 1527f8f4c9..55164f6094 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -547,6 +547,10 @@ void LLLocationInputCtrl::onFocusLost()
{
LLUICtrl::onFocusLost();
refreshLocation();
+
+ // Setting cursor to 0 to show the left edge of the text. See STORM-370.
+ mTextEntry->setCursor(0);
+
if(mTextEntry->hasSelection()){
mTextEntry->deselect();
}
diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp
index 5ea94e0611..d3c9c3e131 100644
--- a/indra/newview/llpanelme.cpp
+++ b/indra/newview/llpanelme.cpp
@@ -76,17 +76,19 @@ void LLPanelMe::onOpen(const LLSD& key)
{
LLPanelProfile::onOpen(key);
- // Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068)
- bool opened = gSavedSettings.getBOOL("MePanelOpened");
- // In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this
- // is the last time onOpen() is called
- if( !opened && !LLSideTray::getInstance()->getCollapsed() )
- {
- buildEditPanel();
- openPanel(mEditPanel, getAvatarId());
-
- gSavedSettings.setBOOL("MePanelOpened", true);
- }
+ // Removed this action as per SOCIAL-431 The first time a new resident opens the profile tab
+ // in the sidebar, they see the old profile editing panel
+ //
+ //// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068)
+ //bool opened = gSavedSettings.getBOOL("MePanelOpened");
+ //// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this
+ //// is the last time onOpen() is called
+ //if( !opened && !LLSideTray::getInstance()->getCollapsed() )
+ //{
+ // buildEditPanel();
+ // openPanel(mEditPanel, getAvatarId());
+ // gSavedSettings.setBOOL("MePanelOpened", true);
+ //}
}
bool LLPanelMe::notifyChildren(const LLSD& info)
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index 211b9cf4b1..0b6267c9e6 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -766,22 +766,12 @@ BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
{
- const LLInventoryItem *inv = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mUUID));
- if (inv)
+ const LLInventoryObject* cat = object->getInventoryObject(mUUID);
+ if ( (cat) && (move_inv_category_world_to_agent(mUUID, LLUUID::null, FALSE)) )
{
- const LLPermissions& perm = inv->getPermissions();
- bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
- GP_OBJECT_MANIPULATE);
- if((can_copy && perm.allowTransferTo(gAgent.getID()))
- || object->permYouOwner())
-// || gAgent.isGodlike())
-
- {
- *type = LLViewerAssetType::lookupDragAndDropType(inv->getType());
-
- *id = inv->getUUID();
- return TRUE;
- }
+ *type = LLViewerAssetType::lookupDragAndDropType(cat->getType());
+ *id = mUUID;
+ return TRUE;
}
}
}
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index e5ef51bdd1..3862dac340 100644
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -33,6 +33,7 @@
#include "llpanel.h"
#include "llhttpclient.h"
#include "llsdserialize.h"
+#include "llurlentry.h"
#include "llviewerregion.h"
#include "llview.h"
@@ -168,6 +169,18 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v
{
observers.erase(*i);
}
+
+ LLUrlEntryParcel::LLParcelData url_data;
+ url_data.parcel_id = parcel_data.parcel_id;
+ url_data.name = parcel_data.name;
+ url_data.sim_name = parcel_data.sim_name;
+ url_data.global_x = parcel_data.global_x;
+ url_data.global_y = parcel_data.global_y;
+ url_data.global_z = parcel_data.global_z;
+
+ // Pass the parcel data to LLUrlEntryParcel to render
+ // human readable parcel name.
+ LLUrlEntryParcel::processParcelInfo(url_data);
}
void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id)
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index aef665a35c..19d1bdee86 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -498,8 +498,8 @@ private:
LLSideTray::Params::Params()
: collapsed("collapsed",false),
- tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("sidebar_tab_left.tga")),
- tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("button_enabled_selected_32x128.tga")),
+ tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Off.png")),
+ tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Selected.png")),
default_button_width("tab_btn_width",32),
default_button_height("tab_btn_height",32),
default_button_margin("tab_btn_margin",0)
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 960e72ee42..8adb8c30e0 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -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 |
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 611f9de2e6..5617eea4c3 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -139,6 +139,7 @@
#include "lltrans.h"
#include "llui.h"
#include "llurldispatcher.h"
+#include "llurlentry.h"
#include "llslurl.h"
#include "llurlhistory.h"
#include "llurlwhitelist.h"
@@ -2882,9 +2883,17 @@ bool process_login_success_response()
if(!text.empty()) gAgentID.set(text);
gDebugInfo["AgentID"] = text;
+ // Agent id needed for parcel info request in LLUrlEntryParcel
+ // to resolve parcel name.
+ LLUrlEntryParcel::setAgentID(gAgentID);
+
text = response["session_id"].asString();
if(!text.empty()) gAgentSessionID.set(text);
gDebugInfo["SessionID"] = text;
+
+ // Session id needed for parcel info request in LLUrlEntryParcel
+ // to resolve parcel name.
+ LLUrlEntryParcel::setSessionID(gAgentSessionID);
text = response["secure_session_id"].asString();
if(!text.empty()) gAgent.mSecureSessionID.set(text);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index b3642a2c1e..cc851e676b 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -366,11 +366,11 @@ void LLViewerInventoryItem::fetchFromServer(void) const
{
if(gAgent.getID() != mPermissions.getOwner())
{
- url = region->getCapability("FetchLib");
+ url = region->getCapability("FetchLib2");
}
else
{
- url = region->getCapability("FetchInventory");
+ url = region->getCapability("FetchInventory2");
}
}
else
@@ -648,7 +648,7 @@ bool LLViewerInventoryCategory::fetch()
std::string url;
if (gAgent.getRegion())
{
- url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
+ url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");
}
else
{
@@ -660,7 +660,7 @@ bool LLViewerInventoryCategory::fetch()
}
else
{ //Deprecated, but if we don't have a capability, use the old system.
- llinfos << "WebFetchInventoryDescendents capability not found. Using deprecated UDP message." << llendl;
+ llinfos << "FetchInventoryDescendents2 capability not found. Using deprecated UDP message." << llendl;
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("FetchInventoryDescendents");
msg->nextBlock("AgentData");
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 9e16bf2fbb..7cc04e0338 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -557,7 +557,7 @@ class LLAdvancedCheckConsole : public view_listener_t
new_value = get_visibility( (void*)gDebugView->mMemoryView );
}
#endif
-
+
return new_value;
}
};
@@ -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;
@@ -4197,9 +4201,9 @@ class LLObjectEnableReturn : public view_listener_t
{
virtual bool apply(LLViewerObject* obj)
{
- return (obj->isOverAgentOwnedLand() ||
- obj->isOverGroupOwnedLand() ||
- obj->permModify());
+ return
+ obj->permModify() ||
+ obj->isReturnable();
}
} func;
const bool firstonly = true;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1804fac1b3..48794c4c9d 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -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)
{
@@ -516,20 +518,23 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)
// This method returns true if the object is over land owned by the
// agent.
-BOOL LLViewerObject::isOverAgentOwnedLand() const
+bool LLViewerObject::isReturnable()
{
- return mRegionp
- && mRegionp->getParcelOverlay()
- && mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion());
-}
+ if (isAttachment())
+ {
+ return false;
+ }
+ std::vector<LLBBox> boxes;
+ boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned());
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned());
+ }
-// This method returns true if the object is over land owned by the
-// agent.
-BOOL LLViewerObject::isOverGroupOwnedLand() const
-{
- return mRegionp
- && mRegionp->getParcelOverlay()
- && mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
+ return mRegionp
+ && mRegionp->objectIsReturnable(getPositionRegion(), boxes);
}
BOOL LLViewerObject::setParent(LLViewerObject* parent)
@@ -5400,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;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index fe670f8827..614a5e59fa 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -77,6 +77,7 @@ typedef enum e_object_update_type
OUT_TERSE_IMPROVED,
OUT_FULL_COMPRESSED,
OUT_FULL_CACHED,
+ OUT_UNKNOWN,
} EObjectUpdateType;
@@ -226,12 +227,9 @@ public:
virtual BOOL hasLightTexture() const { return FALSE; }
// This method returns true if the object is over land owned by
- // the agent.
- BOOL isOverAgentOwnedLand() const;
-
- // True if over land owned by group of which the agent is
- // either officer or member.
- BOOL isOverGroupOwnedLand() const;
+ // the agent, one of its groups, or it encroaches and
+ // anti-encroachment is enabled
+ bool isReturnable();
/*
// This method will scan through this object, and then query the
@@ -696,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;
};
///////////////////
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index f5a32438cf..5849ab4307 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -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;
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index eee653b0c1..d07e06f6a7 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -145,6 +145,35 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const
return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay);
}
+bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const
+{
+ // boxes are expected to already be axis aligned
+ for (U32 i = 0; i < boxes.size(); ++i)
+ {
+ LLVector3 min = boxes[i].getMinAgent();
+ LLVector3 max = boxes[i].getMaxAgent();
+
+ S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+
+ for (S32 row = top; row <= bottom; row++)
+ {
+ for (S32 column = left; column <= right; column++)
+ {
+ U8 type = ownership(row, column);
+ if ((PARCEL_SELF == type)
+ || (PARCEL_GROUP == type))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const
{
S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index 61be220312..c80baedda6 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -30,6 +30,7 @@
// The ownership data for land parcels.
// One of these structures per region.
+#include "llbbox.h"
#include "lldarray.h"
#include "llframetimer.h"
#include "lluuid.h"
@@ -54,6 +55,12 @@ public:
BOOL isOwnedSelf(const LLVector3& pos) const;
BOOL isOwnedGroup(const LLVector3& pos) const;
BOOL isOwnedOther(const LLVector3& pos) const;
+
+ // "encroaches" means the prim hangs over the parcel, but its center
+ // might be in another parcel. for now, we simply test axis aligned
+ // bounding boxes which isn't perfect, but is close
+ bool encroachesOwned(const std::vector<LLBBox>& boxes) const;
+
BOOL isSoundLocal(const LLVector3& pos) const;
BOOL isBuildCameraAllowed(const LLVector3& pos) const;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 551ba18dd5..c7649001c5 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -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()
@@ -1372,11 +1379,12 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("DispatchRegionInfo");
capabilityNames.append("EstateChangeInfo");
capabilityNames.append("EventQueueGet");
- capabilityNames.append("FetchInventory");
capabilityNames.append("ObjectMedia");
capabilityNames.append("ObjectMediaNavigate");
- capabilityNames.append("FetchLib");
- capabilityNames.append("FetchLibDescendents");
+ capabilityNames.append("FetchLib2");
+ capabilityNames.append("FetchLibDescendents2");
+ capabilityNames.append("FetchInventory2");
+ capabilityNames.append("FetchInventoryDescendents2");
capabilityNames.append("GetDisplayNames");
capabilityNames.append("GetTexture");
capabilityNames.append("GroupProposalBallot");
@@ -1400,7 +1408,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("SendUserReportWithScreenshot");
capabilityNames.append("ServerReleaseNotes");
capabilityNames.append("SetDisplayName");
- capabilityNames.append("SimConsole");
capabilityNames.append("SimConsoleAsync");
capabilityNames.append("StartGroupProposal");
capabilityNames.append("TextureStats");
@@ -1417,7 +1424,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("ViewerMetrics");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
- capabilityNames.append("WebFetchInventoryDescendents");
// Please add new capabilities alphabetically to reduce
// merge conflicts.
@@ -1497,6 +1503,20 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
return NULL;
}
+// the viewer can not yet distinquish between normal- and estate-owned objects
+// so we collapse these two bits and enable the UI if either are set
+const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT
+ | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT;
+
+bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const
+{
+ return (mParcelOverlay != NULL)
+ && (mParcelOverlay->isOwnedSelf(pos)
+ || mParcelOverlay->isOwnedGroup(pos)
+ || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT)
+ && mParcelOverlay->encroachesOwned(boxes)) );
+}
+
void LLViewerRegion::showReleaseNotes()
{
std::string url = this->getCapability("ServerReleaseNotes");
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 8b71998f60..7c6559203e 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -33,6 +33,7 @@
#include "lldarray.h"
#include "llwind.h"
+#include "llbbox.h"
#include "llcloud.h"
#include "llstat.h"
#include "v3dmath.h"
@@ -50,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;
@@ -274,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);
@@ -293,6 +309,8 @@ public:
std::string getHttpUrl() const { return mHttpUrl ;}
LLSpatialPartition* getSpatialPartition(U32 type);
+
+ bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;
public:
struct CompareDistance
{
diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp
new file mode 100644
index 0000000000..e9d21b4848
--- /dev/null
+++ b/indra/newview/llviewerstatsrecorder.cpp
@@ -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
+
+
+
diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h
new file mode 100644
index 0000000000..612ac380f7
--- /dev/null
+++ b/indra/newview/llviewerstatsrecorder.h
@@ -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
+
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index bb4c5b1804..fd89044995 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2106,31 +2106,6 @@ void LLVOAvatar::computeBodySize()
gAgent.sendAgentSetAppearance();
}
}
-
-/* debug spam
- std::cout << "skull = " << skull << std::endl; // adebug
- std::cout << "head = " << head << std::endl; // adebug
- std::cout << "head_scale = " << head_scale << std::endl; // adebug
- std::cout << "neck = " << neck << std::endl; // adebug
- std::cout << "neck_scale = " << neck_scale << std::endl; // adebug
- std::cout << "chest = " << chest << std::endl; // adebug
- std::cout << "chest_scale = " << chest_scale << std::endl; // adebug
- std::cout << "torso = " << torso << std::endl; // adebug
- std::cout << "torso_scale = " << torso_scale << std::endl; // adebug
- std::cout << std::endl; // adebug
-
- std::cout << "pelvis_scale = " << pelvis_scale << std::endl;// adebug
- std::cout << std::endl; // adebug
-
- std::cout << "hip = " << hip << std::endl; // adebug
- std::cout << "hip_scale = " << hip_scale << std::endl; // adebug
- std::cout << "ankle = " << ankle << std::endl; // adebug
- std::cout << "ankle_scale = " << ankle_scale << std::endl; // adebug
- std::cout << "foot = " << foot << std::endl; // adebug
- std::cout << "mBodySize = " << mBodySize << std::endl; // adebug
- std::cout << "mPelvisToFoot = " << mPelvisToFoot << std::endl; // adebug
- std::cout << std::endl; // adebug
-*/
}
//------------------------------------------------------------------------
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 145ee31260..c26008d640 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -40,6 +40,7 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)
return apr_file->write(src, n_bytes) == n_bytes ;
}
+
//---------------------------------------------------------------------------
// LLVOCacheEntry
//---------------------------------------------------------------------------
@@ -212,8 +213,8 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
if(success)
{
success = check_write(apr_file, (void*)mBuffer, size);
+ }
}
-}
return success ;
}
@@ -224,7 +225,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;
+ }
+
+ if(mReadOnly)
+ {
+ llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl;
+ return;
+ }
- LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
+ 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)
- {
- header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ;
- HeaderEntryInfo* entry = *iter ;
+ 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_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;
}
}
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index ed2bc8bafe..e103007979 100644
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -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 ;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 3f785a99fe..cef3d87f36 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -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:
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 62441fd984..75aec21f93 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -115,9 +115,6 @@
name="AlertCautionTextColor"
reference="LtYellow" />
<color
- name="AgentLinkColor"
- reference="EmphasisColor" />
- <color
name="AlertTextColor"
value="0.58 0.66 0.84 1" />
<color
@@ -349,9 +346,6 @@
name="GridlineShadowColor"
value="0 0 0 0.31" />
<color
- name="GroupLinkColor"
- reference="White" />
- <color
name="GroupNotifyBoxColor"
value="0.3344 0.5456 0.5159 1" />
<color
diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml
index 70299c61b4..593e686d4c 100644
--- a/indra/newview/skins/default/xui/da/notifications.xml
+++ b/indra/newview/skins/default/xui/da/notifications.xml
@@ -1636,7 +1636,7 @@ Knappen vil blive vist når der er nok plads til den.
<notification name="ShareItemsConfirmation">
Er du sikker på at du vil dele følgende genstande:
-[ITEMS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
Med følgende beboere:
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index 06cc02cd84..a2d0b5a170 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -2747,7 +2747,7 @@ Die Schaltfläche wird angezeigt, wenn genügend Platz vorhanden ist.
<notification name="ShareItemsConfirmation">
Möchten Sie diese Objekte wirklich für andere freigeben:
-[ITEMS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
Für folgende Einwohner:
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
index c751aa4e0c..719509301b 100644
--- a/indra/newview/skins/default/xui/en/menu_object.xml
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -100,7 +100,7 @@
name="Object Attach HUD" />
</context_menu>
<context_menu
- label="Remove"
+ label="Manage"
name="Remove">
<menu_item_call
enabled="false"
@@ -129,15 +129,6 @@
<menu_item_call.on_enable
function="Object.EnableReturn" />
</menu_item_call>
- <menu_item_call
- enabled="false"
- label="Delete"
- name="Delete">
- <menu_item_call.on_click
- function="Object.Delete" />
- <menu_item_call.on_enable
- function="Object.EnableDelete" />
- </menu_item_call>
</context_menu>
<menu_item_separator layout="topleft" />
<menu_item_call
@@ -176,4 +167,13 @@
<menu_item_call.on_enable
function="Object.EnableBuy" />
</menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Delete"
+ name="Delete">
+ <menu_item_call.on_click
+ function="Object.Delete" />
+ <menu_item_call.on_enable
+ function="Object.EnableDelete" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index d997a262a8..2207e418c8 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2153,6 +2153,16 @@
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">
<menu_item_check.on_check
@@ -2717,6 +2727,18 @@
function="Floater.Toggle"
parameter="region_debug_console" />
</menu_item_check>
+ <menu_item_check
+ label="Region Debug Console"
+ name="Region Debug Console"
+ shortcut="control|shift|`"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="region_debug_console" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="region_debug_console" />
+ </menu_item_check>
<menu_item_separator />
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 3df53ac442..6f21938bdb 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6431,7 +6431,7 @@ Select residents to share with.
type="alertmodal">
Are you sure you want to share the following items:
-[ITEMS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
With the following Residents:
diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
index 61d6cbb2d0..eff674c628 100644
--- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
@@ -67,23 +67,23 @@
<scroll_list.columns
label="Parcel"
name="name"
- width="47" />
+ relative_width="0.2" />
<scroll_list.columns
label="Region"
name="location"
- width="47" />
+ relative_width="0.2" />
<scroll_list.columns
label="Type"
name="type"
- width="47" />
+ relative_width="0.2" />
<scroll_list.columns
label="Area"
name="area"
- width="47" />
+ relative_width="0.2" />
<scroll_list.columns
label="Hidden"
name="hidden"
- width="47" />
+ relative_width="0.2" />
</scroll_list>
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml
index 85d0c633af..2e5ebafe46 100644
--- a/indra/newview/skins/default/xui/en/widgets/floater.xml
+++ b/indra/newview/skins/default/xui/en/widgets/floater.xml
@@ -21,4 +21,5 @@
tear_off_pressed_image="tearoff_pressed.tga"
dock_pressed_image="Icon_Dock_Press"
help_pressed_image="Icon_Help_Press"
+ focus_root="true"
/>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 2dd7a6b0f5..14ce39e8fc 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -2734,7 +2734,7 @@ Se mostrará cuando haya suficiente espacio.
<notification name="ShareItemsConfirmation">
¿Estás seguro de que quieres compartir los elementos siguientes?
-[ITEMS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
Con los siguientes residentes:
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index ec362d7f22..f0b0e63af0 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -2730,7 +2730,7 @@ Le bouton sera affiché quand il y aura suffisamment de place.
<notification name="ShareItemsConfirmation">
Voulez-vous vraiment partager les articles suivants :
-[ITEMS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
avec les résidents suivants :
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index 32483881b2..5e53080c77 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -2679,7 +2679,7 @@ Il pulsante verrà visualizzato quando lo spazio sarà sufficiente.
<notification name="ShareItemsConfirmation">
Sei sicuro di volere condividere gli oggetti
-[ITEMS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
Con i seguenti residenti?
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index c0af0e03ff..f133bb361a 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -2731,7 +2731,7 @@ M キーを押して変更します。
<notification name="ShareItemsConfirmation">
次のアイテムを共有しますか:
-[ITEMS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
次の住人と共有しますか:
diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml
index 8151c7eb93..57a6b8b8ef 100644
--- a/indra/newview/skins/default/xui/pl/notifications.xml
+++ b/indra/newview/skins/default/xui/pl/notifications.xml
@@ -2691,7 +2691,7 @@ Przycisk zostanie wyświetlony w przypadku dostatecznej ilości przestrzeni.
<notification name="ShareItemsConfirmation">
Jesteś pewien/pewna, że chcesz udostępnić następujące obiekty:
-[ITEMS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
następującym Rezydentom:
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index dc38b740aa..a1855f2e89 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -477,7 +477,7 @@ Para aumentar a qualidade do vídeo, vá para Preferências &gt; Vídeo.
</notification>
<notification name="CannotCopyWarning">
Você não tem autorização para copiar os itens abaixo:
-[ITENS]
+[ITEMS]
ao dá-los, você ficará sem eles no seu inventário. Deseja realmente dar estes itens?
<usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/>
</notification>
@@ -2714,7 +2714,7 @@ O botão será exibido quando houver espaço suficente.
<notification name="ShareItemsConfirmation">
Tem certeza de que quer compartilhar os items abaixo?
-[ITENS]
+&lt;nolink&gt;[ITEMS]&lt;/nolink&gt;
Com os seguintes residentes:
diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
index dae22521bb..7862cce3a1 100644
--- a/indra/newview/tests/llremoteparcelrequest_test.cpp
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -32,6 +32,7 @@
#include "../llagent.h"
#include "message.h"
+#include "llurlentry.h"
namespace {
LLControlGroup s_saved_settings("dummy_settings");
@@ -72,6 +73,7 @@ LLUIColor::LLUIColor(void) { }
LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { }
LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }
LLControlGroup::~LLControlGroup(void) { }
+void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { }
namespace tut
{