diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index f126accfb86..cd5e97714c7 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -1002,171 +1002,185 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) end = sd.endMap(); for (i = sd.beginMap(); i != end; ++i) { - if (i->first == INV_ITEM_ID_LABEL) - { - mUUID = i->second; - continue; - } - - if (i->first == INV_PARENT_ID_LABEL) - { - mParentUUID = i->second; - continue; - } + // Use string length as a fast pre-filter before string comparison + const std::string& key = i->first; + const LLSD& value = i->second; + const size_t key_len = key.length(); - if (i->first == INV_THUMBNAIL_LABEL) + switch (key_len) { - const LLSD &thumbnail_map = i->second; - if (thumbnail_map.has(INV_ASSET_ID_LABEL)) - { - mThumbnailUUID = thumbnail_map[INV_ASSET_ID_LABEL]; - } - /* Example: - asset_id - acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 - perms - 8 - service - 3 - version - 1 - */ - continue; - } - - if (i->first == INV_THUMBNAIL_ID_LABEL) - { - mThumbnailUUID = i->second.asUUID(); - continue; - } - - if (i->first == INV_FAVORITE_LABEL) - { - const LLSD& favorite_map = i->second; - if (favorite_map.has(INV_TOGGLED_LABEL)) - { - mFavorite = favorite_map[INV_TOGGLED_LABEL].asBoolean(); - } - continue; - } - - if (i->first == INV_PERMISSIONS_LABEL) - { - mPermissions.importLLSD(i->second); - continue; - } - - if (i->first == INV_SALE_INFO_LABEL) - { - // Sale info used to contain next owner perm. It is now in - // the permissions. Thus, we read that out, and fix legacy - // objects. It's possible this op would fail, but it - // should pick up the vast majority of the tasks. - bool has_perm_mask = false; - U32 perm_mask = 0; - if (!mSaleInfo.fromLLSD(i->second, has_perm_mask, perm_mask)) - { - return false; - } - if (has_perm_mask) - { - if (perm_mask == PERM_NONE) + case 4: // "name", "desc", "type" + if (key == INV_NAME_LABEL) // "name" { - perm_mask = mPermissions.getMaskOwner(); + mName = value.asString(); + LLStringUtil::replaceNonstandardASCII(mName, ' '); + LLStringUtil::replaceChar(mName, '|', ' '); + continue; } - // fair use fix. - if (!(perm_mask & PERM_COPY)) + if (key == INV_DESC_LABEL) // "desc" { - perm_mask |= PERM_TRANSFER; + mDescription = value.asString(); + LLStringUtil::replaceNonstandardASCII(mDescription, ' '); + continue; } - mPermissions.setMaskNext(perm_mask); - } - continue; - } - - if (i->first == INV_SHADOW_ID_LABEL) - { - mAssetUUID = i->second; - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.decrypt(mAssetUUID.mData, UUID_BYTES); - continue; - } - - if (i->first == INV_ASSET_ID_LABEL) - { - mAssetUUID = i->second; - continue; - } + if (key == INV_ASSET_TYPE_LABEL) // "type" + { + if (value.isString()) + { + mType = LLAssetType::lookup(value.asStringRef().c_str()); + } + else if (value.isInteger()) + { + S8 type = (U8)value.asInteger(); + mType = static_cast(type); + } + continue; + } + break; - if (i->first == INV_LINKED_ID_LABEL) - { - mAssetUUID = i->second; - continue; - } + case 5: // "flags" + if (key == INV_FLAGS_LABEL) + { + if (value.isBinary()) + { + mFlags = ll_U32_from_sd(value); + } + else if (value.isInteger()) + { + mFlags = value.asInteger(); + } + continue; + } + break; - if (i->first == INV_ASSET_TYPE_LABEL) - { - LLSD const &label = i->second; - if (label.isString()) - { - mType = LLAssetType::lookup(label.asStringRef().c_str()); - } - else if (label.isInteger()) - { - S8 type = (U8) label.asInteger(); - mType = static_cast(type); - } - continue; - } + case 7: // "item_id" + if (key == INV_ITEM_ID_LABEL) + { + mUUID = value; + continue; + } + break; - if (i->first == INV_INVENTORY_TYPE_LABEL) - { - LLSD const &label = i->second; - if (label.isString()) - { - mInventoryType = LLInventoryType::lookup(label.asStringRef().c_str()); - } - else if (label.isInteger()) - { - S8 type = (U8) label.asInteger(); - mInventoryType = static_cast(type); - } - continue; - } + case 8: // "asset_id", "inv_type" + if (key == INV_ASSET_ID_LABEL) + { + mAssetUUID = value; + continue; + } + if (key == INV_INVENTORY_TYPE_LABEL) // "inv_type" + { + if (value.isString()) + { + mInventoryType = LLInventoryType::lookup(value.asStringRef().c_str()); + } + else if (value.isInteger()) + { + S8 type = (U8)value.asInteger(); + mInventoryType = static_cast(type); + } + continue; + } + if (key == INV_FAVORITE_LABEL) // "favorite" + { + if (value.has(INV_TOGGLED_LABEL)) + { + mFavorite = value[INV_TOGGLED_LABEL].asBoolean(); + } + continue; + } + break; - if (i->first == INV_FLAGS_LABEL) - { - LLSD const &label = i->second; - if (label.isBinary()) - { - mFlags = ll_U32_from_sd(label); - } - else if (label.isInteger()) - { - mFlags = label.asInteger(); - } - continue; - } + case 9: // "parent_id", "shadow_id", "linked_id", "sale_info", "thumbnail" + if (key == INV_PARENT_ID_LABEL) + { + mParentUUID = value; + continue; + } + if (key == INV_SHADOW_ID_LABEL) + { + mAssetUUID = value; + LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); + cipher.decrypt(mAssetUUID.mData, UUID_BYTES); + continue; + } + if (key == INV_LINKED_ID_LABEL) + { + mAssetUUID = value; + continue; + } + if (key == INV_SALE_INFO_LABEL) + { + // Sale info used to contain next owner perm. It is now in + // the permissions. Thus, we read that out, and fix legacy + // objects. It's possible this op would fail, but it + // should pick up the vast majority of the tasks. + bool has_perm_mask = false; + U32 perm_mask = 0; + if (!mSaleInfo.fromLLSD(value, has_perm_mask, perm_mask)) + { + return false; + } + if (has_perm_mask) + { + if (perm_mask == PERM_NONE) + { + perm_mask = mPermissions.getMaskOwner(); + } + // fair use fix. + if (!(perm_mask & PERM_COPY)) + { + perm_mask |= PERM_TRANSFER; + } + mPermissions.setMaskNext(perm_mask); + } + continue; + } + if (key == INV_THUMBNAIL_LABEL) + { + if (value.has(INV_ASSET_ID_LABEL)) + { + mThumbnailUUID = value[INV_ASSET_ID_LABEL]; + } + /* Example: + asset_id + acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 + perms + 8 + service + 3 + version + 1 + */ + continue; + } + break; + case 10: // "created_at" + if (key == INV_CREATION_DATE_LABEL) + { + mCreationDate = value.asInteger(); + continue; + } + break; - if (i->first == INV_NAME_LABEL) - { - mName = i->second.asString(); - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - continue; - } + case 11: // "permissions" + if (key == INV_PERMISSIONS_LABEL) + { + mPermissions.importLLSD(value); + continue; + } + break; - if (i->first == INV_DESC_LABEL) - { - mDescription = i->second.asString(); - LLStringUtil::replaceNonstandardASCII(mDescription, ' '); - continue; - } + case 12: // "thumbnail_id" + if (key == INV_THUMBNAIL_ID_LABEL) + { + mThumbnailUUID = value.asUUID(); + continue; + } + break; - if (i->first == INV_CREATION_DATE_LABEL) - { - mCreationDate = i->second.asInteger(); - continue; + default: + // Unknown field - skip + break; } } diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 1c5530916f3..f0b7457fa23 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1039,6 +1039,19 @@ AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& mFetchDepth = request_body["depth"].asInteger(); } + // Some tasks are time sensitive, don't wait for them. + // Like FETCHCOF which happens on load and is needed for outfit + // loading. + // FETCHCATEGORYLINKS is used for wearing outfits and fetching + // a user selected outfit or for following an outfit link in COF. + // Other tasks, like FETCHCATEGORYSUBSET are general background + // fetches and can safely wait. + // Do count 'time sensitive' tasks in batch timer. + mUseTimeout = + type != AISAPI::UPDATECATEGORY + && type != AISAPI::UPDATEITEM + && type != AISAPI::FETCHCOF + && type != AISAPI::FETCHCATEGORYLINKS; mTaskTimer.setTimerExpirySec(AIS_TASK_EXPIRY_SECONDS); mTaskTimer.start(); @@ -1069,6 +1082,11 @@ void AISUpdate::clearParseResults() void AISUpdate::checkTimeout() { + if (!mUseTimeout) + { + // Priority task, don't wait. + return; + } if (mTaskTimer.hasExpired() || sBatchTimer.hasExpired()) { // If we are taking too long, don't starve other tasks, diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 1dab0dd1f91..b31768d4264 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -109,6 +109,7 @@ class AISAPI class AISUpdate { + LOG_CLASS(AISUpdate); public: AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body); void parseUpdate(const LLSD& update); @@ -158,6 +159,7 @@ class AISUpdate uuid_list_t mCategoryIds; bool mFetch; S32 mFetchDepth; + bool mUseTimeout; LLTimer mTaskTimer; static LLTimer sBatchTimer; static U32 sBatchFrameCount; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 8b9aad46416..c72f1d2c358 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2719,10 +2719,11 @@ bool LLInventoryModel::loadSkeleton( for(LLSD::array_const_iterator it = options.beginArray(), end = options.endArray(); it != end; ++it) { - LLSD name = (*it)["name"]; - LLSD folder_id = (*it)["folder_id"]; - LLSD parent_id = (*it)["parent_id"]; - LLSD version = (*it)["version"]; + const LLSD &folder = *it; + const LLSD &name = folder["name"]; + const LLSD &folder_id = folder["folder_id"]; + const LLSD &parent_id = folder["parent_id"]; + const LLSD &version = folder["version"]; if(name.isDefined() && folder_id.isDefined() && parent_id.isDefined() @@ -2736,7 +2737,7 @@ bool LLInventoryModel::loadSkeleton( cat->setParent(parent_id.asUUID()); LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLSD type_default = (*it)["type_default"]; + const LLSD &type_default = folder["type_default"]; if(type_default.isDefined()) { preferred_type = (LLFolderType::EType)type_default.asInteger(); @@ -3454,6 +3455,8 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, const LLSD& llsd_cats = inventory["categories"]; if (llsd_cats.isArray()) { + size_t cats_count = llsd_cats.size(); + categories.reserve(cats_count); LLSD::array_const_iterator iter = llsd_cats.beginArray(); LLSD::array_const_iterator end = llsd_cats.endArray(); for (; iter != end; ++iter) @@ -3472,6 +3475,8 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, const LLSD& llsd_items = inventory["items"]; if (llsd_items.isArray()) { + size_t items_count = llsd_items.size(); + items.reserve(items_count); LLSD::array_const_iterator iter = llsd_items.beginArray(); LLSD::array_const_iterator end = llsd_items.endArray(); for (; iter != end; ++iter)