@@ -42,10 +42,19 @@ const F32 MAX_ATTACHMENT_REQUEST_LIFETIME = 30.0F;
4242const F32 MIN_RETRY_REQUEST_TIME = 5 .0F ;
4343const F32 MAX_BAD_COF_TIME = 30 .0F ;
4444
45+ class LLRegisterAttachmentCallback : public LLRequestServerAppearanceUpdateOnDestroy
46+ {
47+ public:
48+ void fire (const LLUUID& item_id) override
49+ {
50+ LLAttachmentsMgr::instance ().onRegisterAttachmentComplete (item_id);
51+ LLRequestServerAppearanceUpdateOnDestroy::fire (item_id);
52+ }
53+ };
54+
4555LLAttachmentsMgr::LLAttachmentsMgr ():
4656 mAttachmentRequests(" attach" ,MIN_RETRY_REQUEST_TIME),
47- mDetachRequests(" detach" ,MIN_RETRY_REQUEST_TIME),
48- mQuestionableCOFLinks(" badcof" ,MAX_BAD_COF_TIME)
57+ mDetachRequests(" detach" ,MIN_RETRY_REQUEST_TIME)
4958{
5059}
5160
@@ -113,8 +122,6 @@ void LLAttachmentsMgr::onIdle()
113122
114123 expireOldDetachRequests ();
115124
116- checkInvalidCOFLinks ();
117-
118125 spamStatusInfo ();
119126}
120127
@@ -222,6 +229,11 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
222229{
223230 if (mRecentlyArrivedAttachments .size ())
224231 {
232+ if (!LLAppearanceMgr::instance ().getAttachmentInvLinkEnable ())
233+ {
234+ return ;
235+ }
236+
225237 // One or more attachments have arrived but have not yet been
226238 // processed for COF links
227239 if (mAttachmentRequests .empty ())
@@ -268,17 +280,49 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
268280 }
269281 if (ids_to_link.size ())
270282 {
271- LLPointer<LLInventoryCallback> cb = new LLRequestServerAppearanceUpdateOnDestroy ();
272- for (uuid_vec_t ::const_iterator uuid_it = ids_to_link.begin ();
273- uuid_it != ids_to_link.end (); ++uuid_it)
283+ LLPointer<LLInventoryCallback> cb = new LLRegisterAttachmentCallback ();
284+ for (const LLUUID& id_item: ids_to_link)
274285 {
275- LLAppearanceMgr::instance ().addCOFItemLink (*uuid_it, cb);
286+ if (std::find (mPendingAttachLinks .begin (), mPendingAttachLinks .end (), id_item) == mPendingAttachLinks .end ())
287+ {
288+ LLAppearanceMgr::instance ().addCOFItemLink (id_item, cb);
289+ mPendingAttachLinks .insert (id_item);
290+ }
276291 }
277292 }
278293 mRecentlyArrivedAttachments .clear ();
279294 }
280295}
281296
297+ bool LLAttachmentsMgr::getPendingAttachments (std::set<LLUUID>& ids) const
298+ {
299+ ids.clear ();
300+
301+ // Returns the combined set of attachments that are pending link creation and those that currently have an ongoing link creation process.
302+ set_union (mRecentlyArrivedAttachments .begin (), mRecentlyArrivedAttachments .end (), mPendingAttachLinks .begin (), mPendingAttachLinks .end (), std::inserter (ids, ids.begin ()));
303+
304+ return !ids.empty ();
305+ }
306+
307+ void LLAttachmentsMgr::clearPendingAttachmentLink (const LLUUID& idItem)
308+ {
309+ mPendingAttachLinks .erase (idItem);
310+ }
311+
312+ void LLAttachmentsMgr::onRegisterAttachmentComplete (const LLUUID& id_item_link)
313+ {
314+ if (const LLUUID& id_item = gInventory .getLinkedItemID (id_item_link); id_item != id_item_link)
315+ {
316+ clearPendingAttachmentLink (id_item);
317+
318+ // It may have been detached already in which case we should remove the COF link
319+ if ( isAgentAvatarValid () && !gAgentAvatarp ->isWearingAttachment (id_item) )
320+ {
321+ LLAppearanceMgr::instance ().removeCOFItemLinks (id_item);
322+ }
323+ }
324+ }
325+
282326LLAttachmentsMgr::LLItemRequestTimes::LLItemRequestTimes (const std::string& op_name, F32 timeout):
283327 mOpName(op_name),
284328 mTimeout(timeout)
@@ -407,6 +451,8 @@ void LLAttachmentsMgr::onDetachRequested(const LLUUID& inv_item_id)
407451
408452void LLAttachmentsMgr::onDetachCompleted (const LLUUID& inv_item_id)
409453{
454+ clearPendingAttachmentLink (inv_item_id);
455+
410456 LLTimer timer;
411457 LLInventoryItem *item = gInventory .getItem (inv_item_id);
412458 if (mDetachRequests .getTime (inv_item_id, timer))
@@ -428,10 +474,6 @@ void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id)
428474 {
429475 LL_DEBUGS (" Avatar" ) << " ATT detach on shutdown for " << (item ? item->getName () : " UNKNOWN" ) << " " << inv_item_id << LL_ENDL;
430476 }
431-
432- LL_DEBUGS (" Avatar" ) << " ATT detached item flagging as questionable for COF link checking "
433- << (item ? item->getName () : " UNKNOWN" ) << " id " << inv_item_id << LL_ENDL;
434- mQuestionableCOFLinks .addTime (inv_item_id);
435477}
436478
437479bool LLAttachmentsMgr::isAttachmentStateComplete () const
@@ -440,81 +482,8 @@ bool LLAttachmentsMgr::isAttachmentStateComplete() const
440482 && mAttachmentRequests .empty ()
441483 && mDetachRequests .empty ()
442484 && mRecentlyArrivedAttachments .empty ()
443- && mQuestionableCOFLinks .empty ();
444- }
445-
446- // Check for attachments that are (a) linked in COF and (b) not
447- // attached to the avatar. This is a rotten function to have to
448- // include, because it runs the risk of either repeatedly spamming out
449- // COF link removals if they're failing for some reason, or getting
450- // into a tug of war with some other sequence of events that's in the
451- // process of adding the attachment in question. However, it's needed
452- // because we have no definitive source of authority for what things
453- // are actually supposed to be attached. Scripts, run on the server
454- // side, can remove an attachment without our expecting it. If this
455- // happens to an attachment that's just been added, then the COF link
456- // creation may still be in flight, and we will have to delete the
457- // link after it shows up.
458- //
459- // Note that we only flag items for possible link removal if they have
460- // been previously detached. This means that an attachment failure
461- // will leave the link in the COF, where it will hopefully resolve
462- // correctly on relog.
463- //
464- // See related: MAINT-5070, MAINT-4409
465- //
466- void LLAttachmentsMgr::checkInvalidCOFLinks ()
467- {
468- if (!gInventory .isInventoryUsable () || mQuestionableCOFLinks .empty ())
469- {
470- return ;
471- }
472- LLInventoryModel::cat_array_t cat_array;
473- LLInventoryModel::item_array_t item_array;
474- gInventory .collectDescendents (LLAppearanceMgr::instance ().getCOF (),
475- cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
476- for (S32 i=0 ; i<item_array.size (); i++)
477- {
478- const LLViewerInventoryItem* inv_item = item_array.at (i).get ();
479- const LLUUID& item_id = inv_item->getLinkedUUID ();
480- if (inv_item->getType () == LLAssetType::AT_OBJECT)
481- {
482- LLTimer timer;
483- bool is_flagged_questionable = mQuestionableCOFLinks .getTime (item_id,timer);
484- bool is_wearing_attachment = isAgentAvatarValid () && gAgentAvatarp ->isWearingAttachment (item_id);
485- if (is_wearing_attachment && is_flagged_questionable)
486- {
487- LL_DEBUGS (" Avatar" ) << " ATT was flagged questionable but is now "
488- << (is_wearing_attachment ? " attached " : " " )
489- <<" removing flag after "
490- << timer.getElapsedTimeF32 () << " item "
491- << inv_item->getName () << " id " << item_id << LL_ENDL;
492- mQuestionableCOFLinks .removeTime (item_id);
493- }
494- }
495- }
496-
497- for (LLItemRequestTimes::iterator it = mQuestionableCOFLinks .begin ();
498- it != mQuestionableCOFLinks .end (); )
499- {
500- LLItemRequestTimes::iterator curr_it = it;
501- ++it;
502- const LLUUID& item_id = curr_it->first ;
503- LLViewerInventoryItem *inv_item = gInventory .getItem (item_id);
504- if (curr_it->second .getElapsedTimeF32 () > MAX_BAD_COF_TIME)
505- {
506- if (LLAppearanceMgr::instance ().isLinkedInCOF (item_id))
507- {
508- LL_DEBUGS (" Avatar" ) << " ATT Linked in COF but not attached or requested, deleting link after "
509- << curr_it->second .getElapsedTimeF32 () << " seconds for "
510- << (inv_item ? inv_item->getName () : " UNKNOWN" ) << " id " << item_id << LL_ENDL;
511- LLAppearanceMgr::instance ().removeCOFItemLinks (item_id);
512- }
513- mQuestionableCOFLinks .erase (curr_it);
514- continue ;
515- }
516- }
517- }
485+ && mPendingAttachLinks .empty ();
486+ }
518487
519488void LLAttachmentsMgr::spamStatusInfo ()
520489{
0 commit comments