summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rwxr-xr-xindra/newview/llappearancemgr.cpp90
-rwxr-xr-xindra/newview/llappearancemgr.h4
-rwxr-xr-xindra/newview/llinventorymodel.cpp172
-rwxr-xr-xindra/newview/llinventorymodel.h2
-rwxr-xr-xindra/newview/llviewerinventory.cpp78
-rwxr-xr-xindra/newview/llviewerinventory.h7
-rwxr-xr-xindra/newview/llviewerregion.cpp2
-rwxr-xr-xindra/newview/llviewerstats.cpp40
-rwxr-xr-xindra/newview/llviewerstats.h5
-rwxr-xr-xindra/newview/llvoavatar.cpp27
-rwxr-xr-xindra/newview/llvoavatar.h1
-rwxr-xr-xindra/newview/llvoavatarself.cpp12
12 files changed, 341 insertions, 99 deletions
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index d817f10aee..722587ec0e 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -397,6 +397,12 @@ public:
LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries)
{
addItems(src_items);
+ sInstanceCount++;
+ }
+
+ ~LLCallAfterInventoryCopyMgr()
+ {
+ sInstanceCount--;
}
virtual bool requestOperation(const LLUUID& item_id)
@@ -419,8 +425,15 @@ public:
);
return true;
}
+
+ static S32 getInstanceCount() { return sInstanceCount; }
+
+private:
+ static S32 sInstanceCount;
};
+S32 LLCallAfterInventoryCopyMgr::sInstanceCount = 0;
+
LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
bool enforce_item_restrictions,
bool enforce_ordering):
@@ -1609,25 +1622,6 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLIn
}
}
-void LLAppearanceMgr::removeCategoryContents(const LLUUID& category, bool keep_outfit_links,
- LLPointer<LLInventoryCallback> cb)
-{
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- gInventory.collectDescendents(category, cats, items,
- LLInventoryModel::EXCLUDE_TRASH);
- for (S32 i = 0; i < items.count(); ++i)
- {
- LLViewerInventoryItem *item = items.get(i);
- if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER))
- continue;
- if (item->getIsLinkType())
- {
- remove_inventory_item(item->getUUID(), cb);
- }
- }
-}
-
// Keep the last N wearables of each type. For viewer 2.0, N is 1 for
// both body parts and clothing items.
void LLAppearanceMgr::filterWearableItems(
@@ -1691,6 +1685,11 @@ void LLAppearanceMgr::removeAll(LLInventoryModel::item_array_t& items_to_kill,
void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
{
LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
+ if (!pcat)
+ {
+ llwarns << "no category found for id " << category << llendl;
+ return;
+ }
LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL;
const LLUUID cof = getCOF();
@@ -1756,6 +1755,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
// Will link all the above items.
LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
+#if 0
linkAll(cof,all_items,link_waiter);
// Add link to outfit if category is an outfit.
@@ -1772,7 +1772,37 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
// even in the non-append case, createBaseOutfitLink() already
// deletes the existing link, don't need to do it again here.
bool keep_outfit_links = true;
- removeCategoryContents(cof, keep_outfit_links, link_waiter);
+ remove_folder_contents(cof, keep_outfit_links, link_waiter);
+#else
+ LLSD contents = LLSD::emptyArray();
+ for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();
+ it != all_items.end(); ++it)
+ {
+ LLSD item_contents;
+ LLInventoryItem *item = *it;
+ item_contents["name"] = item->getName();
+ item_contents["desc"] = item->getActualDescription();
+ item_contents["linked_id"] = item->getLinkedUUID();
+ item_contents["type"] = LLAssetType::AT_LINK;
+ contents.append(item_contents);
+ }
+ const LLUUID& base_id = append ? getBaseOutfitUUID() : category;
+ LLViewerInventoryCategory *base_cat = gInventory.getCategory(base_id);
+ if (base_cat)
+ {
+ LLSD base_contents;
+ base_contents["name"] = base_cat->getName();
+ base_contents["desc"] = "";
+ base_contents["linked_id"] = base_cat->getLinkedUUID();
+ base_contents["type"] = LLAssetType::AT_LINK_FOLDER;
+ contents.append(base_contents);
+ }
+ if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+ {
+ dump_sequential_xml(gAgentAvatarp->getFullname() + "_slam_request", contents);
+ }
+ slam_inventory_folder(getCOF(), contents, link_waiter);
+#endif
LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
}
@@ -2154,6 +2184,11 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
category->getUUID(), copy, append));
}
+S32 LLAppearanceMgr::getActiveCopyOperations() const
+{
+ return LLCallAfterInventoryCopyMgr::getInstanceCount();
+}
+
void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
{
LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL;
@@ -2758,7 +2793,7 @@ bool LLAppearanceMgr::updateBaseOutfit()
updateClothingOrderingInfo();
// in a Base Outfit we do not remove items, only links
- removeCategoryContents(base_outfit_id, false, NULL);
+ remove_folder_contents(base_outfit_id, false, NULL);
LLPointer<LLInventoryCallback> dirty_state_updater =
new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
@@ -2918,7 +2953,7 @@ protected:
//LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL;
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{
- dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
+ dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
}
}
else
@@ -2936,7 +2971,7 @@ protected:
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{
const LLSD& content = getContent();
- dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
+ dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
debugCOF(content);
}
onFailure();
@@ -2960,15 +2995,6 @@ protected:
}
}
- void dumpContents(const std::string outprefix, const LLSD& content)
- {
- std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml");
- std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
- std::ofstream ofs(fullpath.c_str(), std::ios_base::out);
- ofs << LLSDOStreamer<LLSDXMLFormatter>(content, LLSDFormatter::OPTIONS_PRETTY);
- LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL;
- }
-
void debugCOF(const LLSD& content)
{
LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index b63e883426..9eb26767c4 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -71,6 +71,8 @@ public:
LLInventoryModel::item_array_t& items_to_kill);
void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
+ S32 getActiveCopyOperations() const;
+
// Copy all items and the src category itself.
void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
LLPointer<LLInventoryCallback> cb);
@@ -235,8 +237,6 @@ private:
LLInventoryModel::item_array_t& obj_items,
LLInventoryModel::item_array_t& gest_items);
- void removeCategoryContents(const LLUUID& category, bool keep_outfit_links,
- LLPointer<LLInventoryCallback> cb);
static void onOutfitRename(const LLSD& notification, const LLSD& response);
void setOutfitLocked(bool locked);
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 38fa3c36e3..c0c48d6695 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1170,79 +1170,193 @@ void parse_llsd_uuid_array(const LLSD& content, const std::string& name, uuid_ve
void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
{
- LL_DEBUGS("Inventory") << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl;
+ if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+ {
+ dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
+ }
+ // Track changes to descendent counts for accounting.
+ std::map<LLUUID,S32> cat_deltas;
+ typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t;
+ deferred_item_map_t items_created;
+ deferred_item_map_t items_updated;
+ std::set<LLUUID> objects_deleted;
+
+ // parse _categories_removed -> objects_deleted
uuid_vec_t cat_ids;
parse_llsd_uuid_array(update,"_categories_removed",cat_ids);
for (uuid_vec_t::const_iterator it = cat_ids.begin();
it != cat_ids.end(); ++it)
{
- onObjectDeletedFromServer(*it, false);
+ LLViewerInventoryCategory *cat = getCategory(*it);
+ cat_deltas[cat->getParentUUID()]--;
+ objects_deleted.insert(*it);
}
+ // parse _categories_items_removed -> objects_deleted
uuid_vec_t item_ids;
parse_llsd_uuid_array(update,"_category_items_removed",item_ids);
for (uuid_vec_t::const_iterator it = item_ids.begin();
it != item_ids.end(); ++it)
{
- onObjectDeletedFromServer(*it, false);
+ LLViewerInventoryItem *item = getItem(*it);
+ cat_deltas[item->getParentUUID()]--;
+ objects_deleted.insert(*it);
}
+ // parse _broken_links_removed -> objects_deleted
uuid_vec_t broken_link_ids;
parse_llsd_uuid_array(update,"_broken_links_removed",broken_link_ids);
for (uuid_vec_t::const_iterator it = broken_link_ids.begin();
it != broken_link_ids.end(); ++it)
{
- onObjectDeletedFromServer(*it, false);
+ LLViewerInventoryItem *item = getItem(*it);
+ cat_deltas[item->getParentUUID()]--;
+ objects_deleted.insert(*it);
}
- if (update.has("item_id"))
+ // parse _created_items
+ uuid_vec_t created_item_ids;
+ parse_llsd_uuid_array(update,"_created_items",created_item_ids);
+
+ if (update.has("_embedded"))
{
- // item has been modified or possibly created (would be better if we could distinguish these cases directly)
- LLUUID item_id = update["item_id"].asUUID();
- LLViewerInventoryItem *item = gInventory.getItem(item_id);
- LLViewerInventoryCategory *cat = gInventory.getCategory(item_id);
- if (item)
+ const LLSD& embedded = update["_embedded"];
+ for(LLSD::map_const_iterator it = embedded.beginMap(),
+ end = embedded.endMap();
+ it != end; ++it)
{
- LLSD changes;
- if (update.has("name") && update["name"] != item->getName())
+ const std::string& field = (*it).first;
+
+ // parse created links
+ if (field == "link")
{
- changes["name"] = update["name"];
- }
- if (update.has("desc") && update["desc"] != item->getActualDescription())
+ const LLSD& links = embedded["link"];
+ for(LLSD::map_const_iterator linkit = links.beginMap(),
+ linkend = links.endMap();
+ linkit != linkend; ++linkit)
+ {
+ const LLUUID link_id((*linkit).first);
+ const LLSD& link_map = (*linkit).second;
+ uuid_vec_t::const_iterator pos =
+ std::find(created_item_ids.begin(),
+ created_item_ids.end(),link_id);
+ if (pos != created_item_ids.end())
+ {
+ LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem);
+ BOOL rv = new_link->unpackMessage(link_map);
+ if (rv)
+ {
+ items_created[link_id] = new_link;
+ const LLUUID& parent_id = new_link->getParentUUID();
+ cat_deltas[parent_id]++;
+ }
+ else
+ {
+ llwarns << "failed to unpack" << llendl;
+ }
+ }
+ else
+ {
+ LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl;
+ }
+ }
+ }
+ else
{
- changes["desc"] = update["desc"];
+ llwarns << "unrecognized embedded field " << field << llendl;
}
- onItemUpdated(item_id,changes,true);
}
- else if (cat)
+
+ }
+
+ // Parse item update at the top level.
+ if (update.has("item_id"))
+ {
+ LLUUID item_id = update["item_id"].asUUID();
+ LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
+ BOOL rv = new_item->unpackMessage(update);
+ if (rv)
{
- llerrs << "don't handle cat update yet" << llendl;
+ items_updated[item_id] = new_item;
+ // This statement is here to cause a new entry with 0
+ // delta to be created if it does not already exist;
+ // otherwise has no effect.
+ cat_deltas[new_item->getParentUUID()];
}
else
{
- llerrs << "don't handle creation case yet" << llendl;
+ llerrs << "unpack failed" << llendl;
}
-
}
+ // Do descendent/version accounting.
+ // Can remove this if/when we use the version info directly.
+ for (std::map<LLUUID,S32>::const_iterator catit = cat_deltas.begin();
+ catit != cat_deltas.end(); ++catit)
+ {
+ const LLUUID cat_id(catit->first);
+ S32 delta = catit->second;
+ LLInventoryModel::LLCategoryUpdate up(cat_id, delta);
+ gInventory.accountForUpdate(up);
+ }
+
// TODO - how can we use this version info? Need to be sure all
// changes are going through AIS first, or at least through
// something with a reliable responder.
-#if 0
const std::string& ucv = "_updated_category_versions";
if (update.has(ucv))
{
for(LLSD::map_const_iterator it = update[ucv].beginMap(),
end = update[ucv].endMap();
- it != end; ++it)
+ it != end; ++it)
{
const LLUUID id((*it).first);
S32 version = (*it).second.asInteger();
+ LLViewerInventoryCategory *cat = gInventory.getCategory(id);
+ if (cat->getVersion() != version)
+ {
+ llwarns << "Possible version mismatch, viewer " << cat->getVersion()
+ << " server " << version << llendl;
+ }
}
}
-#endif
+
+ // CREATE ITEMS
+ for (deferred_item_map_t::const_iterator create_it = items_created.begin();
+ create_it != items_created.end(); ++create_it)
+ {
+ LLUUID item_id(create_it->first);
+ LLPointer<LLViewerInventoryItem> new_item = create_it->second;
+
+ // FIXME risky function since it calls updateServer() in some
+ // cases. Maybe break out the update/create cases, in which
+ // case this is create.
+ LL_DEBUGS("Inventory") << "created item " << item_id << llendl;
+ gInventory.updateItem(new_item);
+ }
+ // UPDATE ITEMS
+ for (deferred_item_map_t::const_iterator update_it = items_updated.begin();
+ update_it != items_updated.end(); ++update_it)
+ {
+ LLUUID item_id(update_it->first);
+ LLPointer<LLViewerInventoryItem> new_item = update_it->second;
+ // FIXME risky function since it calls updateServer() in some
+ // cases. Maybe break out the update/create cases, in which
+ // case this is update.
+ LL_DEBUGS("Inventory") << "updated item " << item_id << llendl;
+ gInventory.updateItem(new_item);
+ }
+
+ // DELETE OBJECTS
+ for (std::set<LLUUID>::const_iterator del_it = objects_deleted.begin();
+ del_it != objects_deleted.end(); ++del_it)
+ {
+ LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl;
+ onObjectDeletedFromServer(*del_it, false, false);
+ }
+
}
void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
@@ -1395,7 +1509,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo
// Update model after an item is confirmed as removed from
// server. Works for categories or items.
-void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links)
+void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links, bool update_parent_version)
{
LLPointer<LLInventoryObject> obj = getObject(object_id);
if(obj)
@@ -1406,9 +1520,13 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f
onDescendentsPurgedFromServer(object_id, fix_broken_links);
}
+
// From item/cat removeFromServer()
- LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
- accountForUpdate(up);
+ if (update_parent_version)
+ {
+ LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
+ accountForUpdate(up);
+ }
// From purgeObject()
LLPreview::hide(object_id);
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index fd2481b531..a41a824906 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -334,7 +334,7 @@ public:
// Update model after an item is confirmed as removed from
// server. Works for categories or items.
- void onObjectDeletedFromServer(const LLUUID& item_id, bool fix_broken_links = true);
+ void onObjectDeletedFromServer(const LLUUID& item_id, bool fix_broken_links = true, bool update_parent_version = true);
// Update model after all descendents removed from server.
void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 465a49d004..0608c46051 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -493,6 +493,34 @@ private:
LLSD mUpdates;
};
+class SlamFolderCommand: public AISCommand
+{
+public:
+ SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
+ mContents(contents),
+ AISCommand(callback)
+ {
+ std::string cap;
+ if (!getCap(cap))
+ {
+ llwarns << "No cap found" << llendl;
+ return;
+ }
+ LLUUID tid;
+ tid.generate();
+ std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
+ llinfos << url << llendl;
+ LLCurl::ResponderPtr responder = this;
+ LLSD headers;
+ headers["Content-Type"] = "application/llsd+xml";
+ F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+ command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers, timeout);
+ setCommandFunc(cmd);
+ }
+private:
+ LLSD mContents;
+};
+
///----------------------------------------------------------------------------
/// Class LLViewerInventoryItem
///----------------------------------------------------------------------------
@@ -1828,6 +1856,54 @@ void create_new_item(const std::string& name,
}
+void slam_inventory_folder(const LLUUID& folder_id,
+ const LLSD& contents,
+ LLPointer<LLInventoryCallback> cb)
+{
+ std::string cap;
+ if (AISCommand::getCap(cap))
+ {
+ LLPointer<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
+ cmd_ptr->run_command();
+ }
+ else // no cap
+ {
+ for (LLSD::array_const_iterator it = contents.beginArray();
+ it != contents.endArray();
+ ++it)
+ {
+ const LLSD& item_contents = *it;
+ link_inventory_item(gAgent.getID(),
+ item_contents["linked_id"].asUUID(),
+ folder_id,
+ item_contents["name"].asString(),
+ item_contents["desc"].asString(),
+ LLAssetType::EType(item_contents["type"].asInteger()),
+ cb);
+ }
+ remove_folder_contents(folder_id,false,cb);
+ }
+}
+
+void remove_folder_contents(const LLUUID& category, bool keep_outfit_links,
+ LLPointer<LLInventoryCallback> cb)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(category, cats, items,
+ LLInventoryModel::EXCLUDE_TRASH);
+ for (S32 i = 0; i < items.count(); ++i)
+ {
+ LLViewerInventoryItem *item = items.get(i);
+ if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER))
+ continue;
+ if (item->getIsLinkType())
+ {
+ remove_inventory_item(item->getUUID(), cb);
+ }
+ }
+}
+
const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not)
const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not)
const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)
@@ -2263,3 +2339,5 @@ BOOL LLViewerInventoryItem::regenerateLink()
gInventory.notifyObservers();
return TRUE;
}
+
+
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index c52b0c2d9d..9af71dfc9c 100755
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -407,4 +407,11 @@ void menu_create_inventory_item(LLInventoryPanel* root,
const LLSD& userdata,
const LLUUID& default_parent_uuid = LLUUID::null);
+void slam_inventory_folder(const LLUUID& folder_id,
+ const LLSD& contents,
+ LLPointer<LLInventoryCallback> cb);
+
+void remove_folder_contents(const LLUUID& folder_id, bool keep_outfit_links,
+ LLPointer<LLInventoryCallback> cb);
+
#endif // LL_LLVIEWERINVENTORY_H
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index e77b29aca4..b635087d66 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1877,7 +1877,7 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
{
if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia")))
{
- llwarns << "getCapability called before caps received" << llendl;
+ llwarns << "getCapability called before caps received for " << name << llendl;
}
CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index b73411080a..68633fba6e 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -734,44 +734,28 @@ void send_stats()
LLHTTPClient::post(url, body, new ViewerStatsResponder());
}
-LLFrameTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name)
+LLTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name)
{
phase_map_t::iterator iter = mPhaseMap.find(phase_name);
if (iter == mPhaseMap.end())
{
- LLFrameTimer timer;
+ LLTimer timer;
mPhaseMap[phase_name] = timer;
}
- LLFrameTimer& timer = mPhaseMap[phase_name];
+ LLTimer& timer = mPhaseMap[phase_name];
return timer;
}
void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name)
{
- LLFrameTimer& timer = getPhaseTimer(phase_name);
- lldebugs << "startPhase " << phase_name << llendl;
- timer.unpause();
-}
-
-void LLViewerStats::PhaseMap::stopAllPhases()
-{
- for (phase_map_t::iterator iter = mPhaseMap.begin();
- iter != mPhaseMap.end(); ++iter)
- {
- const std::string& phase_name = iter->first;
- if (iter->second.getStarted())
- {
- // Going from started to paused state - record stats.
- recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
- }
- lldebugs << "stopPhase (all) " << phase_name << llendl;
- iter->second.pause();
- }
+ LLTimer& timer = getPhaseTimer(phase_name);
+ timer.start();
+ LL_DEBUGS("Avatar") << "startPhase " << phase_name << llendl;
}
void LLViewerStats::PhaseMap::clearPhases()
{
- lldebugs << "clearPhases" << llendl;
+ LL_DEBUGS("Avatar") << "clearPhases" << llendl;
mPhaseMap.clear();
}
@@ -796,7 +780,6 @@ LLViewerStats::PhaseMap::PhaseMap()
{
}
-
void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name)
{
phase_map_t::iterator iter = mPhaseMap.find(phase_name);
@@ -809,6 +792,7 @@ void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name)
}
}
}
+
// static
LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name)
{
@@ -832,14 +816,18 @@ void LLViewerStats::PhaseMap::recordPhaseStat(const std::string& phase_name, F32
bool LLViewerStats::PhaseMap::getPhaseValues(const std::string& phase_name, F32& elapsed, bool& completed)
{
phase_map_t::iterator iter = mPhaseMap.find(phase_name);
+ bool found = false;
if (iter != mPhaseMap.end())
{
+ found = true;
elapsed = iter->second.getElapsedTimeF32();
completed = !iter->second.getStarted();
- return true;
+ LL_DEBUGS("Avatar") << " phase_name " << phase_name << " elapsed " << elapsed << " completed " << completed << " timer addr " << (S32)(&iter->second) << llendl;
}
else
{
- return false;
+ LL_DEBUGS("Avatar") << " phase_name " << phase_name << " NOT FOUND" << llendl;
}
+
+ return found;
}
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 6b2461be41..eaa0b6beff 100755
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -279,7 +279,7 @@ public:
// Phase tracking (originally put in for avatar rezzing), tracking
// progress of active/completed phases for activities like outfit changing.
- typedef std::map<std::string,LLFrameTimer> phase_map_t;
+ typedef std::map<std::string,LLTimer> phase_map_t;
typedef std::map<std::string,StatsAccumulator> phase_stats_t;
class PhaseMap
{
@@ -288,11 +288,10 @@ public:
static phase_stats_t sStats;
public:
PhaseMap();
- LLFrameTimer& getPhaseTimer(const std::string& phase_name);
+ LLTimer& getPhaseTimer(const std::string& phase_name);
bool getPhaseValues(const std::string& phase_name, F32& elapsed, bool& completed);
void startPhase(const std::string& phase_name);
void stopPhase(const std::string& phase_name);
- void stopAllPhases();
void clearPhases();
LLSD dumpPhases();
static StatsAccumulator& getPhaseStats(const std::string& phase_name);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 310ff47cf5..4593541f35 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6049,9 +6049,12 @@ void LLVOAvatar::clearPhases()
void LLVOAvatar::startPhase(const std::string& phase_name)
{
- F32 elapsed;
- bool completed;
- if (getPhases().getPhaseValues(phase_name, elapsed, completed))
+ F32 elapsed = 0.0;
+ bool completed = false;
+ bool found = getPhases().getPhaseValues(phase_name, elapsed, completed);
+ //LL_DEBUGS("Avatar") << avString() << " phase state " << phase_name
+ // << " found " << found << " elapsed " << elapsed << " completed " << completed << llendl;
+ if (found)
{
if (!completed)
{
@@ -6065,9 +6068,12 @@ void LLVOAvatar::startPhase(const std::string& phase_name)
void LLVOAvatar::stopPhase(const std::string& phase_name, bool err_check)
{
- F32 elapsed;
- bool completed;
- if (getPhases().getPhaseValues(phase_name, elapsed, completed))
+ F32 elapsed = 0.0;
+ bool completed = false;
+ bool found = getPhases().getPhaseValues(phase_name, elapsed, completed);
+ //LL_DEBUGS("Avatar") << avString() << " phase state " << phase_name
+ // << " found " << found << " elapsed " << elapsed << " completed " << completed << llendl;
+ if (found)
{
if (!completed)
{
@@ -7446,6 +7452,15 @@ std::string get_sequential_numbered_file_name(const std::string& prefix,
return outfilename;
}
+void dump_sequential_xml(const std::string outprefix, const LLSD& content)
+{
+ std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml");
+ std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
+ std::ofstream ofs(fullpath.c_str(), std::ios_base::out);
+ ofs << LLSDOStreamer<LLSDXMLFormatter>(content, LLSDFormatter::OPTIONS_PRETTY);
+ LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL;
+}
+
void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables )
{
std::string outprefix(prefix);
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 19ad49d3a1..fad2fd962c 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -998,6 +998,7 @@ extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL;
std::string get_sequential_numbered_file_name(const std::string& prefix,
const std::string& suffix);
+void dump_sequential_xml(const std::string outprefix, const LLSD& content);
void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value);
#endif // LL_VOAVATAR_H
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 5b6fcc5d27..232bf3e478 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -239,6 +239,9 @@ void LLVOAvatarSelf::initInstance()
bool LLVOAvatarSelf::checkStuckAppearance()
{
+ const F32 CONDITIONAL_UNSTICK_INTERVAL = 300.0;
+ const F32 UNCONDITIONAL_UNSTICK_INTERVAL = 600.0;
+
if (gAgentWearables.isCOFChangeInProgress())
{
LL_DEBUGS("Avatar") << "checking for stuck appearance" << llendl;
@@ -246,6 +249,14 @@ bool LLVOAvatarSelf::checkStuckAppearance()
LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << llendl;
S32 active_hp = LLAppearanceMgr::instance().countActiveHoldingPatterns();
LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << llendl;
+ S32 active_copies = LLAppearanceMgr::instance().getActiveCopyOperations();
+ LL_DEBUGS("Avatar") << "active copy operations " << active_copies << llendl;
+
+ if ((change_time > CONDITIONAL_UNSTICK_INTERVAL && active_copies == 0) ||
+ (change_time > UNCONDITIONAL_UNSTICK_INTERVAL))
+ {
+ gAgentWearables.notifyLoadingFinished();
+ }
}
// Return false to continue running check periodically.
@@ -2369,7 +2380,6 @@ LLSD summarize_by_buckets(std::vector<LLSD> in_records,
void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
{
- // gAgentAvatarp->stopAllPhases();
static volatile bool reporting_started(false);
static volatile S32 report_sequence(0);