From f945415210f0e18c2c6d941fda6b7d45cb0f06f1 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Wed, 13 Mar 2013 06:26:25 +0000 Subject: Large changes to the LLCurl::Responder API, as well as pulling in some changes to common libraries from the server codebase: * Additional error checking in http handlers. * Uniform log spam for http errors. * Switch to using constants for http heads and status codes. * Fixed bugs in incorrectly checking if parsing LLSD xml resulted in an error. * Reduced spam regarding LLSD parsing errors in the default completedRaw http handler. It should not longer be necessary to short-circuit completedRaw to avoid spam. * Ported over a few bug fixes from the server code. * Switch mode http status codes to use S32 instead of U32. * Ported LLSD::asStringRef from server code; avoids copying strings all over the place. * Ported server change to LLSD::asBinary; this always returns a reference now instead of copying the entire binary blob. * Ported server pretty notation format (and pretty binary format) to llsd serialization. * The new LLCurl::Responder API no longer has two error handlers to choose from. Overriding the following methods have been deprecated: ** error - use httpFailure ** errorWithContent - use httpFailure ** result - use httpSuccess ** completed - use httpCompleted ** completedHeader - no longer necessary; call getResponseHeaders() from a completion method to obtain these headers. * In order to 'catch' a completed http request, override one of these methods: ** httpSuccess - Called for any 2xx status code. ** httpFailure - Called for any non-2xx status code. ** httpComplete - Called for all status codes. Default implementation is to call either httpSuccess or httpFailure. * It is recommended to keep these methods protected/private in order to avoid triggering of these methods without using a 'push' method (see below). * Uniform error handling should followed whenever possible by calling a variant of this during httpFailure: ** llwarns << dumpResponse() << llendl; * Be sure to include LOG_CLASS(your_class_name) in your class in order for the log entry to give more context. * In order to 'push' a result into the responder, you should no longer call error, errorWithContent, result, or completed. * Nor should you directly call httpSuccess/Failure/Completed (unless passing a message up to a parent class). * Instead, you can set the internal content of a responder and trigger a corresponding method using the following methods: ** successResult - Sets results and calls httpSuccess ** failureResult - Sets results and calls httpFailure ** completedResult - Sets results and calls httpCompleted * To obtain information about a the response from a reponder method, use the following getters: ** getStatus - HTTP status code ** getReason - Reason string ** getContent - Content (Parsed body LLSD) ** getResponseHeaders - Response Headers (LLSD map) ** getHTTPMethod - HTTP method of the request ** getURL - URL of the request * It is still possible to override completeRaw if you want to manipulate data directly out of LLPumpIO. * See indra/llmessage/llcurl.h for more information. --- indra/newview/llinventorymodel.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 99e72cdb22..0b2f80403d 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -414,6 +414,7 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLCreateInventoryCategoryResponder); public: LLCreateInventoryCategoryResponder(LLInventoryModel* model, void (*callback)(const LLSD&, void*), @@ -424,16 +425,21 @@ public: { } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +protected: + virtual void httpFailure() { - LL_WARNS("InvAPI") << "CreateInventoryCategory failed [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("InvAPI") << dumpResponse() << LL_ENDL; } - virtual void result(const LLSD& content) + virtual void httpSuccess() { //Server has created folder. - + const LLSD& content = getContent(); + if (!content.isMap() || !content.has("folder_id")) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLUUID category_id = content["folder_id"].asUUID(); @@ -1340,8 +1346,14 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) } // If we get back a normal response, handle it here -void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) -{ +void LLInventoryModel::fetchInventoryResponder::httpSuccess() +{ + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } start_new_inventory_observer(); /*LLUUID agent_id; @@ -1400,9 +1412,9 @@ void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) } //If we get back an error (not found, etc...), handle it here -void LLInventoryModel::fetchInventoryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLInventoryModel::fetchInventoryResponder::httpFailure() { - llwarns << "fetchInventory error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; gInventory.notifyObservers(); } -- cgit v1.2.3 From e3ceb10c48b7ce339fab8c3c7a726bd4bf2e30e8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 18 Apr 2013 17:31:35 -0400 Subject: SH-4128 WIP - avoid needless called to updateLinkedObjectsFromPurge() --- indra/newview/llinventorymodel.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) mode change 100644 => 100755 indra/newview/llinventorymodel.cpp (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp old mode 100644 new mode 100755 index 8d7478233a..3d2fcdc494 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1171,8 +1171,14 @@ void LLInventoryModel::deleteObject(const LLUUID& id) mParentChildCategoryTree.erase(id); } addChangedMask(LLInventoryObserver::REMOVE, id); + bool is_link_type = obj->getIsLinkType(); obj = NULL; // delete obj - updateLinkedObjectsFromPurge(id); + // Can't have links to links, so there's no need for this update + // if the item removed is a link. + if (!is_link_type) + { + updateLinkedObjectsFromPurge(id); + } gInventory.notifyObservers(); } -- cgit v1.2.3 From 7b52a41e34e1fefd751d69be708b23df59774c6a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 18 Apr 2013 17:49:10 -0400 Subject: SH-4116 WIP - removed follow_folder_links behavior, which was used nowhere and isn't really desirable currently --- indra/newview/llinventorymodel.cpp | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 3d2fcdc494..bbf284147a 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -624,8 +624,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, cat_array_t& cats, item_array_t& items, BOOL include_trash, - LLInventoryCollectFunctor& add, - BOOL follow_folder_links) + LLInventoryCollectFunctor& add) { // Start with categories if(!include_trash) @@ -652,36 +651,6 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, LLViewerInventoryItem* item = NULL; item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id); - // Follow folder links recursively. Currently never goes more - // than one level deep (for current outfit support) - // Note: if making it fully recursive, need more checking against infinite loops. - if (follow_folder_links && item_array) - { - S32 count = item_array->count(); - for(S32 i = 0; i < count; ++i) - { - item = item_array->get(i); - if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) - { - LLViewerInventoryCategory *linked_cat = item->getLinkedCategory(); - if (linked_cat && linked_cat->getPreferredType() != LLFolderType::FT_OUTFIT) - // BAP - was - // LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType())) - // Change back once ensemble typing is in place. - { - if(add(linked_cat,NULL)) - { - // BAP should this be added here? May not - // matter if it's only being used in current - // outfit traversal. - cats.put(LLPointer(linked_cat)); - } - collectDescendentsIf(linked_cat->getUUID(), cats, items, include_trash, add, FALSE); - } - } - } - } - // Move onto items if(item_array) { -- cgit v1.2.3 From 4967998a5c10abcc64e097a4e95505f9adbe4de7 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 24 Apr 2013 13:27:04 -0400 Subject: CHUI-849 WIP, SH-4116 WIP - added simpler match check in inventory for when we don't need the list of matches to be returned. --- indra/newview/llinventorymodel.cpp | 59 ++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 9 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index bbf284147a..11223d96b6 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -593,6 +593,40 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, return id; } +// This is optimized for the case that we just want to know whether a +// category has any immediate children meeting a condition, without +// needing to recurse or build up any lists. +bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id, + LLInventoryCollectFunctor& filter) +{ + LLInventoryModel::cat_array_t *cats; + LLInventoryModel::item_array_t *items; + getDirectDescendentsOf(cat_id, cats, items); + if (cats) + { + for (LLInventoryModel::cat_array_t::const_iterator it = cats->begin(); + it != cats->end(); ++it) + { + if (filter(*it,NULL)) + { + return true; + } + } + } + if (items) + { + for (LLInventoryModel::item_array_t::const_iterator it = items->begin(); + it != items->end(); ++it) + { + if (filter(NULL,*it)) + { + return true; + } + } + } + return false; +} + // Starting with the object specified, add it's descendents to the // array provided, but do not add the inventory object specified by // id. There is no guaranteed order. Neither array will be erased @@ -723,6 +757,10 @@ LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID const LLUUID& start_folder_id) { item_array_t items; + const LLInventoryObject *obj = getObject(id); + if (!obj || obj->getIsLinkType()) + return items; + LLInventoryModel::cat_array_t cat_array; LLLinkedItemIDMatches is_linked_item_match(id); collectDescendentsIf((start_folder_id == LLUUID::null ? gInventory.getRootFolderID() : start_folder_id), @@ -1170,17 +1208,20 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) // REBUILD is expensive, so clear the current change list first else // everything else on the changelist will also get rebuilt. - gInventory.notifyObservers(); - for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); - iter != item_array.end(); - iter++) + if (item_array.size()) { - const LLViewerInventoryItem *linked_item = (*iter); - const LLUUID &item_id = linked_item->getUUID(); - if (item_id == baseobj_id) continue; - addChangedMask(LLInventoryObserver::REBUILD, item_id); + gInventory.notifyObservers(); + for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); + iter != item_array.end(); + iter++) + { + const LLViewerInventoryItem *linked_item = (*iter); + const LLUUID &item_id = linked_item->getUUID(); + if (item_id == baseobj_id) continue; + addChangedMask(LLInventoryObserver::REBUILD, item_id); + } + gInventory.notifyObservers(); } - gInventory.notifyObservers(); } // This is a method which collects the descendents of the id -- cgit v1.2.3 From eb88e4d37850a48132193d332fa8945d3932369b Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 24 Apr 2013 18:08:20 -0400 Subject: SH-4128 WIP - cleanup around item link removal and callbacks --- indra/newview/llinventorymodel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 11223d96b6..bc327b8359 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1178,10 +1178,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id) mParentChildCategoryTree.erase(id); } addChangedMask(LLInventoryObserver::REMOVE, id); - bool is_link_type = obj->getIsLinkType(); obj = NULL; // delete obj + // Can't have links to links, so there's no need for this update // if the item removed is a link. + bool is_link_type = obj->getIsLinkType(); if (!is_link_type) { updateLinkedObjectsFromPurge(id); @@ -1208,7 +1209,7 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) // REBUILD is expensive, so clear the current change list first else // everything else on the changelist will also get rebuilt. - if (item_array.size()) + if (item_array.size() > 0) { gInventory.notifyObservers(); for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); -- cgit v1.2.3 From d73588eaddb1ada6ac896850c3aa9d25307e076a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 24 Apr 2013 18:38:40 -0400 Subject: SH-4128 WIP - misc cleanup --- indra/newview/llinventorymodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index bc327b8359..a0b9e7b0ec 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1178,11 +1178,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id) mParentChildCategoryTree.erase(id); } addChangedMask(LLInventoryObserver::REMOVE, id); - obj = NULL; // delete obj - + // Can't have links to links, so there's no need for this update // if the item removed is a link. bool is_link_type = obj->getIsLinkType(); + obj = NULL; // delete obj if (!is_link_type) { updateLinkedObjectsFromPurge(id); -- cgit v1.2.3 From d843a0d8bef5d36d3a4ef838b1b0335b4532147b Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 25 Apr 2013 17:09:05 -0400 Subject: SH-4137 WIP - added callback-based support for purge descendents, remove category --- indra/newview/llinventorymodel.cpp | 207 ++++++++++++++----------------------- 1 file changed, 76 insertions(+), 131 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index a0b9e7b0ec..ae8efeecda 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1136,6 +1136,79 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, notifyObservers(); } +// Update model after descendents have been purged. +void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id) +{ + LLPointer cat = getCategory(object_id); + if (cat.notNull()) + { + // do the cache accounting + S32 descendents = cat->getDescendentCount(); + if(descendents > 0) + { + LLInventoryModel::LLCategoryUpdate up(object_id, -descendents); + accountForUpdate(up); + } + + // we know that descendent count is 0, however since the + // accounting may actually not do an update, we should force + // it here. + cat->setDescendentCount(0); + + // unceremoniously remove anything we have locally stored. + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + collectDescendents(object_id, + categories, + items, + LLInventoryModel::INCLUDE_TRASH); + S32 count = items.count(); + + LLUUID uu_id; + for(S32 i = 0; i < count; ++i) + { + uu_id = items.get(i)->getUUID(); + + // This check prevents the deletion of a previously deleted item. + // This is necessary because deletion is not done in a hierarchical + // order. The current item may have been already deleted as a child + // of its deleted parent. + if (getItem(uu_id)) + { + deleteObject(uu_id); + } + } + + count = categories.count(); + for(S32 i = 0; i < count; ++i) + { + uu_id = categories.get(i)->getUUID(); + if (getCategory(uu_id)) + { + deleteObject(uu_id); + } + } + } +} + +// Update model after an item is confirmed as removed from +// server. Works for categories or items. +void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id) +{ + LLPointer obj = getObject(object_id); + if(obj) + { + // From item/cat removeFromServer() + LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1); + accountForUpdate(up); + + // From purgeObject() + LLPreview::hide(object_id); + deleteObject(object_id); + } +} + + // Delete a particular inventory object by ID. void LLInventoryModel::deleteObject(const LLUUID& id) { @@ -1187,20 +1260,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id) { updateLinkedObjectsFromPurge(id); } - gInventory.notifyObservers(); -} - -// Delete a particular inventory item by ID, and remove it from the server. -void LLInventoryModel::purgeObject(const LLUUID &id) -{ - lldebugs << "LLInventoryModel::purgeObject() [ id: " << id << " ] " << llendl; - LLPointer obj = getObject(id); - if(obj) - { - obj->removeFromServer(); - LLPreview::hide(id); - deleteObject(id); - } + notifyObservers(); } void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) @@ -1225,119 +1285,6 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) } } -// This is a method which collects the descendents of the id -// provided. If the category is not found, no action is -// taken. This method goes through the long winded process of -// cancelling any calling cards, removing server representation of -// folders, items, etc in a fairly efficient manner. -void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) -{ - EHasChildren children = categoryHasChildren(id); - if(children == CHILDREN_NO) - { - llinfos << "Not purging descendents of " << id << llendl; - return; - } - LLPointer cat = getCategory(id); - if (cat.notNull()) - { - if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode()) - { - // Something on the clipboard is in "cut mode" and needs to be preserved - llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() - << " iterate and purge non hidden items" << llendl; - cat_array_t* categories; - item_array_t* items; - // Get the list of direct descendants in tha categoy passed as argument - getDirectDescendentsOf(id, categories, items); - std::vector list_uuids; - // Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently) - // Note: we need to do that shallow copy as purging things will invalidate the categories or items lists - for (cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it) - { - list_uuids.push_back((*it)->getUUID()); - } - for (item_array_t::const_iterator it = items->begin(); it != items->end(); ++it) - { - list_uuids.push_back((*it)->getUUID()); - } - // Iterate through the list and only purge the UUIDs that are not on the clipboard - for (std::vector::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it) - { - if (!LLClipboard::instance().isOnClipboard(*it)) - { - purgeObject(*it); - } - } - } - else - { - // Fast purge - // do the cache accounting - llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() - << llendl; - S32 descendents = cat->getDescendentCount(); - if(descendents > 0) - { - LLCategoryUpdate up(id, -descendents); - accountForUpdate(up); - } - - // we know that descendent count is 0, however since the - // accounting may actually not do an update, we should force - // it here. - cat->setDescendentCount(0); - - // send it upstream - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("PurgeInventoryDescendents"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("InventoryData"); - msg->addUUID("FolderID", id); - gAgent.sendReliableMessage(); - - // unceremoniously remove anything we have locally stored. - cat_array_t categories; - item_array_t items; - collectDescendents(id, - categories, - items, - INCLUDE_TRASH); - S32 count = items.count(); - - item_map_t::iterator item_map_end = mItemMap.end(); - cat_map_t::iterator cat_map_end = mCategoryMap.end(); - LLUUID uu_id; - - for(S32 i = 0; i < count; ++i) - { - uu_id = items.get(i)->getUUID(); - - // This check prevents the deletion of a previously deleted item. - // This is necessary because deletion is not done in a hierarchical - // order. The current item may have been already deleted as a child - // of its deleted parent. - if (mItemMap.find(uu_id) != item_map_end) - { - deleteObject(uu_id); - } - } - - count = categories.count(); - for(S32 i = 0; i < count; ++i) - { - uu_id = categories.get(i)->getUUID(); - if (mCategoryMap.find(uu_id) != cat_map_end) - { - deleteObject(uu_id); - } - } - } - } -} - // Add/remove an observer. If the observer is destroyed, be sure to // remove it. void LLInventoryModel::addObserver(LLInventoryObserver* observer) @@ -3114,8 +3061,7 @@ bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const L if (option == 0) // YES { const LLUUID folder_id = findCategoryUUIDForType(preferred_type); - purgeDescendentsOf(folder_id); - notifyObservers(); + purge_descendents_of(folder_id, NULL); } return false; } @@ -3130,8 +3076,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT else { const LLUUID folder_id = findCategoryUUIDForType(preferred_type); - purgeDescendentsOf(folder_id); - notifyObservers(); + purge_descendents_of(folder_id, NULL); } } -- cgit v1.2.3 From 89cef0cad260e7c8369070c32478621f1cd22f62 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 1 May 2013 17:55:49 -0400 Subject: SH-4154 WIP - gInventory.validate() has inventory model internal consistency checks --- indra/newview/llinventorymodel.cpp | 197 ++++++++++++++++++++++++++++++++++++- 1 file changed, 196 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ae8efeecda..f60fd63eee 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -252,6 +252,23 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL return NULL; } +bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const +{ + LLInventoryObject *object = getObject(object_id); + while (object && object->getParentUUID().notNull()) + { + LLInventoryObject *parent_object = getObject(object->getParentUUID()); + if (!parent_object) + { + llwarns << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << llendl; + return false; + } + object = parent_object; + } + result = object->getUUID(); + return true; +} + // Get the object by id. Returns NULL if not found. LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const { @@ -2083,7 +2100,7 @@ void LLInventoryModel::buildParentChildMap() // implement it, we would need a set or map of uuid pairs // which would be (folder_id, new_parent_id) to be sent up // to the server. - llinfos << "Lost categroy: " << cat->getUUID() << " - " + llinfos << "Lost category: " << cat->getUUID() << " - " << cat->getName() << llendl; ++lost; // plop it into the lost & found. @@ -2102,6 +2119,8 @@ void LLInventoryModel::buildParentChildMap() // it's a protected folder. cat->setParent(gInventory.getRootFolderID()); } + // FIXME note that updateServer() fails with protected + // types, so this will not work as intended in that case. cat->updateServer(TRUE); catsp = getUnlockedCatArray(cat->getParentUUID()); if(catsp) @@ -2247,6 +2266,11 @@ void LLInventoryModel::buildParentChildMap() notifyObservers(); } } + + //if (!gInventory.validate()) + //{ + // llwarns << "model failed validity check!" << llendl; + //} } struct LLUUIDAndName @@ -2917,6 +2941,9 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) InventoryCallbackInfo cbinfo = (*inv_it); gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID); } + + //gInventory.validate(); + // Don't show the inventory. We used to call showAgentInventory here. //LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); //if(view) @@ -3363,6 +3390,174 @@ void LLInventoryModel::dumpInventory() const llinfos << "\n**********************\nEnd Inventory Dump" << llendl; } +// Do various integrity checks on model, logging issues found and +// returning an overall good/bad flag. +bool LLInventoryModel::validate() const +{ + bool valid = true; + + if (getRootFolderID().isNull()) + { + llwarns << "no root folder id" << llendl; + valid = false; + } + if (getLibraryRootFolderID().isNull()) + { + llwarns << "no root folder id" << llendl; + valid = false; + } + + if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size()) + { + // ParentChild should be one larger because of the special entry for null uuid. + llinfos << "unexpected sizes: cat map size " << mCategoryMap.size() + << " parent/child " << mParentChildCategoryTree.size() << llendl; + valid = false; + } + S32 cat_lock = 0; + S32 item_lock = 0; + S32 desc_unknown_count = 0; + S32 version_unknown_count = 0; + for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit) + { + const LLUUID& cat_id = cit->first; + const LLViewerInventoryCategory *cat = cit->second; + if (!cat) + { + llwarns << "invalid cat" << llendl; + valid = false; + continue; + } + if (cat_id != cat->getUUID()) + { + llwarns << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << llendl; + valid = false; + } + + if (cat->getParentUUID().isNull()) + { + if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID()) + { + llwarns << "cat " << cat_id << " has no parent, but is not root (" + << getRootFolderID() << ") or library root (" + << getLibraryRootFolderID() << ")" << llendl; + } + } + cat_array_t* cats; + item_array_t* items; + getDirectDescendentsOf(cat_id,cats,items); + if (!cats || !items) + { + llwarns << "invalid direct descendents for " << cat_id << llendl; + valid = false; + continue; + } + if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) + { + desc_unknown_count++; + } + else if (cats->size() + items->size() != cat->getDescendentCount()) + { + llwarns << "invalid desc count for " << cat_id << " name " << cat->getName() + << " cached " << cat->getDescendentCount() + << " expected " << cats->size() << "+" << items->size() + << "=" << cats->size() +items->size() << llendl; + valid = false; + } + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + version_unknown_count++; + } + if (mCategoryLock.count(cat_id)) + { + cat_lock++; + } + if (mItemLock.count(cat_id)) + { + item_lock++; + } + for (S32 i = 0; isize(); i++) + { + LLViewerInventoryItem *item = items->get(i); + + if (!item) + { + llwarns << "null item at index " << i << " for cat " << cat_id << llendl; + valid = false; + continue; + } + + const LLUUID& item_id = item->getUUID(); + + if (item->getParentUUID() != cat_id) + { + llwarns << "wrong parent for " << item_id << " found " + << item->getParentUUID() << " expected " << cat_id + << llendl; + valid = false; + } + + + // Entries in items and mItemMap should correspond. + item_map_t::const_iterator it = mItemMap.find(item_id); + if (it == mItemMap.end()) + { + llwarns << "item " << item_id << " found as child of " + << cat_id << " but not in top level mItemMap" << llendl; + valid = false; + } + else + { + LLViewerInventoryItem *top_item = it->second; + if (top_item != item) + { + llwarns << "item mismatch, item_id " << item_id + << " top level entry is different, uuid " << top_item->getUUID() << llendl; + } + } + + // Topmost ancestor should be root or library. + LLUUID topmost_ancestor_id; + bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id); + if (!found) + { + llwarns << "unable to find topmost ancestor for " << item_id << llendl; + valid = false; + } + else + { + if (topmost_ancestor_id != getRootFolderID() && + topmost_ancestor_id != getLibraryRootFolderID()) + { + llwarns << "unrecognized top level ancestor for " << item_id + << " got " << topmost_ancestor_id + << " expected " << getRootFolderID() + << " or " << getLibraryRootFolderID() << llendl; + valid = false; + } + } + } + + } + if (cat_lock > 0 || item_lock > 0) + { + llwarns << "Found locks on some categories: sub-cat arrays " + << cat_lock << ", item arrays " << item_lock << llendl; + } + if (desc_unknown_count != 0) + { + llinfos << "Found " << desc_unknown_count << " cats with unknown descendent count" << llendl; + } + if (version_unknown_count != 0) + { + llinfos << "Found " << version_unknown_count << " cats with unknown version" << llendl; + } + + llinfos << "Validate done, valid = " << (U32) valid << llendl; + + return valid; +} + ///---------------------------------------------------------------------------- /// Local function definitions ///---------------------------------------------------------------------------- -- cgit v1.2.3 From 9881b65845b7320a2fc23b8ebc2a68996840ca16 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 7 May 2013 16:12:18 -0400 Subject: SH-4154 FIX - added a few more validity checks. Disabled by default so users won't have logs spammed. --- indra/newview/llinventorymodel.cpp | 92 +++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index f60fd63eee..bb5da2e9db 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2267,10 +2267,10 @@ void LLInventoryModel::buildParentChildMap() } } - //if (!gInventory.validate()) - //{ - // llwarns << "model failed validity check!" << llendl; - //} + // if (!gInventory.validate()) + // { + // llwarns << "model failed validity check!" << llendl; + // } } struct LLUUIDAndName @@ -3002,7 +3002,7 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) // If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added. if (gInventory.getItem(titem->getUUID())) { - lldebugs << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl; + llinfos << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl; continue; } gInventory.updateItem(titem); @@ -3458,7 +3458,8 @@ bool LLInventoryModel::validate() const } else if (cats->size() + items->size() != cat->getDescendentCount()) { - llwarns << "invalid desc count for " << cat_id << " name " << cat->getName() + llwarns << "invalid desc count for " << cat_id << " name [" << cat->getName() + << "] parent " << cat->getParentUUID() << " cached " << cat->getDescendentCount() << " expected " << cats->size() << "+" << items->size() << "=" << cats->size() +items->size() << llendl; @@ -3538,7 +3539,86 @@ bool LLInventoryModel::validate() const } } + // Does this category appear as a child of its supposed parent? + const LLUUID& parent_id = cat->getParentUUID(); + if (!parent_id.isNull()) + { + cat_array_t* cats; + item_array_t* items; + getDirectDescendentsOf(parent_id,cats,items); + if (!cats) + { + llwarns << "cat " << cat_id << " name [" << cat->getName() + << "] orphaned - no child cat array for alleged parent " << parent_id << llendl; + valid = false; + } + else + { + bool found = false; + for (S32 i = 0; isize(); i++) + { + LLViewerInventoryCategory *kid_cat = cats->get(i); + if (kid_cat == cat) + { + found = true; + break; + } + } + if (!found) + { + llwarns << "cat " << cat_id << " name [" << cat->getName() + << "] orphaned - not found in child cat array of alleged parent " << parent_id << llendl; + } + } + } + } + + for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit) + { + const LLUUID& item_id = iit->first; + LLViewerInventoryItem *item = iit->second; + if (item->getUUID() != item_id) + { + llwarns << "item_id " << item_id << " does not match " << item->getUUID() << llendl; + valid = false; + } + + const LLUUID& parent_id = item->getParentUUID(); + if (parent_id.isNull()) + { + llwarns << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << llendl; + } + else + { + cat_array_t* cats; + item_array_t* items; + getDirectDescendentsOf(parent_id,cats,items); + if (!items) + { + llwarns << "item " << item_id << " name [" << item->getName() + << "] orphaned - alleged parent has no child items list " << parent_id << llendl; + } + else + { + bool found = false; + for (S32 i=0; isize(); ++i) + { + if (items->get(i) == item) + { + found = true; + break; + } + } + if (!found) + { + llwarns << "item " << item_id << " name [" << item->getName() + << "] orphaned - not found as child of alleged parent " << parent_id << llendl; + } + } + + } } + if (cat_lock > 0 || item_lock > 0) { llwarns << "Found locks on some categories: sub-cat arrays " -- cgit v1.2.3 From 228178ac15f60f9b66b72a9d3f13e706d7d6de36 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 9 May 2013 11:01:29 -0400 Subject: SH-4168 WIP - fixed some bugs in inventory deletion and lost-and-found handling. --- indra/newview/llinventorymodel.cpp | 121 +++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 37 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index bb5da2e9db..b49e617f62 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1197,14 +1197,39 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id) } count = categories.count(); - for(S32 i = 0; i < count; ++i) + // Slightly kludgy way to make sure categories are removed + // only after their child categories have gone away. + + // FIXME: Would probably make more sense to have this whole + // descendent-clearing thing be a post-order recursive + // function to get the leaf-up behavior automatically. + S32 deleted_count; + S32 total_deleted_count = 0; + do { - uu_id = categories.get(i)->getUUID(); - if (getCategory(uu_id)) + deleted_count = 0; + for(S32 i = 0; i < count; ++i) { - deleteObject(uu_id); + uu_id = categories.get(i)->getUUID(); + if (getCategory(uu_id)) + { + cat_array_t* cat_list = getUnlockedCatArray(uu_id); + if (!cat_list || (cat_list->size() == 0)) + { + deleteObject(uu_id); + deleted_count++; + } + } } + total_deleted_count += deleted_count; + } + while (deleted_count > 0); + if (total_deleted_count != count) + { + llwarns << "Unexpected count of categories deleted, got " + << total_deleted_count << " expected " << count << llendl; } + gInventory.validate(); } } @@ -1258,12 +1283,20 @@ void LLInventoryModel::deleteObject(const LLUUID& id) item_list = getUnlockedItemArray(id); if(item_list) { + if (item_list->size()) + { + llwarns << "Deleting cat " << id << " while it still has child items" << llendl; + } delete item_list; mParentChildItemTree.erase(id); } cat_list = getUnlockedCatArray(id); if(cat_list) { + if (cat_list->size()) + { + llwarns << "Deleting cat " << id << " while it still has child cats" << llendl; + } delete cat_list; mParentChildCategoryTree.erase(id); } @@ -2084,11 +2117,16 @@ void LLInventoryModel::buildParentChildMap() S32 count = cats.count(); S32 i; S32 lost = 0; + cat_array_t lost_cats; for(i = 0; i < count; ++i) { LLViewerInventoryCategory* cat = cats.get(i); catsp = getUnlockedCatArray(cat->getParentUUID()); - if(catsp) + if(catsp && + // Only the two root folders should be children of null. + // Others should go to lost & found. + (cat->getParentUUID().notNull() || + cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY )) { catsp->put(cat); } @@ -2103,34 +2141,7 @@ void LLInventoryModel::buildParentChildMap() llinfos << "Lost category: " << cat->getUUID() << " - " << cat->getName() << llendl; ++lost; - // plop it into the lost & found. - LLFolderType::EType pref = cat->getPreferredType(); - if(LLFolderType::FT_NONE == pref) - { - cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); - } - else if(LLFolderType::FT_ROOT_INVENTORY == pref) - { - // it's the root - cat->setParent(LLUUID::null); - } - else - { - // it's a protected folder. - cat->setParent(gInventory.getRootFolderID()); - } - // FIXME note that updateServer() fails with protected - // types, so this will not work as intended in that case. - cat->updateServer(TRUE); - catsp = getUnlockedCatArray(cat->getParentUUID()); - if(catsp) - { - catsp->put(cat); - } - else - { - llwarns << "Lost and found Not there!!" << llendl; - } + lost_cats.put(cat); } } if(lost) @@ -2138,6 +2149,42 @@ void LLInventoryModel::buildParentChildMap() llwarns << "Found " << lost << " lost categories." << llendl; } + // Do moves in a separate pass to make sure we've properly filed + // the FT_LOST_AND_FOUND category before we try to find its UUID. + for(i = 0; igetPreferredType(); + if(LLFolderType::FT_NONE == pref) + { + cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); + } + else if(LLFolderType::FT_ROOT_INVENTORY == pref) + { + // it's the root + cat->setParent(LLUUID::null); + } + else + { + // it's a protected folder. + cat->setParent(gInventory.getRootFolderID()); + } + // FIXME note that updateServer() fails with protected + // types, so this will not work as intended in that case. + cat->updateServer(TRUE); + catsp = getUnlockedCatArray(cat->getParentUUID()); + if(catsp) + { + catsp->put(cat); + } + else + { + llwarns << "Lost and found Not there!!" << llendl; + } + } + const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null); sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin(); @@ -2267,10 +2314,10 @@ void LLInventoryModel::buildParentChildMap() } } - // if (!gInventory.validate()) - // { - // llwarns << "model failed validity check!" << llendl; - // } + if (!gInventory.validate()) + { + llwarns << "model failed validity check!" << llendl; + } } struct LLUUIDAndName -- cgit v1.2.3 From b1998cabc487c434555276a389ed19847b98f998 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 13 May 2013 17:08:37 -0400 Subject: SH-4168 WIP, SH-4155 WIP - update inventory model based on ais returns, try to maintain loading... string more consistently in folder bridge --- indra/newview/llinventorymodel.cpp | 85 ++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index b49e617f62..fd57845c0e 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -48,6 +48,7 @@ #include "llcallbacklist.h" #include "llvoavatarself.h" #include "llgesturemgr.h" +#include "llsdutil.h" #include //#define DIFF_INVENTORY_FILES @@ -1153,8 +1154,69 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, notifyObservers(); } +void parse_llsd_uuid_array(const LLSD& content, const std::string& name, uuid_vec_t& ids) +{ + ids.clear(); + if (content.has(name)) + { + for(LLSD::array_const_iterator it = content[name].beginArray(), + end = content[name].endArray(); + it != end; ++it) + { + ids.push_back((*it).asUUID()); + } + } +} + +void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) +{ + llinfos << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl; + + 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) + { + llinfos << "remove category: " << *it << llendl; + onObjectDeletedFromServer(*it, false); + } + + 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) + { + llinfos << "remove item: " << *it << llendl; + onObjectDeletedFromServer(*it, false); + } + + 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) + { + llinfos << "remove broken link: " << *it << llendl; + onObjectDeletedFromServer(*it, false); + } + + 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) + { + const LLUUID id((*it).first); + S32 version = (*it).second.asInteger(); + llinfos << "update category: " << id << " to version " << version << llendl; + } + } + + +} + // Update model after descendents have been purged. -void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id) +void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links) { LLPointer cat = getCategory(object_id); if (cat.notNull()) @@ -1192,7 +1254,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id) // of its deleted parent. if (getItem(uu_id)) { - deleteObject(uu_id); + deleteObject(uu_id, fix_broken_links); } } @@ -1216,7 +1278,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id) cat_array_t* cat_list = getUnlockedCatArray(uu_id); if (!cat_list || (cat_list->size() == 0)) { - deleteObject(uu_id); + deleteObject(uu_id, fix_broken_links); deleted_count++; } } @@ -1235,24 +1297,30 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id) // Update model after an item is confirmed as removed from // server. Works for categories or items. -void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id) +void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links) { LLPointer obj = getObject(object_id); if(obj) { + if (getCategory(object_id)) + { + // For category, need to delete/update all children first. + onDescendentsPurgedFromServer(object_id, fix_broken_links); + } + // From item/cat removeFromServer() LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1); accountForUpdate(up); // From purgeObject() LLPreview::hide(object_id); - deleteObject(object_id); + deleteObject(object_id, fix_broken_links); } } // Delete a particular inventory object by ID. -void LLInventoryModel::deleteObject(const LLUUID& id) +void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links) { lldebugs << "LLInventoryModel::deleteObject()" << llendl; LLPointer obj = getObject(id); @@ -1303,10 +1371,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id) addChangedMask(LLInventoryObserver::REMOVE, id); // Can't have links to links, so there's no need for this update - // if the item removed is a link. + // if the item removed is a link. Can also skip if source of the + // update is getting broken link info separately. bool is_link_type = obj->getIsLinkType(); obj = NULL; // delete obj - if (!is_link_type) + if (fix_broken_links && !is_link_type) { updateLinkedObjectsFromPurge(id); } -- cgit v1.2.3 From 0f6a4a3389cdce6d5bb92cd6f4861a46def284cc Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 20 May 2013 18:06:26 -0400 Subject: SH-4200 FIX - retry ais ops on 5xx errors, dialed back some verbose logging. --- indra/newview/llinventorymodel.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index fd57845c0e..73ef3e60da 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1170,14 +1170,13 @@ void parse_llsd_uuid_array(const LLSD& content, const std::string& name, uuid_ve void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) { - llinfos << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl; + LL_DEBUGS("Inventory") << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl; 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) { - llinfos << "remove category: " << *it << llendl; onObjectDeletedFromServer(*it, false); } @@ -1186,7 +1185,6 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) { - llinfos << "remove item: " << *it << llendl; onObjectDeletedFromServer(*it, false); } @@ -1195,10 +1193,13 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS for (uuid_vec_t::const_iterator it = broken_link_ids.begin(); it != broken_link_ids.end(); ++it) { - llinfos << "remove broken link: " << *it << llendl; onObjectDeletedFromServer(*it, false); } + // 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)) { @@ -1208,9 +1209,9 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS { const LLUUID id((*it).first); S32 version = (*it).second.asInteger(); - llinfos << "update category: " << id << " to version " << version << llendl; } } +#endif } @@ -1291,7 +1292,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo llwarns << "Unexpected count of categories deleted, got " << total_deleted_count << " expected " << count << llendl; } - gInventory.validate(); + //gInventory.validate(); } } @@ -2925,7 +2926,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) LLUUID tid; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, tid); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Bulk inventory: " << tid << llendl; + LL_DEBUGS("Inventory") << "Bulk inventory: " << tid << llendl; #endif update_map_t update; @@ -2937,9 +2938,9 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) { LLPointer tfolder = new LLViewerInventoryCategory(gAgent.getID()); tfolder->unpackMessage(msg, _PREHASH_FolderData, i); - llinfos << "unpacked folder '" << tfolder->getName() << "' (" - << tfolder->getUUID() << ") in " << tfolder->getParentUUID() - << llendl; + LL_DEBUGS("Inventory") << "unpacked folder '" << tfolder->getName() << "' (" + << tfolder->getUUID() << ") in " << tfolder->getParentUUID() + << llendl; if(tfolder->getUUID().notNull()) { folders.push_back(tfolder); @@ -2979,8 +2980,8 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) { LLPointer titem = new LLViewerInventoryItem; titem->unpackMessage(msg, _PREHASH_ItemData, i); - llinfos << "unpacked item '" << titem->getName() << "' in " - << titem->getParentUUID() << llendl; + LL_DEBUGS("Inventory") << "unpacked item '" << titem->getName() << "' in " + << titem->getParentUUID() << llendl; U32 callback_id; msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id); if(titem->getUUID().notNull() ) // && callback_id.notNull() ) @@ -3118,7 +3119,8 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) // If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added. if (gInventory.getItem(titem->getUUID())) { - llinfos << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl; + LL_DEBUGS("Inventory") << "Skipping prefetched item [ Name: " << titem->getName() + << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl; continue; } gInventory.updateItem(titem); -- cgit v1.2.3 From 6c56c77ec575141963c5de8dfa228253fe175bc3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 24 May 2013 08:53:21 -0400 Subject: SH-4027 WIP - initial implementation of item update via AIS. --- indra/newview/llinventorymodel.cpp | 93 +++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 73ef3e60da..06c614aeaa 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1196,6 +1196,36 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS onObjectDeletedFromServer(*it, false); } + if (update.has("item_id")) + { + // 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) + { + LLSD changes; + if (update.has("name") && update["name"] != item->getName()) + { + changes["name"] = update["name"]; + } + if (update.has("desc") && update["desc"] != item->getActualDescription()) + { + changes["desc"] = update["desc"]; + } + onItemUpdated(item_id,changes); + } + else if (cat) + { + llerrs << "don't handle cat update yet" << llendl; + } + else + { + llerrs << "don't handle creation case yet" << llendl; + } + + } + // 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. @@ -1212,10 +1242,71 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS } } #endif - } +void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates) +{ + U32 mask = LLInventoryObserver::NONE; + + LLPointer item = gInventory.getItem(item_id); + LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << llendl; + if(item) + { + for (LLSD::map_const_iterator it = updates.beginMap(); + it != updates.endMap(); ++it) + { + if (it->first == "name") + { + llinfos << "Updating name from " << item->getName() << " to " << it->second.asString() << llendl; + item->rename(it->second.asString()); + mask |= LLInventoryObserver::LABEL; + } + else if (it->first == "desc") + { + llinfos << "Updating description from " << item->getActualDescription() + << " to " << it->second.asString() << llendl; + item->setDescription(it->second.asString()); + } + else + { + llerrs << "unhandled updates for field: " << it->first << llendl; + } + } + mask |= LLInventoryObserver::INTERNAL; + addChangedMask(mask, item->getUUID()); + gInventory.notifyObservers(); // do we want to be able to make this optional? + } +} + +void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates) +{ + U32 mask = LLInventoryObserver::NONE; + + LLPointer cat = gInventory.getCategory(cat_id); + LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << llendl; + if(cat) + { + for (LLSD::map_const_iterator it = updates.beginMap(); + it != updates.endMap(); ++it) + { + if (it->first == "name") + { + llinfos << "Updating name from " << cat->getName() << " to " << it->second.asString() << llendl; + cat->rename(it->second.asString()); + mask |= LLInventoryObserver::LABEL; + } + else + { + llerrs << "unhandled updates for field: " << it->first << llendl; + } + } + mask |= LLInventoryObserver::INTERNAL; + addChangedMask(mask, cat->getUUID()); + gInventory.notifyObservers(); // do we want to be able to make this optional? + } +} + // Update model after descendents have been purged. void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links) { -- cgit v1.2.3 From 34d2cd03765b6b9b582035a933f4ec11fb262ff4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 24 May 2013 15:51:33 -0400 Subject: SH-4207 WIP - use item updates with callback when updating link descriptions. Reworked updateAppearanceFromCOF() cof-validation stages. --- indra/newview/llinventorymodel.cpp | 51 ++++++-------------------------------- 1 file changed, 8 insertions(+), 43 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 06c614aeaa..38fa3c36e3 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1213,7 +1213,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS { changes["desc"] = update["desc"]; } - onItemUpdated(item_id,changes); + onItemUpdated(item_id,changes,true); } else if (cat) { @@ -1245,7 +1245,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS } -void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates) +void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version) { U32 mask = LLInventoryObserver::NONE; @@ -1275,6 +1275,12 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates) } mask |= LLInventoryObserver::INTERNAL; addChangedMask(mask, item->getUUID()); + if (update_parent_version) + { + // Descendent count is unchanged, but folder version incremented. + LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), 0); + accountForUpdate(up); + } gInventory.notifyObservers(); // do we want to be able to make this optional? } } @@ -1852,47 +1858,6 @@ void LLInventoryModel::accountForUpdate( } } - -/* -void LLInventoryModel::incrementCategoryVersion(const LLUUID& category_id) -{ - LLViewerInventoryCategory* cat = getCategory(category_id); - if(cat) - { - S32 version = cat->getVersion(); - if(LLViewerInventoryCategory::VERSION_UNKNOWN != version) - { - cat->setVersion(version + 1); - llinfos << "IncrementVersion: " << cat->getName() << " " - << cat->getVersion() << llendl; - } - else - { - llinfos << "Attempt to increment version when unknown: " - << category_id << llendl; - } - } - else - { - llinfos << "Attempt to increment category: " << category_id << llendl; - } -} -void LLInventoryModel::incrementCategorySetVersion( - const std::set& categories) -{ - if(!categories.empty()) - { - std::set::const_iterator it = categories.begin(); - std::set::const_iterator end = categories.end(); - for(; it != end; ++it) - { - incrementCategoryVersion(*it); - } - } -} -*/ - - LLInventoryModel::EHasChildren LLInventoryModel::categoryHasChildren( const LLUUID& cat_id) const { -- cgit v1.2.3 From f7c9739fd9bb4355765ecff4b92e879b38302e49 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 5 Jun 2013 15:13:48 -0400 Subject: SH-3635 WIP - COF slammer works in AISv3 regions. Extensive rework of onAISUpdateReceived. --- indra/newview/llinventorymodel.cpp | 167 +++++++++++++++++++++++++++++++------ 1 file changed, 141 insertions(+), 26 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 38fa3c36e3..1a5e76183c 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1172,77 +1172,188 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS { LL_DEBUGS("Inventory") << "ais update " << context << ":" << ll_pretty_print_sd(update) << llendl; + // Track changes to descendent counts for accounting. + std::map cat_deltas; + typedef std::map > deferred_item_map_t; + deferred_item_map_t items_created; + deferred_item_map_t items_updated; + std::set 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 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 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::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 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 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::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 +1506,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 obj = getObject(object_id); if(obj) @@ -1406,9 +1517,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); -- cgit v1.2.3 From ca806315a98627b29a4933cbf8b27431ca43dd0f Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 5 Jun 2013 15:52:44 -0400 Subject: SH-3635 WIP - logging cleanup, moved some big dumps into separate XML files --- indra/newview/llinventorymodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 1a5e76183c..c0c48d6695 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1170,7 +1170,10 @@ 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 cat_deltas; -- cgit v1.2.3 From bee76e305214598b2cb148e399d86e28d80287ca Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 6 Jun 2013 17:59:16 -0400 Subject: SH-4166 WIP - fix for a permissions issue that was preventing cof-created links from being reordered in outfits. --- indra/newview/llinventorymodel.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index c0c48d6695..532d3a3495 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1247,6 +1247,13 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS BOOL rv = new_link->unpackMessage(link_map); if (rv) { + LLPermissions default_perms; + default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null); + default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE); + new_link->setPermissions(default_perms); + LLSaleInfo default_sale_info; + new_link->setSaleInfo(default_sale_info); + //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl; items_created[link_id] = new_link; const LLUUID& parent_id = new_link->getParentUUID(); cat_deltas[parent_id]++; -- cgit v1.2.3 From 41694a902dc8cfebebb6e23691d41cb5627fa5a1 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 7 Jun 2013 10:35:07 -0400 Subject: SH-4216 WIP - broke up the onAISUpdateReceived monolith --- indra/newview/llinventorymodel.cpp | 252 ++++++++++++++++++++++--------------- 1 file changed, 149 insertions(+), 103 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 532d3a3495..3c7539a7f9 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1154,70 +1154,70 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, notifyObservers(); } -void parse_llsd_uuid_array(const LLSD& content, const std::string& name, uuid_vec_t& ids) +class AISUpdate { - ids.clear(); - if (content.has(name)) - { - for(LLSD::array_const_iterator it = content[name].beginArray(), - end = content[name].endArray(); - it != end; ++it) - { - ids.push_back((*it).asUUID()); - } - } -} - -void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) -{ - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) - { - dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); - } +public: + AISUpdate(const LLSD& update); + void parseUpdate(const LLSD& update); + void parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids); + void parseLink(const LLUUID& link_id, const LLSD& link_map); + void parseCreatedLinks(const LLSD& links); + void doUpdate(); +private: + typedef std::map uuid_int_map_t; + uuid_int_map_t mCatDeltas; + uuid_int_map_t mCatVersions; - // Track changes to descendent counts for accounting. - std::map cat_deltas; typedef std::map > deferred_item_map_t; - deferred_item_map_t items_created; - deferred_item_map_t items_updated; - std::set objects_deleted; + deferred_item_map_t mItemsCreated; + deferred_item_map_t mItemsUpdated; - // parse _categories_removed -> objects_deleted + std::set mObjectsDeleted; + uuid_vec_t mItemsCreatedIds; +}; + +AISUpdate::AISUpdate(const LLSD& update) +{ + parseUpdate(update); +} + +void AISUpdate::parseUpdate(const LLSD& update) +{ + // parse _categories_removed -> mObjectsDeleted uuid_vec_t cat_ids; - parse_llsd_uuid_array(update,"_categories_removed",cat_ids); + parseUUIDArray(update,"_categories_removed",cat_ids); for (uuid_vec_t::const_iterator it = cat_ids.begin(); it != cat_ids.end(); ++it) { - LLViewerInventoryCategory *cat = getCategory(*it); - cat_deltas[cat->getParentUUID()]--; - objects_deleted.insert(*it); + LLViewerInventoryCategory *cat = gInventory.getCategory(*it); + mCatDeltas[cat->getParentUUID()]--; + mObjectsDeleted.insert(*it); } - // parse _categories_items_removed -> objects_deleted + // parse _categories_items_removed -> mObjectsDeleted uuid_vec_t item_ids; - parse_llsd_uuid_array(update,"_category_items_removed",item_ids); + parseUUIDArray(update,"_category_items_removed",item_ids); for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) { - LLViewerInventoryItem *item = getItem(*it); - cat_deltas[item->getParentUUID()]--; - objects_deleted.insert(*it); + LLViewerInventoryItem *item = gInventory.getItem(*it); + mCatDeltas[item->getParentUUID()]--; + mObjectsDeleted.insert(*it); } - // parse _broken_links_removed -> objects_deleted + // parse _broken_links_removed -> mObjectsDeleted uuid_vec_t broken_link_ids; - parse_llsd_uuid_array(update,"_broken_links_removed",broken_link_ids); + parseUUIDArray(update,"_broken_links_removed",broken_link_ids); for (uuid_vec_t::const_iterator it = broken_link_ids.begin(); it != broken_link_ids.end(); ++it) { - LLViewerInventoryItem *item = getItem(*it); - cat_deltas[item->getParentUUID()]--; - objects_deleted.insert(*it); + LLViewerInventoryItem *item = gInventory.getItem(*it); + mCatDeltas[item->getParentUUID()]--; + mObjectsDeleted.insert(*it); } // parse _created_items - uuid_vec_t created_item_ids; - parse_llsd_uuid_array(update,"_created_items",created_item_ids); + parseUUIDArray(update,"_created_items",mItemsCreatedIds); if (update.has("_embedded")) { @@ -1227,48 +1227,13 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS it != end; ++it) { const std::string& field = (*it).first; - + // parse created links if (field == "link") { 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 new_link(new LLViewerInventoryItem); - BOOL rv = new_link->unpackMessage(link_map); - if (rv) - { - LLPermissions default_perms; - default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null); - default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE); - new_link->setPermissions(default_perms); - LLSaleInfo default_sale_info; - new_link->setSaleInfo(default_sale_info); - //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl; - 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; - } - } - } + parseCreatedLinks(links); + } else { llwarns << "unrecognized embedded field " << field << llendl; @@ -1285,11 +1250,11 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS BOOL rv = new_item->unpackMessage(update); if (rv) { - items_updated[item_id] = new_item; + mItemsUpdated[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()]; + mCatDeltas[new_item->getParentUUID()]; } else { @@ -1297,10 +1262,86 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS } } + // Parse updated category versions. + 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) + { + const LLUUID id((*it).first); + S32 version = (*it).second.asInteger(); + mCatVersions[id] = version; + } + } +} + +void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids) +{ + ids.clear(); + if (content.has(name)) + { + for(LLSD::array_const_iterator it = content[name].beginArray(), + end = content[name].endArray(); + it != end; ++it) + { + ids.push_back((*it).asUUID()); + } + } +} + +void AISUpdate::parseLink(const LLUUID& link_id, const LLSD& link_map) +{ + LLPointer new_link(new LLViewerInventoryItem); + BOOL rv = new_link->unpackMessage(link_map); + if (rv) + { + LLPermissions default_perms; + default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null); + default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE); + new_link->setPermissions(default_perms); + LLSaleInfo default_sale_info; + new_link->setSaleInfo(default_sale_info); + //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl; + mItemsCreated[link_id] = new_link; + const LLUUID& parent_id = new_link->getParentUUID(); + mCatDeltas[parent_id]++; + } + else + { + llwarns << "failed to parse" << llendl; + } +} + +void AISUpdate::parseCreatedLinks(const LLSD& links) +{ + 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(mItemsCreatedIds.begin(), + mItemsCreatedIds.end(),link_id); + if (pos != mItemsCreatedIds.end()) + { + parseLink(link_id,link_map); + } + else + { + LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl; + } + } +} + +void AISUpdate::doUpdate() +{ // Do descendent/version accounting. // Can remove this if/when we use the version info directly. - for (std::map::const_iterator catit = cat_deltas.begin(); - catit != cat_deltas.end(); ++catit) + for (std::map::const_iterator catit = mCatDeltas.begin(); + catit != mCatDeltas.end(); ++catit) { const LLUUID cat_id(catit->first); S32 delta = catit->second; @@ -1311,27 +1352,22 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS // 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. - const std::string& ucv = "_updated_category_versions"; - if (update.has(ucv)) + for (uuid_int_map_t::iterator ucv_it = mCatVersions.begin(); + ucv_it != mCatVersions.end(); ++ucv_it) { - for(LLSD::map_const_iterator it = update[ucv].beginMap(), - end = update[ucv].endMap(); - it != end; ++it) + const LLUUID id = ucv_it->first; + S32 version = ucv_it->second; + LLViewerInventoryCategory *cat = gInventory.getCategory(id); + if (cat->getVersion() != version) { - 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; - } + llwarns << "Possible version mismatch, viewer " << cat->getVersion() + << " server " << version << llendl; } } // CREATE ITEMS - for (deferred_item_map_t::const_iterator create_it = items_created.begin(); - create_it != items_created.end(); ++create_it) + for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin(); + create_it != mItemsCreated.end(); ++create_it) { LLUUID item_id(create_it->first); LLPointer new_item = create_it->second; @@ -1344,8 +1380,8 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS } // UPDATE ITEMS - for (deferred_item_map_t::const_iterator update_it = items_updated.begin(); - update_it != items_updated.end(); ++update_it) + for (deferred_item_map_t::const_iterator update_it = mItemsUpdated.begin(); + update_it != mItemsUpdated.end(); ++update_it) { LLUUID item_id(update_it->first); LLPointer new_item = update_it->second; @@ -1357,13 +1393,23 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS } // DELETE OBJECTS - for (std::set::const_iterator del_it = objects_deleted.begin(); - del_it != objects_deleted.end(); ++del_it) + for (std::set::const_iterator del_it = mObjectsDeleted.begin(); + del_it != mObjectsDeleted.end(); ++del_it) { LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl; - onObjectDeletedFromServer(*del_it, false, false); + gInventory.onObjectDeletedFromServer(*del_it, false, false); + } +} + +void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) +{ + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); } + AISUpdate ais_update(update); // parse update llsd into stuff to do. + ais_update.doUpdate(); // execute the updates in the appropriate order. } void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version) -- cgit v1.2.3 From 89e3959cf393ce9eeb058304264d4f55f4fe9ca2 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 7 Jun 2013 12:58:04 -0400 Subject: SH-4216 WIP - moved AISv3 commands and responders to llaisapi.* files --- indra/newview/llinventorymodel.cpp | 248 +------------------------------------ 1 file changed, 1 insertion(+), 247 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 3c7539a7f9..6dc193292e 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llinventorymodel.h" +#include "llaisapi.h" #include "llagent.h" #include "llagentwearables.h" #include "llappearancemgr.h" @@ -1154,253 +1155,6 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, notifyObservers(); } -class AISUpdate -{ -public: - AISUpdate(const LLSD& update); - void parseUpdate(const LLSD& update); - void parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids); - void parseLink(const LLUUID& link_id, const LLSD& link_map); - void parseCreatedLinks(const LLSD& links); - void doUpdate(); -private: - typedef std::map uuid_int_map_t; - uuid_int_map_t mCatDeltas; - uuid_int_map_t mCatVersions; - - typedef std::map > deferred_item_map_t; - deferred_item_map_t mItemsCreated; - deferred_item_map_t mItemsUpdated; - - std::set mObjectsDeleted; - uuid_vec_t mItemsCreatedIds; -}; - -AISUpdate::AISUpdate(const LLSD& update) -{ - parseUpdate(update); -} - -void AISUpdate::parseUpdate(const LLSD& update) -{ - // parse _categories_removed -> mObjectsDeleted - uuid_vec_t cat_ids; - parseUUIDArray(update,"_categories_removed",cat_ids); - for (uuid_vec_t::const_iterator it = cat_ids.begin(); - it != cat_ids.end(); ++it) - { - LLViewerInventoryCategory *cat = gInventory.getCategory(*it); - mCatDeltas[cat->getParentUUID()]--; - mObjectsDeleted.insert(*it); - } - - // parse _categories_items_removed -> mObjectsDeleted - uuid_vec_t item_ids; - parseUUIDArray(update,"_category_items_removed",item_ids); - for (uuid_vec_t::const_iterator it = item_ids.begin(); - it != item_ids.end(); ++it) - { - LLViewerInventoryItem *item = gInventory.getItem(*it); - mCatDeltas[item->getParentUUID()]--; - mObjectsDeleted.insert(*it); - } - - // parse _broken_links_removed -> mObjectsDeleted - uuid_vec_t broken_link_ids; - parseUUIDArray(update,"_broken_links_removed",broken_link_ids); - for (uuid_vec_t::const_iterator it = broken_link_ids.begin(); - it != broken_link_ids.end(); ++it) - { - LLViewerInventoryItem *item = gInventory.getItem(*it); - mCatDeltas[item->getParentUUID()]--; - mObjectsDeleted.insert(*it); - } - - // parse _created_items - parseUUIDArray(update,"_created_items",mItemsCreatedIds); - - if (update.has("_embedded")) - { - const LLSD& embedded = update["_embedded"]; - for(LLSD::map_const_iterator it = embedded.beginMap(), - end = embedded.endMap(); - it != end; ++it) - { - const std::string& field = (*it).first; - - // parse created links - if (field == "link") - { - const LLSD& links = embedded["link"]; - parseCreatedLinks(links); - } - else - { - llwarns << "unrecognized embedded field " << field << llendl; - } - } - - } - - // Parse item update at the top level. - if (update.has("item_id")) - { - LLUUID item_id = update["item_id"].asUUID(); - LLPointer new_item(new LLViewerInventoryItem); - BOOL rv = new_item->unpackMessage(update); - if (rv) - { - mItemsUpdated[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. - mCatDeltas[new_item->getParentUUID()]; - } - else - { - llerrs << "unpack failed" << llendl; - } - } - - // Parse updated category versions. - 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) - { - const LLUUID id((*it).first); - S32 version = (*it).second.asInteger(); - mCatVersions[id] = version; - } - } -} - -void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids) -{ - ids.clear(); - if (content.has(name)) - { - for(LLSD::array_const_iterator it = content[name].beginArray(), - end = content[name].endArray(); - it != end; ++it) - { - ids.push_back((*it).asUUID()); - } - } -} - -void AISUpdate::parseLink(const LLUUID& link_id, const LLSD& link_map) -{ - LLPointer new_link(new LLViewerInventoryItem); - BOOL rv = new_link->unpackMessage(link_map); - if (rv) - { - LLPermissions default_perms; - default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null); - default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE); - new_link->setPermissions(default_perms); - LLSaleInfo default_sale_info; - new_link->setSaleInfo(default_sale_info); - //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl; - mItemsCreated[link_id] = new_link; - const LLUUID& parent_id = new_link->getParentUUID(); - mCatDeltas[parent_id]++; - } - else - { - llwarns << "failed to parse" << llendl; - } -} - -void AISUpdate::parseCreatedLinks(const LLSD& links) -{ - 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(mItemsCreatedIds.begin(), - mItemsCreatedIds.end(),link_id); - if (pos != mItemsCreatedIds.end()) - { - parseLink(link_id,link_map); - } - else - { - LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl; - } - } -} - -void AISUpdate::doUpdate() -{ - // Do descendent/version accounting. - // Can remove this if/when we use the version info directly. - for (std::map::const_iterator catit = mCatDeltas.begin(); - catit != mCatDeltas.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. - for (uuid_int_map_t::iterator ucv_it = mCatVersions.begin(); - ucv_it != mCatVersions.end(); ++ucv_it) - { - const LLUUID id = ucv_it->first; - S32 version = ucv_it->second; - LLViewerInventoryCategory *cat = gInventory.getCategory(id); - if (cat->getVersion() != version) - { - llwarns << "Possible version mismatch, viewer " << cat->getVersion() - << " server " << version << llendl; - } - } - - // CREATE ITEMS - for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin(); - create_it != mItemsCreated.end(); ++create_it) - { - LLUUID item_id(create_it->first); - LLPointer 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 = mItemsUpdated.begin(); - update_it != mItemsUpdated.end(); ++update_it) - { - LLUUID item_id(update_it->first); - LLPointer 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::const_iterator del_it = mObjectsDeleted.begin(); - del_it != mObjectsDeleted.end(); ++del_it) - { - LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl; - gInventory.onObjectDeletedFromServer(*del_it, false, false); - } -} - void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) { if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) -- cgit v1.2.3 From 2d0b329003d0350c12ce4686f1261e68ce39573b Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 17 Jun 2013 16:20:17 -0400 Subject: SH-4238 WIP - postpone calling notifyObservers until all deletes are processed. --- indra/newview/llinventorymodel.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6dc193292e..aadf87ab35 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1157,6 +1157,7 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) { + LLTimer timer; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); @@ -1164,6 +1165,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS AISUpdate ais_update(update); // parse update llsd into stuff to do. ais_update.doUpdate(); // execute the updates in the appropriate order. + llinfos << "elapsed: " << timer.getElapsedTimeF32() << llendl; } void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version) @@ -1316,7 +1318,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, bool update_parent_version) +void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links, bool update_parent_version, bool do_notify_observers) { LLPointer obj = getObject(object_id); if(obj) @@ -1337,13 +1339,13 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f // From purgeObject() LLPreview::hide(object_id); - deleteObject(object_id, fix_broken_links); + deleteObject(object_id, fix_broken_links, do_notify_observers); } } // Delete a particular inventory object by ID. -void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links) +void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, bool do_notify_observers) { lldebugs << "LLInventoryModel::deleteObject()" << llendl; LLPointer obj = getObject(id); @@ -1402,7 +1404,10 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links) { updateLinkedObjectsFromPurge(id); } - notifyObservers(); + if (do_notify_observers) + { + notifyObservers(); + } } void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) -- cgit v1.2.3 From 3e0e236f33a866a3962295a99495fd1159532ba8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 24 Jun 2013 15:42:27 -0400 Subject: SH-4243 WIP - cleaned up callback structure for createNewCategory, modified makeNewOutfitLinks() to wait for category creation before populating. --- indra/newview/llinventorymodel.cpp | 72 +++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 39 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index aadf87ab35..82d58523ce 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -472,11 +472,9 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder LOG_CLASS(LLCreateInventoryCategoryResponder); public: LLCreateInventoryCategoryResponder(LLInventoryModel* model, - void (*callback)(const LLSD&, void*), - void* user_data) : - mModel(model), - mCallback(callback), - mData(user_data) + boost::optional callback): + mModel(model), + mCallback(callback) { } @@ -497,7 +495,7 @@ protected: } LLUUID category_id = content["folder_id"].asUUID(); - + LL_DEBUGS("Avatar") << ll_pretty_print_sd(content) << llendl; // Add the category to the internal representation LLPointer cat = new LLViewerInventoryCategory( category_id, @@ -510,17 +508,15 @@ protected: LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); mModel->accountForUpdate(update); mModel->updateCategory(cat); - - if (mCallback && mData) + + if (mCallback) { - mCallback(content, mData); + mCallback.get()(content); } - } private: - void (*mCallback)(const LLSD&, void*); - void* mData; + boost::optional mCallback; LLInventoryModel* mModel; }; @@ -531,8 +527,7 @@ private: LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, const std::string& pname, - void (*callback)(const LLSD&, void*), //Default to NULL - void* user_data) //Default to NULL + boost::optional callback) { LLUUID id; @@ -559,33 +554,32 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type)); } - if ( callback && user_data ) //callback required for acked message. + LLViewerRegion* viewer_region = gAgent.getRegion(); + std::string url; + if ( viewer_region ) + url = viewer_region->getCapability("CreateInventoryCategory"); + + if (!url.empty() && callback.get_ptr()) { - LLViewerRegion* viewer_region = gAgent.getRegion(); - std::string url; - if ( viewer_region ) - url = viewer_region->getCapability("CreateInventoryCategory"); + //Let's use the new capability. - if (!url.empty()) - { - //Let's use the new capability. - - LLSD request, body; - body["folder_id"] = id; - body["parent_id"] = parent_id; - body["type"] = (LLSD::Integer) preferred_type; - body["name"] = name; - - request["message"] = "CreateInventoryCategory"; - request["payload"] = body; - - // viewer_region->getCapAPI().post(request); - LLHTTPClient::post( - url, - body, - new LLCreateInventoryCategoryResponder(this, callback, user_data) ); - return LLUUID::null; - } + LLSD request, body; + body["folder_id"] = id; + body["parent_id"] = parent_id; + body["type"] = (LLSD::Integer) preferred_type; + body["name"] = name; + + request["message"] = "CreateInventoryCategory"; + request["payload"] = body; + + LL_DEBUGS("Avatar") << "create category request: " << ll_pretty_print_sd(request) << llendl; + // viewer_region->getCapAPI().post(request); + LLHTTPClient::post( + url, + body, + new LLCreateInventoryCategoryResponder(this, callback) ); + + return LLUUID::null; } // Add the category to the internal representation -- cgit v1.2.3 From ffd7b0d7e7ef13510d7299e601a71c7fedb0a4d1 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 25 Jun 2013 17:52:02 -0400 Subject: SH-4305 WIP --- indra/newview/llinventorymodel.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 82d58523ce..e1fd2e02fa 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -472,7 +472,7 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder LOG_CLASS(LLCreateInventoryCategoryResponder); public: LLCreateInventoryCategoryResponder(LLInventoryModel* model, - boost::optional callback): + boost::optional callback): mModel(model), mCallback(callback) { @@ -511,12 +511,12 @@ protected: if (mCallback) { - mCallback.get()(content); + mCallback.get()(category_id); } } private: - boost::optional mCallback; + boost::optional mCallback; LLInventoryModel* mModel; }; @@ -527,7 +527,7 @@ private: LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, const std::string& pname, - boost::optional callback) + boost::optional callback) { LLUUID id; -- cgit v1.2.3 From a85fa3b10a406218cabfecc0d592e816f8dfdb53 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 11 Jul 2013 15:15:04 -0700 Subject: Adding support for COPY methods to httpclient. Implementing viewer-side use of AISv3 COPY library folder operation. (SH-4304) --- indra/newview/llinventorymodel.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index e1fd2e02fa..0d99bea3fc 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1718,7 +1718,6 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const LLViewerInventoryCategory* cat = getCategory(update.mCategoryID); if(cat) { - bool accounted = false; S32 version = cat->getVersion(); if(version != LLViewerInventoryCategory::VERSION_UNKNOWN) { @@ -1733,22 +1732,27 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const } if(descendents_server == descendents_actual) { - accounted = true; descendents_actual += update.mDescendentDelta; cat->setDescendentCount(descendents_actual); cat->setVersion(++version); - lldebugs << "accounted: '" << cat->getName() << "' " + LL_DEBUGS("Inventory") << "accounted: '" << cat->getName() << "' " << version << " with " << descendents_actual - << " descendents." << llendl; + << " descendents." << LL_ENDL; + } + else + { + // Error condition, this means that the category did not register that + // it got new descendents (perhaps because it is still being loaded) + // which means its descendent count will be wrong. + llwarns << "Accounting failed for '" << cat->getName() << "' version:" + << version << " due to mismatched descendent count: server == " + << descendents_server << ", viewer == " << descendents_actual << llendl; } } - if(!accounted) + else { - // Error condition, this means that the category did not register that - // it got new descendents (perhaps because it is still being loaded) - // which means its descendent count will be wrong. - llwarns << "Accounting failed for '" << cat->getName() << "' version:" - << version << llendl; + llwarns << "Accounting failed for '" << cat->getName() << "' version: unknown (" + << version << ")" << llendl; } } else -- cgit v1.2.3 From 7af477f796f9926dfec4aaa1336047b41144fbbb Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 17 Jul 2013 15:32:06 -0400 Subject: SH-4344 FIX - return the lowest UUID for a child of root with the desired preferred type. Also removed some duplicate code between findCategoryUUIDForType and findLibraryCategoryUUIDForType --- indra/newview/llinventorymodel.cpp | 63 ++++++++++++-------------------------- 1 file changed, 20 insertions(+), 43 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 0d99bea3fc..be1a396fff 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -388,16 +388,13 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id) mItemLock[cat_id] = false; } -// findCategoryUUIDForType() returns the uuid of the category that -// specifies 'type' as what it defaults to containing. The category is -// not necessarily only for that type. *NOTE: This will create a new -// inventory category on the fly if one does not exist. -const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder/*, - bool find_in_library*/) +const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( + LLFolderType::EType preferred_type, + bool create_folder, + const LLUUID& root_id) { LLUUID rv = LLUUID::null; - const LLUUID &root_id = /*(find_in_library) ? gInventory.getLibraryRootFolderID() :*/ gInventory.getRootFolderID(); if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) { rv = root_id; @@ -413,14 +410,17 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe { if(cats->get(i)->getPreferredType() == preferred_type) { - rv = cats->get(i)->getUUID(); - break; + const LLUUID& folder_id = cats->get(i)->getUUID(); + if (rv.isNull() || folder_id < rv) + { + rv = folder_id; + } } } } } - if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/)) + if(rv.isNull() && isInventoryUsable() && create_folder) { if(root_id.notNull()) { @@ -430,41 +430,18 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe return rv; } -const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder) +// findCategoryUUIDForType() returns the uuid of the category that +// specifies 'type' as what it defaults to containing. The category is +// not necessarily only for that type. *NOTE: This will create a new +// inventory category on the fly if one does not exist. +const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder) { - LLUUID rv = LLUUID::null; - - const LLUUID &root_id = gInventory.getLibraryRootFolderID(); - if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) - { - rv = root_id; - } - else if (root_id.notNull()) - { - cat_array_t* cats = NULL; - cats = get_ptr_in_map(mParentChildCategoryTree, root_id); - if(cats) - { - S32 count = cats->count(); - for(S32 i = 0; i < count; ++i) - { - if(cats->get(i)->getPreferredType() == preferred_type) - { - rv = cats->get(i)->getUUID(); - break; - } - } - } - } + return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getRootFolderID()); +} - if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/)) - { - if(root_id.notNull()) - { - return createNewCategory(root_id, preferred_type, LLStringUtil::null); - } - } - return rv; +const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder) +{ + return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getLibraryRootFolderID()); } class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder -- cgit v1.2.3 From e26268add0d10cb7609afd9070f00d0331b78c4e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 1 Nov 2013 11:02:51 -0400 Subject: SH-4595 WIP - reworked descendents of LLInventoryAddedObserver to use gInventory.getAddedIDs(). LLInventoryAddedObserver isn't really needed anymore, but leaving it in as a debugging point at least for now. --- indra/newview/llinventorymodel.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index be1a396fff..e9bbf3a7cd 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1454,6 +1454,7 @@ void LLInventoryModel::notifyObservers() mModifyMask = LLInventoryObserver::NONE; mChangedItemIDs.clear(); + mAddedItemIDs.clear(); mIsNotifyObservers = FALSE; } @@ -1473,13 +1474,18 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) if (referent.notNull()) { mChangedItemIDs.insert(referent); - } + + if (mask & LLInventoryObserver::ADD) + { + mAddedItemIDs.insert(referent); + } - // Update all linked items. Starting with just LABEL because I'm - // not sure what else might need to be accounted for this. - if (mModifyMask & LLInventoryObserver::LABEL) - { - addChangedMaskForLinks(referent, LLInventoryObserver::LABEL); + // Update all linked items. Starting with just LABEL because I'm + // not sure what else might need to be accounted for this. + if (mask & LLInventoryObserver::LABEL) + { + addChangedMaskForLinks(referent, LLInventoryObserver::LABEL); + } } } -- cgit v1.2.3 From 6ea320198afcd3080fd7fcdfcb5829b5e8ef2c31 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 4 Nov 2013 15:55:04 -0500 Subject: SH-4595 WIP - use new LLInventoryObserver::CREATE flag to distinguish newly created items from existing ones being added to inventory. --- indra/newview/llinventorymodel.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index e9bbf3a7cd..1ad70492ca 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -774,9 +774,8 @@ bool LLInventoryModel::isInventoryUsable() const // Calling this method with an inventory item will either change an // existing item with a matching item_id, or will add the item to the // current inventory. -U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) +U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) { - U32 mask = LLInventoryObserver::NONE; if(item->getUUID().isNull()) { return mask; @@ -2652,10 +2651,11 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account) } U32 changes = 0x0; + U32 mask = account ? LLInventoryObserver::CREATE : 0x0; //as above, this loop never seems to loop more than once per call for (item_array_t::iterator it = items.begin(); it != items.end(); ++it) { - changes |= gInventory.updateItem(*it); + changes |= gInventory.updateItem(*it, mask); } gInventory.notifyObservers(); gViewerWindow->getWindow()->decBusyCount(); -- cgit v1.2.3 From c1f60e7f2fe1775d8ca5f79af23579ac8a1fd851 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 15 Nov 2013 13:33:31 -0500 Subject: SH-4621 WIP --- indra/newview/llinventorymodel.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 1ad70492ca..3dbc1ae288 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1467,6 +1467,19 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) // (which is in the process of processing the list of items marked for change). // This means the change may fail to be processed. llwarns << "Adding changed mask within notify observers! Change will likely be lost." << llendl; + LLViewerInventoryItem *item = getItem(referent); + if (item) + { + llwarns << "Item " << item->getName() << llendl; + } + else + { + LLViewerInventoryCategory *cat = getCategory(referent); + if (cat) + { + llwarns << "Category " << cat->getName() << llendl; + } + } } mModifyMask |= mask; @@ -2344,9 +2357,10 @@ void LLInventoryModel::buildParentChildMap() // The inv tree is built. mIsAgentInvUsable = true; - llinfos << "Inventory initialized, notifying observers" << llendl; - addChangedMask(LLInventoryObserver::ALL, LLUUID::null); - notifyObservers(); + // notifyObservers() has been moved to + // llstartup/idle_startup() after this func completes. + // Allows some system categories to be created before + // observers start firing. } } @@ -2356,6 +2370,14 @@ void LLInventoryModel::buildParentChildMap() } } +void LLInventoryModel::createCommonSystemCategories() +{ + gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH,true); + gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true); + gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD,true); + gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS,true); +} + struct LLUUIDAndName { LLUUIDAndName() {} -- cgit v1.2.3 From 8179175e6e6078fab9dc16cf02b5ee744955cd7d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 18 Nov 2013 13:19:43 -0500 Subject: SH-4578 WIP - cleaner folder version accounting --- indra/newview/llinventorymodel.cpp | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 3dbc1ae288..52b6e4bf3b 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -105,17 +105,7 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item) if(c->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN) { S32 descendents_server = c->getDescendentCount(); - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - mModel->getDirectDescendentsOf( - c->getUUID(), - cats, - items); - S32 descendents_actual = 0; - if(cats && items) - { - descendents_actual = cats->count() + items->count(); - } + S32 descendents_actual = c->getViewerDescendentCount(); if(descendents_server == descendents_actual) { mCachedCatIDs.insert(c->getUUID()); @@ -1717,14 +1707,7 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const if(version != LLViewerInventoryCategory::VERSION_UNKNOWN) { S32 descendents_server = cat->getDescendentCount(); - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - getDirectDescendentsOf(update.mCategoryID, cats, items); - S32 descendents_actual = 0; - if(cats && items) - { - descendents_actual = cats->count() + items->count(); - } + S32 descendents_actual = cat->getViewerDescendentCount(); if(descendents_server == descendents_actual) { descendents_actual += update.mDescendentDelta; @@ -1821,14 +1804,7 @@ bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const if(cat && (cat->getVersion()!=LLViewerInventoryCategory::VERSION_UNKNOWN)) { S32 descendents_server = cat->getDescendentCount(); - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - getDirectDescendentsOf(cat_id, cats, items); - S32 descendents_actual = 0; - if(cats && items) - { - descendents_actual = cats->count() + items->count(); - } + S32 descendents_actual = cat->getViewerDescendentCount(); if(descendents_server == descendents_actual) { return true; -- cgit v1.2.3 From d26ea73ce8e6c76517e836316150ca76f5f925d9 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 18 Nov 2013 16:03:30 -0500 Subject: SH-4625 FIX - changed a warning that didn't really indicate a problem to an info statement --- indra/newview/llinventorymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 52b6e4bf3b..6b1bf69b5e 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3704,7 +3704,7 @@ bool LLInventoryModel::validate() const if (cat_lock > 0 || item_lock > 0) { - llwarns << "Found locks on some categories: sub-cat arrays " + llinfos << "Found locks on some categories: sub-cat arrays " << cat_lock << ", item arrays " << item_lock << llendl; } if (desc_unknown_count != 0) -- cgit v1.2.3 From c0d780cb4473c02e885c67fbc1bc30e87536d1b8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 25 Nov 2013 16:52:58 -0500 Subject: SH-4613 WIP - add CREATE mask bit for newly created items in AISUpdate::doUpdate() - needed for some inventory observers. --- indra/newview/llinventorymodel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6b1bf69b5e..891d7c821c 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -944,7 +944,7 @@ LLInventoryModel::item_array_t* LLInventoryModel::getUnlockedItemArray(const LLU // Calling this method with an inventory category will either change // an existing item with the matching id, or it will add the category. -void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat) +void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask) { if(cat->getUUID().isNull()) { @@ -961,7 +961,6 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat) if(old_cat) { // We already have an old category, modify it's values - U32 mask = LLInventoryObserver::NONE; LLUUID old_parent_id = old_cat->getParentUUID(); LLUUID new_parent_id = cat->getParentUUID(); if(old_parent_id != new_parent_id) @@ -1128,6 +1127,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS llinfos << "elapsed: " << timer.getElapsedTimeF32() << llendl; } +// Does not appear to be used currently. void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version) { U32 mask = LLInventoryObserver::NONE; @@ -1168,6 +1168,7 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, } } +// Not used? void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates) { U32 mask = LLInventoryObserver::NONE; -- cgit v1.2.3 From 940cde3938217daf348bd62f719cae262bad86b0 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 3 Dec 2013 11:49:29 -0500 Subject: SH-4640 WIP --- indra/newview/llinventorymodel.cpp | 174 +++++++++++++++++++++++++++++++------ 1 file changed, 148 insertions(+), 26 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 891d7c821c..2c63203773 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -127,6 +127,7 @@ LLInventoryModel gInventory; LLInventoryModel::LLInventoryModel() : mModifyMask(LLInventoryObserver::ALL), mChangedItemIDs(), + mBacklinkMMap(), mCategoryMap(), mItemMap(), mCategoryLock(), @@ -686,26 +687,8 @@ void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask) if (!obj || obj->getIsLinkType()) return; - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - LLLinkedItemIDMatches is_linked_item_match(object_id); - collectDescendentsIf(gInventory.getRootFolderID(), - cat_array, - item_array, - LLInventoryModel::INCLUDE_TRASH, - is_linked_item_match); - if (cat_array.empty() && item_array.empty()) - { - return; - } - for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin(); - cat_iter != cat_array.end(); - cat_iter++) - { - LLViewerInventoryCategory *linked_cat = (*cat_iter); - addChangedMask(mask, linked_cat->getUUID()); - }; - + LLInventoryModel::item_array_t item_array = + collectLinksTo(object_id,gInventory.getRootFolderID()); for (LLInventoryModel::item_array_t::iterator iter = item_array.begin(); iter != item_array.end(); iter++) @@ -733,11 +716,14 @@ LLViewerInventoryItem* LLInventoryModel::getLinkedItem(const LLUUID& object_id) return object_id.notNull() ? getItem(getLinkedItemID(object_id)) : NULL; } -LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID& id, - const LLUUID& start_folder_id) +LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id, + const LLUUID& start_folder_id) { + // Get item list via collectDescendents (slow!) item_array_t items; const LLInventoryObject *obj = getObject(id); + // FIXME - should be as below, but this is causing a stack-smashing crash of cause TBD... check in the REBUILD code. + //if (obj && obj->getIsLinkType()) if (!obj || obj->getIsLinkType()) return items; @@ -748,6 +734,38 @@ LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID items, LLInventoryModel::INCLUDE_TRASH, is_linked_item_match); + + // Get via backlinks - fast. + item_array_t fast_items; + std::pair range = mBacklinkMMap.equal_range(id); + for (backlink_mmap_t::iterator it = range.first; it != range.second; ++it) + { + LLViewerInventoryItem *item = getItem(it->second); + if (item) + { + fast_items.put(item); + } + } + + // Validate equivalence. + if (items.size() != fast_items.size()) + { + llwarns << "size mismatch, " << items.size() << " != " << fast_items.size() << llendl; + } + for (item_array_t::iterator ita = items.begin(); ita != items.end(); ++ita) + { + if (fast_items.find(*ita) == item_array_t::FAIL) + { + llwarns << "in descendents search but not fast search " << (*ita)->getUUID() << llendl; + } + } + for (item_array_t::iterator itb = fast_items.begin(); itb != fast_items.end(); ++itb) + { + if (items.find(*itb) == item_array_t::FAIL) + { + llwarns << "in fast search but not descendents search " << (*itb)->getUUID() << llendl; + } + } return items; } @@ -1355,11 +1373,16 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo mParentChildCategoryTree.erase(id); } addChangedMask(LLInventoryObserver::REMOVE, id); - + + bool is_link_type = obj->getIsLinkType(); + if (is_link_type) + { + removeBacklinkInfo(obj->getUUID(), obj->getLinkedUUID()); + } + // Can't have links to links, so there's no need for this update // if the item removed is a link. Can also skip if source of the // update is getting broken link info separately. - bool is_link_type = obj->getIsLinkType(); obj = NULL; // delete obj if (fix_broken_links && !is_link_type) { @@ -1373,7 +1396,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) { - LLInventoryModel::item_array_t item_array = collectLinkedItems(baseobj_id); + LLInventoryModel::item_array_t item_array = collectLinksTo(baseobj_id); // REBUILD is expensive, so clear the current change list first else // everything else on the changelist will also get rebuilt. @@ -1653,6 +1676,47 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category) } } +bool LLInventoryModel::hasBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) const +{ + std::pair range; + range = mBacklinkMMap.equal_range(target_id); + for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it) + { + if (it->second == link_id) + { + return true; + } + } + return false; +} + +void LLInventoryModel::addBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) +{ + if (!hasBacklinkInfo(link_id, target_id)) + { + mBacklinkMMap.insert(std::make_pair(target_id, link_id)); + } +} + +void LLInventoryModel::removeBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) +{ + std::pair range; + range = mBacklinkMMap.equal_range(target_id); + for (backlink_mmap_t::iterator it = range.first; it != range.second; ) + { + if (it->second == link_id) + { + backlink_mmap_t::iterator delete_it = it; // iterator will be invalidated by erase. + ++it; + mBacklinkMMap.erase(delete_it); + } + else + { + ++it; + } + } +} + void LLInventoryModel::addItem(LLViewerInventoryItem* item) { llassert(item); @@ -1674,7 +1738,13 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) { llinfos << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl; } - + if (item->getIsLinkType()) + { + // Add back-link from linked-to UUID. + const LLUUID& link_id = item->getUUID(); + const LLUUID& target_id = item->getLinkedUUID(); + addBacklinkInfo(link_id, target_id); + } mItemMap[item->getUUID()] = item; } } @@ -1693,6 +1763,7 @@ void LLInventoryModel::empty() mParentChildItemTree.end(), DeletePairedPointer()); mParentChildItemTree.clear(); + mBacklinkMMap.clear(); // forget all backlink information. mCategoryMap.clear(); // remove all references (should delete entries) mItemMap.clear(); // remove all references (should delete entries) mLastItem = NULL; @@ -3701,6 +3772,57 @@ bool LLInventoryModel::validate() const } } + // Link checking + if (item->getIsLinkType()) + { + const LLUUID& link_id = item->getUUID(); + const LLUUID& target_id = item->getLinkedUUID(); + LLViewerInventoryItem *target_item = getItem(target_id); + LLViewerInventoryCategory *target_cat = getCategory(target_id); + // Linked-to UUID should have back reference to this link. + if (!hasBacklinkInfo(link_id, target_id)) + { + llwarns << "link " << item->getUUID() << " type " << item->getActualType() + << " missing backlink info at target_id " << target_id + << llendl; + } + // Links should have referents. + if (item->getActualType() == LLAssetType::AT_LINK && !target_item) + { + llwarns << "broken item link " << item->getName() << " id " << item->getUUID() << llendl; + } + else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat) + { + llwarns << "broken folder link " << item->getName() << " id " << item->getUUID() << llendl; + } + if (target_item && target_item->getIsLinkType()) + { + llwarns << "link " << item->getName() << " references a link item " + << target_item->getName() << " " << target_item->getUUID() << llendl; + } + + // Links should not have backlinks. + std::pair range = mBacklinkMMap.equal_range(link_id); + if (range.first != range.second) + { + llwarns << "Link item " << item->getName() << " has backlinks!" << llendl; + } + } + else + { + // Check the backlinks of a non-link item. + const LLUUID& target_id = item->getUUID(); + std::pair range = mBacklinkMMap.equal_range(target_id); + for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it) + { + const LLUUID& link_id = it->second; + LLViewerInventoryItem *link_item = getItem(link_id); + if (!link_item || !link_item->getIsLinkType()) + { + llwarns << "invalid backlink from target " << item->getName() << " to " << link_id << llendl; + } + } + } } if (cat_lock > 0 || item_lock > 0) -- cgit v1.2.3 From 1320e5ddcd9fc3be526dcacbf4710f8bcf878665 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 3 Dec 2013 16:35:07 -0500 Subject: SH-4640 WIP - use backlinks in inventory --- indra/newview/llinventorymodel.cpp | 40 +++++--------------------------------- 1 file changed, 5 insertions(+), 35 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 2c63203773..268cb7d8b2 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -687,8 +687,7 @@ void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask) if (!obj || obj->getIsLinkType()) return; - LLInventoryModel::item_array_t item_array = - collectLinksTo(object_id,gInventory.getRootFolderID()); + LLInventoryModel::item_array_t item_array = collectLinksTo(object_id); for (LLInventoryModel::item_array_t::iterator iter = item_array.begin(); iter != item_array.end(); iter++) @@ -716,56 +715,27 @@ LLViewerInventoryItem* LLInventoryModel::getLinkedItem(const LLUUID& object_id) return object_id.notNull() ? getItem(getLinkedItemID(object_id)) : NULL; } -LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id, - const LLUUID& start_folder_id) +LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id) { // Get item list via collectDescendents (slow!) item_array_t items; const LLInventoryObject *obj = getObject(id); - // FIXME - should be as below, but this is causing a stack-smashing crash of cause TBD... check in the REBUILD code. + // FIXME - should be as in next line, but this is causing a + // stack-smashing crash of cause TBD... check in the REBUILD code. //if (obj && obj->getIsLinkType()) if (!obj || obj->getIsLinkType()) return items; - LLInventoryModel::cat_array_t cat_array; - LLLinkedItemIDMatches is_linked_item_match(id); - collectDescendentsIf((start_folder_id == LLUUID::null ? gInventory.getRootFolderID() : start_folder_id), - cat_array, - items, - LLInventoryModel::INCLUDE_TRASH, - is_linked_item_match); - - // Get via backlinks - fast. - item_array_t fast_items; std::pair range = mBacklinkMMap.equal_range(id); for (backlink_mmap_t::iterator it = range.first; it != range.second; ++it) { LLViewerInventoryItem *item = getItem(it->second); if (item) { - fast_items.put(item); + items.put(item); } } - // Validate equivalence. - if (items.size() != fast_items.size()) - { - llwarns << "size mismatch, " << items.size() << " != " << fast_items.size() << llendl; - } - for (item_array_t::iterator ita = items.begin(); ita != items.end(); ++ita) - { - if (fast_items.find(*ita) == item_array_t::FAIL) - { - llwarns << "in descendents search but not fast search " << (*ita)->getUUID() << llendl; - } - } - for (item_array_t::iterator itb = fast_items.begin(); itb != fast_items.end(); ++itb) - { - if (items.find(*itb) == item_array_t::FAIL) - { - llwarns << "in fast search but not descendents search " << (*itb)->getUUID() << llendl; - } - } return items; } -- cgit v1.2.3 From f6947e9ce5a5225c30dd347ee2e16392411c6d2f Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 19 Dec 2013 15:39:21 -0500 Subject: SH-4664 WIP - updated from from UpdateCreateInventoryItem to inventory observers. --- indra/newview/llinventorymodel.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 268cb7d8b2..1699088b99 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1514,7 +1514,7 @@ void LLInventoryModel::fetchInventoryResponder::httpSuccess() LLPointer titem = new LLViewerInventoryItem; titem->unpackMessage(content["items"][i]); - lldebugs << "LLInventoryModel::messageUpdateCore() item id:" + lldebugs << "LLInventoryModel::fetchInventoryResponder item id: " << titem->getUUID() << llendl; items.push_back(titem); // examine update for changes. @@ -2617,7 +2617,7 @@ void LLInventoryModel::registerCallbacks(LLMessageSystem* msg) void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, void**) { // do accounting and highlight new items if they arrive - if (gInventory.messageUpdateCore(msg, true)) + if (gInventory.messageUpdateCore(msg, true, LLInventoryObserver::UPDATE_CREATE)) { U32 callback_id; LLUUID item_id; @@ -2637,7 +2637,7 @@ void LLInventoryModel::processFetchInventoryReply(LLMessageSystem* msg, void**) } -bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account) +bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 mask) { //make sure our added inventory observer is active start_new_inventory_observer(); @@ -2691,7 +2691,10 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account) } U32 changes = 0x0; - U32 mask = account ? LLInventoryObserver::CREATE : 0x0; + if (account) + { + mask |= LLInventoryObserver::CREATE; + } //as above, this loop never seems to loop more than once per call for (item_array_t::iterator it = items.begin(); it != items.end(); ++it) { -- cgit v1.2.3 From 487ca1bad37883be0325b564ab557a8f77575388 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 14 May 2014 17:50:59 -0400 Subject: v-r -> s-e merge WIP --- indra/newview/llinventorymodel.cpp | 144 ++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 72 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 7b3aacd5e9..29b9c2b998 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -253,7 +253,7 @@ bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& LLInventoryObject *parent_object = getObject(object->getParentUUID()); if (!parent_object) { - llwarns << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << llendl; + LL_WARNS() << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << LL_ENDL; return false; } object = parent_object; @@ -522,7 +522,7 @@ protected: } LLUUID category_id = content["folder_id"].asUUID(); - LL_DEBUGS("Avatar") << ll_pretty_print_sd(content) << llendl; + LL_DEBUGS("Avatar") << ll_pretty_print_sd(content) << LL_ENDL; // Add the category to the internal representation LLPointer cat = new LLViewerInventoryCategory( category_id, @@ -599,7 +599,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, request["message"] = "CreateInventoryCategory"; request["payload"] = body; - LL_DEBUGS("Avatar") << "create category request: " << ll_pretty_print_sd(request) << llendl; + LL_DEBUGS("Avatar") << "create category request: " << ll_pretty_print_sd(request) << LL_ENDL; // viewer_region->getCapAPI().post(request); LLHTTPClient::post( url, @@ -791,7 +791,7 @@ LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id LLViewerInventoryItem *item = getItem(it->second); if (item) { - items.put(item); + items.push_back(item); } } @@ -1171,7 +1171,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS AISUpdate ais_update(update); // parse update llsd into stuff to do. ais_update.doUpdate(); // execute the updates in the appropriate order. - llinfos << "elapsed: " << timer.getElapsedTimeF32() << llendl; + LL_INFOS() << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; } // Does not appear to be used currently. @@ -1180,7 +1180,7 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, U32 mask = LLInventoryObserver::NONE; LLPointer item = gInventory.getItem(item_id); - LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << llendl; + LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << LL_ENDL; if(item) { for (LLSD::map_const_iterator it = updates.beginMap(); @@ -1188,19 +1188,19 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, { if (it->first == "name") { - llinfos << "Updating name from " << item->getName() << " to " << it->second.asString() << llendl; + LL_INFOS() << "Updating name from " << item->getName() << " to " << it->second.asString() << LL_ENDL; item->rename(it->second.asString()); mask |= LLInventoryObserver::LABEL; } else if (it->first == "desc") { - llinfos << "Updating description from " << item->getActualDescription() - << " to " << it->second.asString() << llendl; + LL_INFOS() << "Updating description from " << item->getActualDescription() + << " to " << it->second.asString() << LL_ENDL; item->setDescription(it->second.asString()); } else { - llerrs << "unhandled updates for field: " << it->first << llendl; + LL_ERRS() << "unhandled updates for field: " << it->first << LL_ENDL; } } mask |= LLInventoryObserver::INTERNAL; @@ -1221,7 +1221,7 @@ void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updat U32 mask = LLInventoryObserver::NONE; LLPointer cat = gInventory.getCategory(cat_id); - LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << llendl; + LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << LL_ENDL; if(cat) { for (LLSD::map_const_iterator it = updates.beginMap(); @@ -1229,13 +1229,13 @@ void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updat { if (it->first == "name") { - llinfos << "Updating name from " << cat->getName() << " to " << it->second.asString() << llendl; + LL_INFOS() << "Updating name from " << cat->getName() << " to " << it->second.asString() << LL_ENDL; cat->rename(it->second.asString()); mask |= LLInventoryObserver::LABEL; } else { - llerrs << "unhandled updates for field: " << it->first << llendl; + LL_ERRS() << "unhandled updates for field: " << it->first << LL_ENDL; } } mask |= LLInventoryObserver::INTERNAL; @@ -1270,12 +1270,12 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo categories, items, LLInventoryModel::INCLUDE_TRASH); - S32 count = items.count(); + S32 count = items.size(); LLUUID uu_id; for(S32 i = 0; i < count; ++i) { - uu_id = items.get(i)->getUUID(); + uu_id = items.at(i)->getUUID(); // This check prevents the deletion of a previously deleted item. // This is necessary because deletion is not done in a hierarchical @@ -1287,7 +1287,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo } } - count = categories.count(); + count = categories.size(); // Slightly kludgy way to make sure categories are removed // only after their child categories have gone away. @@ -1301,7 +1301,7 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo deleted_count = 0; for(S32 i = 0; i < count; ++i) { - uu_id = categories.get(i)->getUUID(); + uu_id = categories.at(i)->getUUID(); if (getCategory(uu_id)) { cat_array_t* cat_list = getUnlockedCatArray(uu_id); @@ -1317,8 +1317,8 @@ void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bo while (deleted_count > 0); if (total_deleted_count != count) { - llwarns << "Unexpected count of categories deleted, got " - << total_deleted_count << " expected " << count << llendl; + LL_WARNS() << "Unexpected count of categories deleted, got " + << total_deleted_count << " expected " << count << LL_ENDL; } //gInventory.validate(); } @@ -1386,7 +1386,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo { if (item_list->size()) { - llwarns << "Deleting cat " << id << " while it still has child items" << llendl; + LL_WARNS() << "Deleting cat " << id << " while it still has child items" << LL_ENDL; } delete item_list; mParentChildItemTree.erase(id); @@ -1396,7 +1396,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo { if (cat_list->size()) { - llwarns << "Deleting cat " << id << " while it still has child cats" << llendl; + LL_WARNS() << "Deleting cat " << id << " while it still has child cats" << LL_ENDL; } delete cat_list; mParentChildCategoryTree.erase(id); @@ -1513,14 +1513,14 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) LLViewerInventoryItem *item = getItem(referent); if (item) { - llwarns << "Item " << item->getName() << llendl; + LL_WARNS() << "Item " << item->getName() << LL_ENDL; } else { LLViewerInventoryCategory *cat = getCategory(referent); if (cat) { - llwarns << "Category " << cat->getName() << llendl; + LL_WARNS() << "Category " << cat->getName() << LL_ENDL; } } } @@ -2267,7 +2267,7 @@ void LLInventoryModel::buildParentChildMap() LL_INFOS() << "Lost category: " << cat->getUUID() << " - " << cat->getName() << LL_ENDL; ++lost; - lost_cats.put(cat); + lost_cats.push_back(cat); // notifyObservers() has been moved to // llstartup/idle_startup() after this func completes. // Allows some system categories to be created before @@ -2277,7 +2277,7 @@ void LLInventoryModel::buildParentChildMap() if (!gInventory.validate()) { - llwarns << "model failed validity check!" << llendl; + LL_WARNS() << "model failed validity check!" << LL_ENDL; } } @@ -3419,20 +3419,20 @@ bool LLInventoryModel::validate() const if (getRootFolderID().isNull()) { - llwarns << "no root folder id" << llendl; + LL_WARNS() << "no root folder id" << LL_ENDL; valid = false; } if (getLibraryRootFolderID().isNull()) { - llwarns << "no root folder id" << llendl; + LL_WARNS() << "no root folder id" << LL_ENDL; valid = false; } if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size()) { // ParentChild should be one larger because of the special entry for null uuid. - llinfos << "unexpected sizes: cat map size " << mCategoryMap.size() - << " parent/child " << mParentChildCategoryTree.size() << llendl; + LL_INFOS() << "unexpected sizes: cat map size " << mCategoryMap.size() + << " parent/child " << mParentChildCategoryTree.size() << LL_ENDL; valid = false; } S32 cat_lock = 0; @@ -3445,13 +3445,13 @@ bool LLInventoryModel::validate() const const LLViewerInventoryCategory *cat = cit->second; if (!cat) { - llwarns << "invalid cat" << llendl; + LL_WARNS() << "invalid cat" << LL_ENDL; valid = false; continue; } if (cat_id != cat->getUUID()) { - llwarns << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << llendl; + LL_WARNS() << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL; valid = false; } @@ -3459,9 +3459,9 @@ bool LLInventoryModel::validate() const { if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID()) { - llwarns << "cat " << cat_id << " has no parent, but is not root (" + LL_WARNS() << "cat " << cat_id << " has no parent, but is not root (" << getRootFolderID() << ") or library root (" - << getLibraryRootFolderID() << ")" << llendl; + << getLibraryRootFolderID() << ")" << LL_ENDL; } } cat_array_t* cats; @@ -3469,7 +3469,7 @@ bool LLInventoryModel::validate() const getDirectDescendentsOf(cat_id,cats,items); if (!cats || !items) { - llwarns << "invalid direct descendents for " << cat_id << llendl; + LL_WARNS() << "invalid direct descendents for " << cat_id << LL_ENDL; valid = false; continue; } @@ -3479,11 +3479,11 @@ bool LLInventoryModel::validate() const } else if (cats->size() + items->size() != cat->getDescendentCount()) { - llwarns << "invalid desc count for " << cat_id << " name [" << cat->getName() + LL_WARNS() << "invalid desc count for " << cat_id << " name [" << cat->getName() << "] parent " << cat->getParentUUID() << " cached " << cat->getDescendentCount() << " expected " << cats->size() << "+" << items->size() - << "=" << cats->size() +items->size() << llendl; + << "=" << cats->size() +items->size() << LL_ENDL; valid = false; } if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) @@ -3500,11 +3500,11 @@ bool LLInventoryModel::validate() const } for (S32 i = 0; isize(); i++) { - LLViewerInventoryItem *item = items->get(i); + LLViewerInventoryItem *item = items->at(i); if (!item) { - llwarns << "null item at index " << i << " for cat " << cat_id << llendl; + LL_WARNS() << "null item at index " << i << " for cat " << cat_id << LL_ENDL; valid = false; continue; } @@ -3513,9 +3513,9 @@ bool LLInventoryModel::validate() const if (item->getParentUUID() != cat_id) { - llwarns << "wrong parent for " << item_id << " found " + LL_WARNS() << "wrong parent for " << item_id << " found " << item->getParentUUID() << " expected " << cat_id - << llendl; + << LL_ENDL; valid = false; } @@ -3524,8 +3524,8 @@ bool LLInventoryModel::validate() const item_map_t::const_iterator it = mItemMap.find(item_id); if (it == mItemMap.end()) { - llwarns << "item " << item_id << " found as child of " - << cat_id << " but not in top level mItemMap" << llendl; + LL_WARNS() << "item " << item_id << " found as child of " + << cat_id << " but not in top level mItemMap" << LL_ENDL; valid = false; } else @@ -3533,8 +3533,8 @@ bool LLInventoryModel::validate() const LLViewerInventoryItem *top_item = it->second; if (top_item != item) { - llwarns << "item mismatch, item_id " << item_id - << " top level entry is different, uuid " << top_item->getUUID() << llendl; + LL_WARNS() << "item mismatch, item_id " << item_id + << " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL; } } @@ -3543,7 +3543,7 @@ bool LLInventoryModel::validate() const bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id); if (!found) { - llwarns << "unable to find topmost ancestor for " << item_id << llendl; + LL_WARNS() << "unable to find topmost ancestor for " << item_id << LL_ENDL; valid = false; } else @@ -3551,10 +3551,10 @@ bool LLInventoryModel::validate() const if (topmost_ancestor_id != getRootFolderID() && topmost_ancestor_id != getLibraryRootFolderID()) { - llwarns << "unrecognized top level ancestor for " << item_id + LL_WARNS() << "unrecognized top level ancestor for " << item_id << " got " << topmost_ancestor_id << " expected " << getRootFolderID() - << " or " << getLibraryRootFolderID() << llendl; + << " or " << getLibraryRootFolderID() << LL_ENDL; valid = false; } } @@ -3569,8 +3569,8 @@ bool LLInventoryModel::validate() const getDirectDescendentsOf(parent_id,cats,items); if (!cats) { - llwarns << "cat " << cat_id << " name [" << cat->getName() - << "] orphaned - no child cat array for alleged parent " << parent_id << llendl; + LL_WARNS() << "cat " << cat_id << " name [" << cat->getName() + << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL; valid = false; } else @@ -3578,7 +3578,7 @@ bool LLInventoryModel::validate() const bool found = false; for (S32 i = 0; isize(); i++) { - LLViewerInventoryCategory *kid_cat = cats->get(i); + LLViewerInventoryCategory *kid_cat = cats->at(i); if (kid_cat == cat) { found = true; @@ -3587,8 +3587,8 @@ bool LLInventoryModel::validate() const } if (!found) { - llwarns << "cat " << cat_id << " name [" << cat->getName() - << "] orphaned - not found in child cat array of alleged parent " << parent_id << llendl; + LL_WARNS() << "cat " << cat_id << " name [" << cat->getName() + << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL; } } } @@ -3600,14 +3600,14 @@ bool LLInventoryModel::validate() const LLViewerInventoryItem *item = iit->second; if (item->getUUID() != item_id) { - llwarns << "item_id " << item_id << " does not match " << item->getUUID() << llendl; + LL_WARNS() << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL; valid = false; } const LLUUID& parent_id = item->getParentUUID(); if (parent_id.isNull()) { - llwarns << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << llendl; + LL_WARNS() << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL; } else { @@ -3616,15 +3616,15 @@ bool LLInventoryModel::validate() const getDirectDescendentsOf(parent_id,cats,items); if (!items) { - llwarns << "item " << item_id << " name [" << item->getName() - << "] orphaned - alleged parent has no child items list " << parent_id << llendl; + LL_WARNS() << "item " << item_id << " name [" << item->getName() + << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL; } else { bool found = false; for (S32 i=0; isize(); ++i) { - if (items->get(i) == item) + if (items->at(i) == item) { found = true; break; @@ -3632,8 +3632,8 @@ bool LLInventoryModel::validate() const } if (!found) { - llwarns << "item " << item_id << " name [" << item->getName() - << "] orphaned - not found as child of alleged parent " << parent_id << llendl; + LL_WARNS() << "item " << item_id << " name [" << item->getName() + << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL; } } @@ -3648,30 +3648,30 @@ bool LLInventoryModel::validate() const // Linked-to UUID should have back reference to this link. if (!hasBacklinkInfo(link_id, target_id)) { - llwarns << "link " << item->getUUID() << " type " << item->getActualType() + LL_WARNS() << "link " << item->getUUID() << " type " << item->getActualType() << " missing backlink info at target_id " << target_id - << llendl; + << LL_ENDL; } // Links should have referents. if (item->getActualType() == LLAssetType::AT_LINK && !target_item) { - llwarns << "broken item link " << item->getName() << " id " << item->getUUID() << llendl; + LL_WARNS() << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL; } else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat) { - llwarns << "broken folder link " << item->getName() << " id " << item->getUUID() << llendl; + LL_WARNS() << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL; } if (target_item && target_item->getIsLinkType()) { - llwarns << "link " << item->getName() << " references a link item " - << target_item->getName() << " " << target_item->getUUID() << llendl; + LL_WARNS() << "link " << item->getName() << " references a link item " + << target_item->getName() << " " << target_item->getUUID() << LL_ENDL; } // Links should not have backlinks. std::pair range = mBacklinkMMap.equal_range(link_id); if (range.first != range.second) { - llwarns << "Link item " << item->getName() << " has backlinks!" << llendl; + LL_WARNS() << "Link item " << item->getName() << " has backlinks!" << LL_ENDL; } } else @@ -3685,7 +3685,7 @@ bool LLInventoryModel::validate() const LLViewerInventoryItem *link_item = getItem(link_id); if (!link_item || !link_item->getIsLinkType()) { - llwarns << "invalid backlink from target " << item->getName() << " to " << link_id << llendl; + LL_WARNS() << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL; } } } @@ -3693,19 +3693,19 @@ bool LLInventoryModel::validate() const if (cat_lock > 0 || item_lock > 0) { - llinfos << "Found locks on some categories: sub-cat arrays " - << cat_lock << ", item arrays " << item_lock << llendl; + LL_INFOS() << "Found locks on some categories: sub-cat arrays " + << cat_lock << ", item arrays " << item_lock << LL_ENDL; } if (desc_unknown_count != 0) { - llinfos << "Found " << desc_unknown_count << " cats with unknown descendent count" << llendl; + LL_INFOS() << "Found " << desc_unknown_count << " cats with unknown descendent count" << LL_ENDL; } if (version_unknown_count != 0) { - llinfos << "Found " << version_unknown_count << " cats with unknown version" << llendl; + LL_INFOS() << "Found " << version_unknown_count << " cats with unknown version" << LL_ENDL; } - llinfos << "Validate done, valid = " << (U32) valid << llendl; + LL_INFOS() << "Validate done, valid = " << (U32) valid << LL_ENDL; return valid; } -- cgit v1.2.3 From 01ad22ce197ba3bbf97ee396e163e5de529ad2e8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 15 May 2014 12:53:09 -0400 Subject: fix for bad merge --- indra/newview/llinventorymodel.cpp | 166 +++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 29b9c2b998..14ca0095ae 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2268,6 +2268,172 @@ void LLInventoryModel::buildParentChildMap() << cat->getName() << LL_ENDL; ++lost; lost_cats.push_back(cat); + } + } + if(lost) + { + LL_WARNS() << "Found " << lost << " lost categories." << LL_ENDL; + } + + // Do moves in a separate pass to make sure we've properly filed + // the FT_LOST_AND_FOUND category before we try to find its UUID. + for(i = 0; igetPreferredType(); + if(LLFolderType::FT_NONE == pref) + { + cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); + } + else if(LLFolderType::FT_ROOT_INVENTORY == pref) + { + // it's the root + cat->setParent(LLUUID::null); + } + else + { + // it's a protected folder. + cat->setParent(gInventory.getRootFolderID()); + } + // FIXME note that updateServer() fails with protected + // types, so this will not work as intended in that case. + cat->updateServer(TRUE); + catsp = getUnlockedCatArray(cat->getParentUUID()); + if(catsp) + { + catsp->push_back(cat); + } + else + { + LL_WARNS() << "Lost and found Not there!!" << LL_ENDL; + } + } + + const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null); + sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin(); + + + // Now the items. We allocated in the last step, so now all we + // have to do is iterate over the items and put them in the right + // place. + item_array_t items; + if(!mItemMap.empty()) + { + LLPointer item; + for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit) + { + item = (*iit).second; + items.push_back(item); + } + } + count = items.size(); + lost = 0; + uuid_vec_t lost_item_ids; + for(i = 0; i < count; ++i) + { + LLPointer item; + item = items.at(i); + itemsp = getUnlockedItemArray(item->getParentUUID()); + if(itemsp) + { + itemsp->push_back(item); + } + else + { + LL_INFOS() << "Lost item: " << item->getUUID() << " - " + << item->getName() << LL_ENDL; + ++lost; + // plop it into the lost & found. + // + item->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); + // move it later using a special message to move items. If + // we update server here, the client might crash. + //item->updateServer(); + lost_item_ids.push_back(item->getUUID()); + itemsp = getUnlockedItemArray(item->getParentUUID()); + if(itemsp) + { + itemsp->push_back(item); + } + else + { + LL_WARNS() << "Lost and found Not there!!" << LL_ENDL; + } + } + } + if(lost) + { + LL_WARNS() << "Found " << lost << " lost items." << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + BOOL start_new_message = TRUE; + const LLUUID lnf = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + for(uuid_vec_t::iterator it = lost_item_ids.begin() ; it < lost_item_ids.end(); ++it) + { + if(start_new_message) + { + start_new_message = FALSE; + msg->newMessageFast(_PREHASH_MoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOLFast(_PREHASH_Stamp, FALSE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, (*it)); + msg->addUUIDFast(_PREHASH_FolderID, lnf); + msg->addString("NewName", NULL); + if(msg->isSendFull(NULL)) + { + start_new_message = TRUE; + gAgent.sendReliableMessage(); + } + } + if(!start_new_message) + { + gAgent.sendReliableMessage(); + } + } + + const LLUUID &agent_inv_root_id = gInventory.getRootFolderID(); + if (agent_inv_root_id.notNull()) + { + cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id); + if(catsp) + { + // *HACK - fix root inventory folder + // some accounts has pbroken inventory root folders + + std::string name = "My Inventory"; + LLUUID prev_root_id = mRootFolderID; + for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(), + it_end = mParentChildCategoryTree.end(); it != it_end; ++it) + { + cat_array_t* cat_array = it->second; + for (cat_array_t::const_iterator cat_it = cat_array->begin(), + cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it) + { + LLPointer category = *cat_it; + + if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY) + continue; + if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) + { + if(category->getUUID()!=mRootFolderID) + { + LLUUID& new_inv_root_folder_id = const_cast(mRootFolderID); + new_inv_root_folder_id = category->getUUID(); + } + } + } + } + + // 'My Inventory', + // root of the agent's inv found. + // The inv tree is built. + mIsAgentInvUsable = true; + // notifyObservers() has been moved to // llstartup/idle_startup() after this func completes. // Allows some system categories to be created before -- cgit v1.2.3