Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
318 changes: 166 additions & 152 deletions indra/llinventory/llinventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
<key> asset_id </key>
<uuid> acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 </uuid>
<key> perms </key>
<integer> 8 </integer>
<key>service</key>
<integer> 3 </integer>
<key>version</key>
<integer> 1 </key>
*/
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<LLAssetType::EType>(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<LLAssetType::EType>(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<LLInventoryType::EType>(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<LLInventoryType::EType>(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:
<key> asset_id </key>
<uuid> acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 </uuid>
<key> perms </key>
<integer> 8 </integer>
<key>service</key>
<integer> 3 </integer>
<key>version</key>
<integer> 1 </key>
*/
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;
}
}

Expand Down
18 changes: 18 additions & 0 deletions indra/newview/llaisapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions indra/newview/llaisapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -158,6 +159,7 @@ class AISUpdate
uuid_list_t mCategoryIds;
bool mFetch;
S32 mFetchDepth;
bool mUseTimeout;
LLTimer mTaskTimer;
static LLTimer sBatchTimer;
static U32 sBatchFrameCount;
Expand Down
Loading
Loading