diff options
Diffstat (limited to 'indra/newview')
44 files changed, 851 insertions, 191 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b5cb067061..8e006001b4 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 @@ -1545,7 +1547,7 @@ if (WINDOWS) ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecsd4.dll SLPlugin media_plugin_quicktime - media_plugin_webkit + #media_plugin_webkit winmm_shim windows-crash-logger windows-updater 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..fab6343864 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" @@ -89,10 +90,12 @@ // Linden library includes #include "llavatarnamecache.h" +#include "lldiriterator.h" #include "llimagej2c.h" #include "llmemory.h" #include "llprimitive.h" #include "llurlaction.h" +#include "llurlentry.h" #include "llvfile.h" #include "llvfsthread.h" #include "llvolumemgr.h" @@ -666,6 +669,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 +996,8 @@ bool LLAppViewer::init() LLAgentLanguage::init(); + + return true; } @@ -1709,6 +1718,10 @@ bool LLAppViewer::cleanup() } LLMetricPerformanceTesterBasic::cleanClass() ; +#if LL_RECORD_VIEWER_STATS + LLViewerStatsRecorder::cleanupClass(); +#endif + llinfos << "Cleaning up Media and Textures" << llendflush; //Note: @@ -3290,7 +3303,9 @@ void LLAppViewer::migrateCacheDirectory() S32 file_count = 0; std::string file_name; std::string mask = delimiter + "*.*"; - while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name)) + + LLDirIterator iter(old_cache_dir, mask); + while (iter.next(file_name)) { if (file_name == "." || file_name == "..") continue; std::string source_path = old_cache_dir + delimiter + file_name; @@ -3509,7 +3524,8 @@ bool LLAppViewer::initCache() dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""); std::string found_file; - if (gDirUtilp->getNextFileInDir(dir, mask, found_file)) + LLDirIterator iter(dir, mask); + if (iter.next(found_file)) { old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file; @@ -4567,6 +4583,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/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 898cc1c0ba..fc7a27e5e0 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -30,6 +30,7 @@ #include "llcommandlineparser.h" +#include "lldiriterator.h" #include "llmemtype.h" #include "llurldispatcher.h" // SLURL from other app instance #include "llviewernetwork.h" @@ -504,7 +505,9 @@ std::string LLAppViewerLinux::generateSerialNumber() // trawl /dev/disk/by-uuid looking for a good-looking UUID to grab std::string this_name; - while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name)) + + LLDirIterator iter(uuiddir, "*"); + while (iter.next(this_name)) { if (this_name.length() > best.length() || (this_name.length() == best.length() && diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 11b3379814..182d3d23f1 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -35,6 +35,7 @@ #include "llfloateruipreview.h" // Own header // Internal utility +#include "lldiriterator.h" #include "lleventtimer.h" #include "llexternaleditor.h" #include "llrender.h" @@ -481,9 +482,11 @@ BOOL LLFloaterUIPreview::postBuild() std::string language_directory; std::string xui_dir = get_xui_dir(); // directory containing localizations -- don't forget trailing delim mLanguageSelection->removeall(); // clear out anything temporarily in list from XML + + LLDirIterator iter(xui_dir, "*"); while(found) // for every directory { - if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", language_directory))) // get next directory + if((found = iter.next(language_directory))) // get next directory { std::string full_path = xui_dir + language_directory; if(LLFile::isfile(full_path.c_str())) // if it's not a directory, skip it @@ -635,42 +638,51 @@ void LLFloaterUIPreview::refreshList() mFileList->clearRows(); // empty list std::string name; BOOL found = TRUE; + + LLDirIterator floater_iter(getLocalizedDirectory(), "floater_*.xml"); while(found) // for every floater file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", name))) // get next file matching pattern + if((found = floater_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } } found = TRUE; + + LLDirIterator inspect_iter(getLocalizedDirectory(), "inspect_*.xml"); while(found) // for every inspector file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name))) // get next file matching pattern + if((found = inspect_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } } found = TRUE; + + LLDirIterator menu_iter(getLocalizedDirectory(), "menu_*.xml"); while(found) // for every menu file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name))) // get next file matching pattern + if((found = menu_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } } found = TRUE; + + LLDirIterator panel_iter(getLocalizedDirectory(), "panel_*.xml"); while(found) // for every panel file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", name))) // get next file matching pattern + if((found = panel_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } } - found = TRUE; + + LLDirIterator sidepanel_iter(getLocalizedDirectory(), "sidepanel_*.xml"); while(found) // for every sidepanel file that matches the pattern { - if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name))) // get next file matching pattern + if((found = sidepanel_iter.next(name))) // get next file matching pattern { addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) } diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 7546c070ea..ce936a9924 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -52,6 +52,7 @@ #include <boost/regex.hpp> #if LL_MSVC +#pragma warning(push) // disable boost::lexical_cast warning #pragma warning (disable:4702) #endif 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/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/lllogchat.cpp b/indra/newview/lllogchat.cpp index 9adf374c71..efc4e23838 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -32,6 +32,7 @@ #include "lltrans.h" #include "llviewercontrol.h" +#include "lldiriterator.h" #include "llinstantmessage.h" #include "llsingleton.h" // for LLSingleton @@ -41,6 +42,7 @@ #include <boost/regex/v4/match_results.hpp> #if LL_MSVC +#pragma warning(push) // disable warning about boost::lexical_cast unreachable code // when it fails to parse the string #pragma warning (disable:4702) @@ -601,7 +603,8 @@ std::string LLLogChat::oldLogFileName(std::string filename) //LL_INFOS("") << "Checking:" << directory << " for " << pattern << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ std::vector<std::string> allfiles; - while (gDirUtilp->getNextFileInDir(directory, pattern, scanResult)) + LLDirIterator iter(directory, pattern); + while (iter.next(scanResult)) { //LL_INFOS("") << "Found :" << scanResult << LL_ENDL; allfiles.push_back(scanResult); diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index c10c21683b..9346e48d1e 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -1323,19 +1323,19 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id) void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list) { + void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back; if (mInventoryItemsPanel->getVisible()) { std::set<LLUUID> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList(); - std::for_each(item_set.begin(), item_set.end(), boost::bind( &uuid_vec_t::push_back, &uuid_list, _1)); + std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, _1)); } else if (mWearablesListViewPanel->getVisible()) { std::vector<LLSD> item_set; mWearableItemsList->getSelectedValues(item_set); - std::for_each(item_set.begin(), item_set.end(), boost::bind( &uuid_vec_t::push_back, &uuid_list, boost::bind(&LLSD::asUUID, _1 ))); - + std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, boost::bind(&LLSD::asUUID, _1 ))); } // return selected_id; 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/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index d3b6dcd86f..8a0d0a6623 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -54,6 +54,7 @@ #include "llfilepicker.h" #include "llnotifications.h" +#include "lldiriterator.h" #include "llevent.h" // LLSimpleListener #include "llnotificationsutil.h" #include "lluuid.h" @@ -1115,7 +1116,8 @@ void LLViewerMedia::clearAllCookies() } // the hard part: iterate over all user directories and delete the cookie file from each one - while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename)) + LLDirIterator dir_iter(base_dir, "*_*"); + while (dir_iter.next(filename)) { target = base_dir; target += filename; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 60b118284b..7cc04e0338 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -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; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 18d6e4c8c8..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) { @@ -5403,6 +5405,26 @@ void LLViewerObject::setAttachmentItemID(const LLUUID &id) mAttachmentItemID = id; } +EObjectUpdateType LLViewerObject::getLastUpdateType() const +{ + return mLastUpdateType; +} + +void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type) +{ + mLastUpdateType = last_update_type; +} + +BOOL LLViewerObject::getLastUpdateCached() const +{ + return mLastUpdateCached; +} + +void LLViewerObject::setLastUpdateCached(BOOL last_update_cached) +{ + mLastUpdateCached = last_update_cached; +} + const LLUUID &LLViewerObject::extractAttachmentItemID() { LLUUID item_id = LLUUID::null; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 5c1a34d555..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; @@ -693,8 +694,15 @@ public: const LLUUID &getAttachmentItemID() const; void setAttachmentItemID(const LLUUID &id); const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object + EObjectUpdateType getLastUpdateType() const; + void setLastUpdateType(EObjectUpdateType last_update_type); + BOOL getLastUpdateCached() const; + void setLastUpdateCached(BOOL last_update_cached); + private: LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory. + EObjectUpdateType mLastUpdateType; + BOOL mLastUpdateCached; }; /////////////////// 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/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 2a67d12b64..3b2cfe656f 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() diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 3d3f1d62a6..7c6559203e 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -51,7 +51,7 @@ // Surface id's #define LAND 1 #define WATER 2 -const U32 MAX_OBJECT_CACHE_ENTRIES = 10000; +const U32 MAX_OBJECT_CACHE_ENTRIES = 50000; class LLEventPoll; @@ -275,9 +275,24 @@ public: void getInfo(LLSD& info); + typedef enum + { + CACHE_MISS_TYPE_FULL = 0, + CACHE_MISS_TYPE_CRC, + CACHE_MISS_TYPE_NONE + } eCacheMissType; + + typedef enum + { + CACHE_UPDATE_DUPE = 0, + CACHE_UPDATE_CHANGED, + CACHE_UPDATE_ADDED, + CACHE_UPDATE_REPLACED + } eCacheUpdateResult; + // handle a full update message - void cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp); - LLDataPacker *getDP(U32 local_id, U32 crc); + eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp); + LLDataPacker *getDP(U32 local_id, U32 crc, U8 &cache_miss_type); void requestCacheMisses(); void addCacheMissFull(const U32 local_id); 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/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/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index d239347810..4f6ec4ca61 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -33,6 +33,7 @@ #include "pipeline.h" #include "llsky.h" +#include "lldiriterator.h" #include "llfloaterreg.h" #include "llsliderctrl.h" #include "llspinctrl.h" @@ -85,11 +86,12 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name) std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", "")); LL_DEBUGS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL; - bool found = true; + bool found = true; + LLDirIterator app_settings_iter(path_name, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name); + found = app_settings_iter.next(name); if(found) { @@ -111,11 +113,12 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name) std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", "")); LL_DEBUGS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL; - found = true; + found = true; + LLDirIterator user_settings_iter(path_name2, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name); + found = user_settings_iter.next(name); if(found) { name=name.erase(name.length()-4); diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index e5f52dfc97..848efcbb49 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -31,6 +31,7 @@ #include "pipeline.h" #include "llsky.h" +#include "lldiriterator.h" #include "llfloaterreg.h" #include "llsliderctrl.h" #include "llspinctrl.h" @@ -100,11 +101,12 @@ void LLWLParamManager::loadPresets(const std::string& file_name) std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", "")); LL_DEBUGS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL; - bool found = true; + bool found = true; + LLDirIterator app_settings_iter(path_name, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name); + found = app_settings_iter.next(name); if(found) { @@ -126,11 +128,12 @@ void LLWLParamManager::loadPresets(const std::string& file_name) std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", "")); LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL; - found = true; + found = true; + LLDirIterator user_settings_iter(path_name2, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name); + found = user_settings_iter.next(name); if(found) { name=name.erase(name.length()-4); 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] +<nolink>[ITEMS]</nolink> 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] +<nolink>[ITEMS]</nolink> 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 3d500c2371..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 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] +<nolink>[ITEMS]</nolink> 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] +<nolink>[ITEMS]</nolink> 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] +<nolink>[ITEMS]</nolink> 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] +<nolink>[ITEMS]</nolink> 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] +<nolink>[ITEMS]</nolink> 次の住人と共有しますか: 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] +<nolink>[ITEMS]</nolink> 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 > 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] +<nolink>[ITEMS]</nolink> 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 { |